master
c 889 lines 27.3 KB
Raw
1 /*
2 * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "qemu/osdep.h"
19 #include "iclass.h"
20 #include "attribs.h"
21 #include "genptr.h"
22 #include "decode.h"
23 #include "insn.h"
24 #include "printinsn.h"
25 #include "mmvec/decode_ext_mmvec.h"
26
27 #define fZXTN(N, M, VAL) ((VAL) & ((1LL << (N)) - 1))
28
29 /*
30 * Certain operand types represent a non-contiguous set of values.
31 * For example, the compound compare-and-jump instruction can only access
32 * registers R0-R7 and R16-23.
33 * This table represents the mapping from the encoding to the actual values.
34 */
35
36 #define DEF_REGMAP(NAME, ELEMENTS, ...) \
37 static const unsigned int DECODE_REGISTER_##NAME[ELEMENTS] = \
38 { __VA_ARGS__ };
39 /* Name Num Table */
40 DEF_REGMAP(R_16, 16, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23)
41 DEF_REGMAP(R__8, 8, 0, 2, 4, 6, 16, 18, 20, 22)
42 DEF_REGMAP(R_8, 8, 0, 1, 2, 3, 4, 5, 6, 7)
43
44 #define DECODE_MAPPED_REG(OPNUM, NAME) \
45 insn->regno[OPNUM] = DECODE_REGISTER_##NAME[insn->regno[OPNUM]];
46
47 /* Helper functions for decode_*_generated.c.inc */
48 #define DECODE_MAPPED(NAME) \
49 static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) \
50 { \
51 return DECODE_REGISTER_##NAME[x]; \
52 }
53 DECODE_MAPPED(R_16)
54 DECODE_MAPPED(R_8)
55 DECODE_MAPPED(R__8)
56
57 /* Helper function for decodetree_trans_funcs_generated.c.inc */
58 static int shift_left(DisasContext *ctx, int x, int n, int immno)
59 {
60 int ret = x;
61 Insn *insn = ctx->insn;
62 if (!insn->extension_valid ||
63 insn->which_extended != immno) {
64 ret <<= n;
65 }
66 return ret;
67 }
68
69 /* Include the generated decoder for 32 bit insn */
70 #include "decode_normal_generated.c.inc"
71 #include "decode_hvx_generated.c.inc"
72
73 /* Include the generated decoder for 16 bit insn */
74 #include "decode_subinsn_a_generated.c.inc"
75 #include "decode_subinsn_l1_generated.c.inc"
76 #include "decode_subinsn_l2_generated.c.inc"
77 #include "decode_subinsn_s1_generated.c.inc"
78 #include "decode_subinsn_s2_generated.c.inc"
79
80 /* Include the generated helpers for the decoder */
81 #include "decodetree_trans_funcs_generated.c.inc"
82
83 void decode_send_insn_to(Packet *packet, int start, int newloc)
84 {
85 Insn tmpinsn;
86 int direction;
87 int i;
88 if (start == newloc) {
89 return;
90 }
91 if (start < newloc) {
92 /* Move towards end */
93 direction = 1;
94 } else {
95 /* move towards beginning */
96 direction = -1;
97 }
98 for (i = start; i != newloc; i += direction) {
99 tmpinsn = packet->insn[i];
100 packet->insn[i] = packet->insn[i + direction];
101 packet->insn[i + direction] = tmpinsn;
102 }
103 }
104
105 /* Fill newvalue registers with the correct regno */
106 static void
107 decode_fill_newvalue_regno(Packet *packet)
108 {
109 int i, use_regidx, offset, def_idx, dst_idx;
110
111 for (i = 1; i < packet->num_insns; i++) {
112 if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) &&
113 !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) {
114
115 g_assert(packet->insn[i].new_read_idx != -1);
116 use_regidx = packet->insn[i].new_read_idx;
117
118 /*
119 * What's encoded at the N-field is the offset to who's producing
120 * the value. Shift off the LSB which indicates odd/even register,
121 * then walk backwards and skip over the constant extenders.
122 */
123 offset = packet->insn[i].regno[use_regidx] >> 1;
124 def_idx = i - offset;
125 for (int j = 0; j < offset; j++) {
126 if (GET_ATTRIB(packet->insn[i - j - 1].opcode, A_IT_EXTENDER)) {
127 def_idx--;
128 }
129 }
130
131 /*
132 * Check for a badly encoded N-field which points to an instruction
133 * out-of-range
134 */
135 g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1))));
136
137 /* Now patch up the consumer with the register number */
138 g_assert(packet->insn[def_idx].dest_idx != -1);
139 dst_idx = packet->insn[def_idx].dest_idx;
140 packet->insn[i].regno[use_regidx] =
141 packet->insn[def_idx].regno[dst_idx];
142 /*
143 * We need to remember who produces this value to later
144 * check if it was dynamically cancelled
145 */
146 packet->insn[i].new_value_producer_slot =
147 packet->insn[def_idx].slot;
148 }
149 }
150 }
151
152 /* Split CJ into a compare and a jump */
153 static void decode_split_cmpjump(Packet *pkt)
154 {
155 int last, i;
156 int numinsns = pkt->num_insns;
157
158 /*
159 * First, split all compare-jumps.
160 * The compare is sent to the end as a new instruction.
161 * Do it this way so we don't reorder dual jumps. Those need to stay in
162 * original order.
163 */
164 for (i = 0; i < numinsns; i++) {
165 /* It's a cmp-jump */
166 if (GET_ATTRIB(pkt->insn[i].opcode, A_NEWCMPJUMP)) {
167 last = pkt->num_insns;
168 pkt->insn[last] = pkt->insn[i]; /* copy the instruction */
169 pkt->insn[last].part1 = true; /* last insn does the CMP */
170 pkt->insn[i].part1 = false; /* existing insn does the JUMP */
171 pkt->num_insns++;
172 }
173 }
174
175 /* Now re-shuffle all the compares back to the beginning */
176 for (i = 0; i < pkt->num_insns; i++) {
177 if (pkt->insn[i].part1) {
178 decode_send_insn_to(pkt, i, 0);
179 }
180 }
181 }
182
183 static bool decode_opcode_can_jump(int opcode)
184 {
185 if ((GET_ATTRIB(opcode, A_JUMP)) ||
186 (GET_ATTRIB(opcode, A_CALL)) ||
187 (opcode == J2_trap0) ||
188 (opcode == J2_trap1) ||
189 (opcode == J2_rte) ||
190 (opcode == J2_pause)) {
191 /* Exception to A_JUMP attribute */
192 if (opcode == J4_hintjumpr) {
193 return false;
194 }
195 return true;
196 }
197
198 return false;
199 }
200
201 static bool decode_opcode_ends_loop(int opcode)
202 {
203 return GET_ATTRIB(opcode, A_HWLOOP0_END) ||
204 GET_ATTRIB(opcode, A_HWLOOP1_END);
205 }
206
207 /* Set the is_* fields in each instruction */
208 static void decode_set_insn_attr_fields(Packet *pkt)
209 {
210 int i;
211 int numinsns = pkt->num_insns;
212 uint16_t opcode;
213
214 pkt->pkt_has_cof = false;
215 pkt->pkt_has_multi_cof = false;
216 pkt->pkt_has_endloop = false;
217 pkt->pkt_has_dczeroa = false;
218
219 for (i = 0; i < numinsns; i++) {
220 opcode = pkt->insn[i].opcode;
221 if (pkt->insn[i].part1) {
222 continue; /* Skip compare of cmp-jumps */
223 }
224
225 if (GET_ATTRIB(opcode, A_DCZEROA)) {
226 pkt->pkt_has_dczeroa = true;
227 }
228
229 if (GET_ATTRIB(opcode, A_STORE)) {
230 if (GET_ATTRIB(opcode, A_SCALAR_STORE) &&
231 !GET_ATTRIB(opcode, A_MEMSIZE_0B)) {
232 if (pkt->insn[i].slot == 0) {
233 pkt->pkt_has_scalar_store_s0 = true;
234 } else {
235 pkt->pkt_has_scalar_store_s1 = true;
236 }
237 }
238 }
239
240 if (decode_opcode_can_jump(opcode)) {
241 if (pkt->pkt_has_cof) {
242 pkt->pkt_has_multi_cof = true;
243 }
244 pkt->pkt_has_cof = true;
245 }
246
247 pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
248
249 pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
250
251 if (pkt->pkt_has_endloop) {
252 if (pkt->pkt_has_cof) {
253 pkt->pkt_has_multi_cof = true;
254 }
255 pkt->pkt_has_cof = true;
256 }
257 }
258 }
259
260 /*
261 * Shuffle for execution
262 * Move stores to end (in same order as encoding)
263 * Move compares to beginning (for use by .new insns)
264 */
265 static void decode_shuffle_for_execution(Packet *packet)
266 {
267 bool changed = false;
268 int i;
269 bool flag; /* flag means we've seen a non-memory instruction */
270 int n_mems;
271 int last_insn = packet->num_insns - 1;
272
273 /*
274 * Skip end loops, somehow an end loop is getting in and messing
275 * up the order
276 */
277 if (decode_opcode_ends_loop(packet->insn[last_insn].opcode)) {
278 last_insn--;
279 }
280
281 do {
282 changed = false;
283 /*
284 * Stores go last, must not reorder.
285 * Cannot shuffle stores past loads, either.
286 * Iterate backwards. If we see a non-memory instruction,
287 * then a store, shuffle the store to the front. Don't shuffle
288 * stores wrt each other or a load.
289 */
290 for (flag = false, n_mems = 0, i = last_insn; i >= 0; i--) {
291 int opcode = packet->insn[i].opcode;
292
293 if (flag && GET_ATTRIB(opcode, A_STORE)) {
294 decode_send_insn_to(packet, i, last_insn - n_mems);
295 n_mems++;
296 changed = true;
297 } else if (GET_ATTRIB(opcode, A_STORE)) {
298 n_mems++;
299 } else if (GET_ATTRIB(opcode, A_LOAD)) {
300 /*
301 * Don't set flag, since we don't want to shuffle a
302 * store past a load
303 */
304 n_mems++;
305 } else if (GET_ATTRIB(opcode, A_DOTNEWVALUE)) {
306 /*
307 * Don't set flag, since we don't want to shuffle past
308 * a .new value
309 */
310 } else {
311 flag = true;
312 }
313 }
314
315 if (changed) {
316 continue;
317 }
318 /* Compares go first, may be reordered wrt each other */
319 for (flag = false, i = 0; i < last_insn + 1; i++) {
320 int opcode = packet->insn[i].opcode;
321
322 if (packet->insn[i].has_pred_dest &&
323 GET_ATTRIB(opcode, A_STORE) == 0) {
324 /* This should be a compare (not a store conditional) */
325 if (flag) {
326 decode_send_insn_to(packet, i, 0);
327 changed = true;
328 continue;
329 }
330 } else if (GET_ATTRIB(opcode, A_IMPLICIT_WRITES_P3) &&
331 !decode_opcode_ends_loop(packet->insn[i].opcode)) {
332 /*
333 * spNloop instruction
334 * Don't reorder endloops; they are not valid for .new uses,
335 * and we want to match HW
336 */
337 if (flag) {
338 decode_send_insn_to(packet, i, 0);
339 changed = true;
340 continue;
341 }
342 } else if (GET_ATTRIB(opcode, A_IMPLICIT_WRITES_P0) &&
343 !GET_ATTRIB(opcode, A_NEWCMPJUMP)) {
344 if (flag) {
345 decode_send_insn_to(packet, i, 0);
346 changed = true;
347 continue;
348 }
349 } else {
350 flag = true;
351 }
352 }
353 if (changed) {
354 continue;
355 }
356 } while (changed);
357
358 /*
359 * If we have a .new register compare/branch, move that to the very
360 * very end, past stores
361 */
362 for (i = 0; i < last_insn; i++) {
363 if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE)) {
364 decode_send_insn_to(packet, i, last_insn);
365 break;
366 }
367 }
368 /*
369 * And at the very very very end, move any RTE's, since they update
370 * user/supervisor mode.
371 */
372 #if !defined(CONFIG_USER_ONLY)
373 for (i = 0; i < last_insn; i++) {
374 if (packet->insn[i].opcode == J2_rte) {
375 decode_send_insn_to(packet, i, last_insn);
376 break;
377 }
378 }
379 #endif
380 }
381
382 static void
383 apply_extender(Packet *pkt, int i, uint32_t extender)
384 {
385 int immed_num;
386 uint32_t base_immed;
387
388 immed_num = pkt->insn[i].which_extended;
389 base_immed = pkt->insn[i].immed[immed_num];
390
391 pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
392 }
393
394 static void decode_apply_extenders(Packet *packet)
395 {
396 int i;
397 for (i = 0; i < packet->num_insns; i++) {
398 if (GET_ATTRIB(packet->insn[i].opcode, A_IT_EXTENDER)) {
399 packet->insn[i + 1].extension_valid = true;
400 apply_extender(packet, i + 1, packet->insn[i].immed[0]);
401 }
402 }
403 }
404
405 static void decode_remove_extenders(Packet *packet)
406 {
407 int i, j;
408 for (i = 0; i < packet->num_insns; i++) {
409 if (GET_ATTRIB(packet->insn[i].opcode, A_IT_EXTENDER)) {
410 /* Remove this one by moving the remaining instructions down */
411 for (j = i;
412 (j < packet->num_insns - 1) && (j < INSTRUCTIONS_MAX - 1);
413 j++) {
414 packet->insn[j] = packet->insn[j + 1];
415 }
416 packet->num_insns--;
417 }
418 }
419 }
420
421 static SlotMask get_valid_slots(const Packet *pkt, unsigned int slot)
422 {
423 if (GET_ATTRIB(pkt->insn[slot].opcode, A_EXTENSION)) {
424 return mmvec_ext_decode_find_iclass_slots(pkt->insn[slot].opcode);
425 } else {
426 return find_iclass_slots(pkt->insn[slot].opcode,
427 pkt->insn[slot].iclass);
428 }
429 }
430
431 /*
432 * Section 10.3 of the Hexagon V73 Programmer's Reference Manual
433 *
434 * A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
435 * The sub-instructions that comprise a duplex are encoded as 13-bit fields
436 * in the duplex.
437 *
438 * Per table 10-4, the 4-bit duplex iclass is encoded in bits 31:29, 13
439 */
440 static uint32_t get_duplex_iclass(uint32_t encoding)
441 {
442 uint32_t iclass = extract32(encoding, 13, 1);
443 iclass = deposit32(iclass, 1, 3, extract32(encoding, 29, 3));
444 return iclass;
445 }
446
447 /*
448 * Per table 10-5, the duplex ICLASS field values that specify the group of
449 * each sub-instruction in a duplex
450 *
451 * This table points to the decode instruction for each entry in the table
452 */
453 typedef bool (*subinsn_decode_func)(DisasContext *ctx, uint16_t insn);
454 typedef struct {
455 subinsn_decode_func decode_slot0_subinsn;
456 subinsn_decode_func decode_slot1_subinsn;
457 } subinsn_decode_groups;
458
459 static const subinsn_decode_groups decode_groups[16] = {
460 [0x0] = { decode_subinsn_l1, decode_subinsn_l1 },
461 [0x1] = { decode_subinsn_l2, decode_subinsn_l1 },
462 [0x2] = { decode_subinsn_l2, decode_subinsn_l2 },
463 [0x3] = { decode_subinsn_a, decode_subinsn_a },
464 [0x4] = { decode_subinsn_l1, decode_subinsn_a },
465 [0x5] = { decode_subinsn_l2, decode_subinsn_a },
466 [0x6] = { decode_subinsn_s1, decode_subinsn_a },
467 [0x7] = { decode_subinsn_s2, decode_subinsn_a },
468 [0x8] = { decode_subinsn_s1, decode_subinsn_l1 },
469 [0x9] = { decode_subinsn_s1, decode_subinsn_l2 },
470 [0xa] = { decode_subinsn_s1, decode_subinsn_s1 },
471 [0xb] = { decode_subinsn_s2, decode_subinsn_s1 },
472 [0xc] = { decode_subinsn_s2, decode_subinsn_l1 },
473 [0xd] = { decode_subinsn_s2, decode_subinsn_l2 },
474 [0xe] = { decode_subinsn_s2, decode_subinsn_s2 },
475 [0xf] = { NULL, NULL }, /* Reserved */
476 };
477
478 static uint16_t get_slot0_subinsn(uint32_t encoding)
479 {
480 return extract32(encoding, 0, 13);
481 }
482
483 static uint16_t get_slot1_subinsn(uint32_t encoding)
484 {
485 return extract32(encoding, 16, 13);
486 }
487
488 static unsigned int
489 decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
490 {
491 if (parse_bits(encoding) != 0) {
492 if (decode_normal(ctx, encoding) ||
493 decode_hvx(ctx, encoding)) {
494 insn->generate = opcode_genptr[insn->opcode];
495 insn->iclass = iclass_bits(encoding);
496 return 1;
497 }
498 /* Invalid non-duplex encoding */
499 return 0;
500 } else {
501 uint32_t iclass = get_duplex_iclass(encoding);
502 unsigned int slot0_subinsn = get_slot0_subinsn(encoding);
503 unsigned int slot1_subinsn = get_slot1_subinsn(encoding);
504 subinsn_decode_func decode_slot0_subinsn =
505 decode_groups[iclass].decode_slot0_subinsn;
506 subinsn_decode_func decode_slot1_subinsn =
507 decode_groups[iclass].decode_slot1_subinsn;
508
509 /* The slot1 subinsn needs to be in the packet first */
510 if (decode_slot1_subinsn(ctx, slot1_subinsn)) {
511 insn->generate = opcode_genptr[insn->opcode];
512 insn->iclass = iclass_bits(encoding);
513 ctx->insn = ++insn;
514 if (decode_slot0_subinsn(ctx, slot0_subinsn)) {
515 insn->generate = opcode_genptr[insn->opcode];
516 insn->iclass = iclass_bits(encoding);
517 return 2;
518 }
519 /*
520 * Slot0 decode failed after slot1 succeeded. This is an invalid
521 * duplex encoding (both sub-instructions must be valid).
522 */
523 ctx->insn = --insn;
524 }
525 /* Invalid duplex encoding - return 0 to signal failure */
526 return 0;
527 }
528 }
529
530 static void decode_add_endloop_insn(Insn *insn, int loopnum)
531 {
532 if (loopnum == 10) {
533 insn->opcode = J2_endloop01;
534 insn->generate = opcode_genptr[J2_endloop01];
535 } else if (loopnum == 1) {
536 insn->opcode = J2_endloop1;
537 insn->generate = opcode_genptr[J2_endloop1];
538 } else if (loopnum == 0) {
539 insn->opcode = J2_endloop0;
540 insn->generate = opcode_genptr[J2_endloop0];
541 } else {
542 g_assert_not_reached();
543 }
544 }
545
546 static bool decode_parsebits_is_loopend(uint32_t encoding32)
547 {
548 uint32_t bits = parse_bits(encoding32);
549 return bits == 0x2;
550 }
551
552 /*
553 * Check that the packet's instructions can be grouped into slots: walk them
554 * in encoding order handing out slots in strictly decreasing order, and fail
555 * if an instruction has no valid slot at or below the running slot. Two
556 * instructions may legally share a slot, so this does not require unique
557 * slots, only that every instruction fits.
558 */
559 static bool has_valid_slot_assignment(Packet *pkt)
560 {
561 int i;
562 int slot = 3;
563
564 for (i = 0; i < pkt->num_insns; i++) {
565 SlotMask valid_slots;
566 if (decode_opcode_ends_loop(pkt->insn[i].opcode)) {
567 /* We overload slot 0 for endloop. */
568 continue;
569 }
570 if (slot < 0) {
571 return false;
572 }
573 valid_slots = get_valid_slots(pkt, i);
574 while (!(valid_slots & (1 << slot))) {
575 if (slot <= 0) {
576 return false;
577 }
578 slot--;
579 }
580 slot--;
581 }
582 return true;
583 }
584
585 static bool
586 decode_set_slot_number(Packet *pkt)
587 {
588 int slot;
589 int i;
590 bool hit_mem_insn = false;
591 bool hit_duplex = false;
592 bool slot0_found = false;
593 bool slot1_found = false;
594 int slot1_iidx = 0;
595
596 /*
597 * The slots are encoded in reverse order
598 * For each instruction, count down until you find a suitable slot
599 */
600 for (i = 0, slot = 3; i < pkt->num_insns; i++) {
601 SlotMask valid_slots = get_valid_slots(pkt, i);
602
603 while (!(valid_slots & (1 << slot))) {
604 slot--;
605 }
606 pkt->insn[i].slot = slot;
607 if (slot) {
608 /* I've assigned the slot, now decrement it for the next insn */
609 slot--;
610 }
611 }
612
613 /* Fix the exceptions - mem insns to slot 0,1 */
614 for (i = pkt->num_insns - 1; i >= 0; i--) {
615 /* First memory instruction always goes to slot 0 */
616 if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
617 GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
618 !hit_mem_insn) {
619 hit_mem_insn = true;
620 pkt->insn[i].slot = 0;
621 continue;
622 }
623
624 /* Next memory instruction always goes to slot 1 */
625 if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
626 GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
627 hit_mem_insn) {
628 pkt->insn[i].slot = 1;
629 }
630 }
631
632 /* Fix the exceptions - duplex always slot 0,1 */
633 for (i = pkt->num_insns - 1; i >= 0; i--) {
634 /* First subinsn always goes to slot 0 */
635 if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN) && !hit_duplex) {
636 hit_duplex = true;
637 pkt->insn[i].slot = 0;
638 continue;
639 }
640
641 /* Next subinsn always goes to slot 1 */
642 if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN) && hit_duplex) {
643 pkt->insn[i].slot = 1;
644 }
645 }
646
647 /* Fix the exceptions - slot 1 is never empty, always aligns to slot 0 */
648 for (i = pkt->num_insns - 1; i >= 0; i--) {
649 /* Is slot0 used? */
650 if (pkt->insn[i].slot == 0) {
651 bool is_endloop = (pkt->insn[i].opcode == J2_endloop01);
652 is_endloop |= (pkt->insn[i].opcode == J2_endloop0);
653 is_endloop |= (pkt->insn[i].opcode == J2_endloop1);
654
655 /*
656 * Make sure it's not endloop since, we're overloading
657 * slot0 for endloop
658 */
659 if (!is_endloop) {
660 slot0_found = true;
661 }
662 }
663 /* Is slot1 used? */
664 if (pkt->insn[i].slot == 1) {
665 slot1_found = true;
666 slot1_iidx = i;
667 }
668 }
669 /* Is slot0 empty and slot1 used? */
670 if ((!slot0_found) && slot1_found) {
671 /* Then push it to slot0 */
672 pkt->insn[slot1_iidx].slot = 0;
673 }
674
675 return has_valid_slot_assignment(pkt);
676 }
677
678 bool opcode_supported(uint16_t opcode, const HexagonCPUDef *hex_def)
679 {
680 HexagonVersion hex_version = hex_def->hex_version;
681 #include "tag_rev_info.c.inc"
682
683 struct tag_rev_info info = tag_rev_info[opcode];
684 if (hex_version == HEX_VER_ANY) {
685 return true;
686 }
687 if ((info.introduced != HEX_VER_NONE && hex_version < info.introduced) ||
688 (info.removed != HEX_VER_NONE && hex_version >= info.removed)) {
689 return false;
690 }
691 return true;
692 }
693
694 /*
695 * Check for GPR write conflicts in the packet.
696 * A conflict exists when a register is written by more than one instruction
697 * and at least one of those writes is unconditional.
698 *
699 * TODO: handle the more general case of any
700 * packet w/multiple-register-write operands.
701 */
702 static bool pkt_has_write_conflict(Packet *pkt)
703 {
704 DECLARE_BITMAP(all_dest_gprs, 32) = { 0 };
705 DECLARE_BITMAP(wreg_mult_gprs, 32) = { 0 };
706 DECLARE_BITMAP(uncond_wreg_gprs, 32) = { 0 };
707 DECLARE_BITMAP(conflict, 32);
708
709 for (int i = 0; i < pkt->num_insns; i++) {
710 Insn *insn = &pkt->insn[i];
711 int dest = insn->dest_idx;
712
713 if (dest < 0 || !insn->dest_is_gpr) {
714 continue;
715 }
716
717 int rnum = insn->regno[dest];
718 bool is_uncond = !GET_ATTRIB(insn->opcode, A_CONDEXEC);
719
720 if (test_bit(rnum, all_dest_gprs)) {
721 set_bit(rnum, wreg_mult_gprs);
722 }
723 set_bit(rnum, all_dest_gprs);
724 if (is_uncond) {
725 set_bit(rnum, uncond_wreg_gprs);
726 }
727
728 if (insn->dest_is_pair) {
729 if (test_bit(rnum + 1, all_dest_gprs)) {
730 set_bit(rnum + 1, wreg_mult_gprs);
731 }
732 set_bit(rnum + 1, all_dest_gprs);
733 if (is_uncond) {
734 set_bit(rnum + 1, uncond_wreg_gprs);
735 }
736 }
737 }
738
739 bitmap_and(conflict, wreg_mult_gprs, uncond_wreg_gprs, 32);
740 return !bitmap_empty(conflict, 32);
741 }
742
743 /*
744 * decode_packet
745 * Decodes packet with given words
746 * Returns 0 on insufficient words,
747 * or number of words used on success
748 */
749
750 int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
751 Packet *pkt, bool disas_only)
752 {
753 int num_insns = 0;
754 int words_read = 0;
755 bool end_of_packet = false;
756 int new_insns = 0;
757 int i;
758 uint32_t encoding32;
759
760 /* Initialize */
761 memset(pkt, 0, sizeof(*pkt));
762 for (i = 0; i < INSTRUCTIONS_MAX; i++) {
763 pkt->insn[i].dest_idx = -1;
764 pkt->insn[i].new_read_idx = -1;
765 }
766 /* Try to build packet */
767 while (!end_of_packet && (words_read < max_words)) {
768 Insn *insn = &pkt->insn[num_insns];
769 ctx->insn = insn;
770 encoding32 = words[words_read];
771 end_of_packet = is_packet_end(encoding32);
772 new_insns = decode_insns(ctx, insn, encoding32);
773 if (new_insns == 0) {
774 /* Invalid instruction encoding */
775 return 0;
776 }
777 /*
778 * If we saw an extender, mark next word extended so immediate
779 * decode works
780 */
781 if (pkt->insn[num_insns].opcode == A4_ext) {
782 pkt->insn[num_insns + 1].extension_valid = true;
783 }
784 num_insns += new_insns;
785 words_read++;
786 }
787
788 pkt->num_insns = num_insns;
789 if (!end_of_packet) {
790 /* Ran out of words! */
791 return 0;
792 }
793
794 /*
795 * Check that all the opcodes are supported in this Hexagon definition
796 * If not, return decode error
797 */
798 for (i = 0; i < num_insns; i++) {
799 if (!opcode_supported(pkt->insn[i].opcode, ctx->hex_def)) {
800 return 0;
801 }
802 }
803
804 pkt->encod_pkt_size_in_bytes = words_read * 4;
805 pkt->pkt_has_hvx = false;
806 for (i = 0; i < num_insns; i++) {
807 pkt->pkt_has_hvx |=
808 GET_ATTRIB(pkt->insn[i].opcode, A_CVI);
809 }
810
811 /*
812 * Check for :endloop in the parse bits
813 * Section 10.6 of the Programmer's Reference describes the encoding
814 * The end of hardware loop 0 can be encoded with 2 words
815 * The end of hardware loop 1 needs 3 words
816 */
817 if ((words_read == 2) && (decode_parsebits_is_loopend(words[0]))) {
818 decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 0);
819 }
820 if (words_read >= 3) {
821 bool has_loop0, has_loop1;
822 has_loop0 = decode_parsebits_is_loopend(words[0]);
823 has_loop1 = decode_parsebits_is_loopend(words[1]);
824 if (has_loop0 && has_loop1) {
825 decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 10);
826 } else if (has_loop1) {
827 decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 1);
828 } else if (has_loop0) {
829 decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 0);
830 }
831 }
832
833 decode_apply_extenders(pkt);
834 if (!disas_only) {
835 decode_remove_extenders(pkt);
836 if (!decode_set_slot_number(pkt)) {
837 /* Invalid packet */
838 return 0;
839 }
840 pkt->pkt_has_write_conflict = pkt_has_write_conflict(pkt);
841 }
842 decode_fill_newvalue_regno(pkt);
843
844 if (pkt->pkt_has_hvx) {
845 mmvec_ext_decode_checks(pkt, disas_only);
846 }
847
848 if (!disas_only) {
849 decode_shuffle_for_execution(pkt);
850 decode_split_cmpjump(pkt);
851 decode_set_insn_attr_fields(pkt);
852 }
853
854 return words_read;
855 }
856
857 /* Used for "-d in_asm" logging */
858 int disassemble_hexagon(uint32_t *words, int nwords, bfd_vma pc,
859 GString *buf, const HexagonCPUConfig *cfg)
860 {
861 HexagonCPUDef any_def = {
862 .hex_version = HEX_VER_ANY, /* Allow decode to accept anything */
863 };
864 DisasContext ctx;
865
866 memset(&ctx, 0, sizeof(DisasContext));
867 ctx.hex_def = &any_def;
868
869 if (decode_packet(&ctx, nwords, words, &ctx.pkt, true) > 0) {
870 snprint_a_pkt_disas(buf, &ctx.pkt, words, pc, cfg);
871 return ctx.pkt.encod_pkt_size_in_bytes;
872 } else {
873 for (int i = 0; i < nwords; i++) {
874 g_string_append_printf(buf, "0x" TARGET_FMT_lx "\t", words[i]);
875 if (i == 0) {
876 g_string_append(buf, "{");
877 }
878 g_string_append(buf, "\t");
879 g_string_append(buf, "<invalid>");
880 if (i < nwords - 1) {
881 pc += 4;
882 g_string_append_printf(buf, "\n0x" TARGET_FMT_lx ": ",
883 (target_ulong)pc);
884 }
885 }
886 g_string_append(buf, " }");
887 return nwords * sizeof(uint32_t);
888 }
889 }