/src/binutils-gdb/opcodes/tic6x-dis.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* TI C6X disassembler. |
2 | | Copyright (C) 2010-2025 Free Software Foundation, Inc. |
3 | | Contributed by Joseph Myers <joseph@codesourcery.com> |
4 | | Bernd Schmidt <bernds@codesourcery.com> |
5 | | |
6 | | This file is part of libopcodes. |
7 | | |
8 | | This library is free software; you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation; either version 3 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | It is distributed in the hope that it will be useful, but WITHOUT |
14 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
15 | | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
16 | | License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with this program; if not, write to the Free Software |
20 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
21 | | MA 02110-1301, USA. */ |
22 | | |
23 | | #include "sysdep.h" |
24 | | #include "disassemble.h" |
25 | | #include "opcode/tic6x.h" |
26 | | #include "libiberty.h" |
27 | | |
28 | | /* Define the instruction format table. */ |
29 | | const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] = |
30 | | { |
31 | | #define FMT(name, num_bits, cst_bits, mask, fields) \ |
32 | | { num_bits, cst_bits, mask, fields }, |
33 | | #include "opcode/tic6x-insn-formats.h" |
34 | | #undef FMT |
35 | | }; |
36 | | |
37 | | /* Define the control register table. */ |
38 | | const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] = |
39 | | { |
40 | | #define CTRL(name, isa, rw, crlo, crhi_mask) \ |
41 | | { \ |
42 | | STRINGX(name), \ |
43 | | CONCAT2(TIC6X_INSN_,isa), \ |
44 | | CONCAT2(tic6x_rw_,rw), \ |
45 | | crlo, \ |
46 | | crhi_mask \ |
47 | | }, |
48 | | #include "opcode/tic6x-control-registers.h" |
49 | | #undef CTRL |
50 | | }; |
51 | | |
52 | | /* Define the opcode table. */ |
53 | | const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] = |
54 | | { |
55 | | #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \ |
56 | | { \ |
57 | | STRINGX(name), \ |
58 | | CONCAT2(tic6x_func_unit_,func_unit), \ |
59 | | CONCAT3(tic6x_insn_format,_,format), \ |
60 | | CONCAT2(tic6x_pipeline_,type), \ |
61 | | CONCAT2(TIC6X_INSN_,isa), \ |
62 | | flags, \ |
63 | | fixed, \ |
64 | | ops, \ |
65 | | var \ |
66 | | }, |
67 | | #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \ |
68 | | { \ |
69 | | STRINGX(name), \ |
70 | | CONCAT2(tic6x_func_unit_,func_unit), \ |
71 | | CONCAT3(tic6x_insn_format,_,format), \ |
72 | | CONCAT2(tic6x_pipeline_,type), \ |
73 | | CONCAT2(TIC6X_INSN_,isa), \ |
74 | | flags, \ |
75 | | fixed, \ |
76 | | ops, \ |
77 | | var \ |
78 | | }, |
79 | | #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \ |
80 | | { \ |
81 | | STRINGX(name), \ |
82 | | CONCAT2(tic6x_func_unit_,func_unit), \ |
83 | | CONCAT4(tic6x_insn_format_,func_unit,_,format), \ |
84 | | CONCAT2(tic6x_pipeline_,type), \ |
85 | | CONCAT2(TIC6X_INSN_,isa), \ |
86 | | flags, \ |
87 | | fixed, \ |
88 | | ops, \ |
89 | | var \ |
90 | | }, |
91 | | #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \ |
92 | | { \ |
93 | | STRINGX(name), \ |
94 | | CONCAT2(tic6x_func_unit_,func_unit), \ |
95 | | CONCAT4(tic6x_insn_format_,func_unit,_,format), \ |
96 | | CONCAT2(tic6x_pipeline_,type), \ |
97 | | CONCAT2(TIC6X_INSN_,isa), \ |
98 | | flags, \ |
99 | | fixed, \ |
100 | | ops, \ |
101 | | var \ |
102 | | }, |
103 | | #include "opcode/tic6x-opcode-table.h" |
104 | | #undef INSN |
105 | | #undef INSNE |
106 | | #undef INSNU |
107 | | #undef INSNUE |
108 | | }; |
109 | | |
110 | | /* If instruction format FMT has a field FIELD, return a pointer to |
111 | | the description of that field; otherwise return NULL. */ |
112 | | |
113 | | const tic6x_insn_field * |
114 | | tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field) |
115 | 92.4M | { |
116 | 92.4M | unsigned int f; |
117 | | |
118 | 327M | for (f = 0; f < fmt->num_fields; f++) |
119 | 327M | if (fmt->fields[f].field_id == field) |
120 | 91.9M | return &fmt->fields[f]; |
121 | | |
122 | 469k | return NULL; |
123 | 92.4M | } |
124 | | |
125 | | /* Extract the field width. */ |
126 | | |
127 | | static unsigned int |
128 | | tic6x_field_width (const tic6x_insn_field *field) |
129 | 282k | { |
130 | 282k | unsigned int i; |
131 | 282k | unsigned int width = 0; |
132 | | |
133 | 282k | if (!field->num_bitfields) |
134 | 0 | return field->bitfields[0].width; |
135 | | |
136 | 571k | for (i = 0 ; i < field->num_bitfields ; i++) |
137 | 288k | width += field->bitfields[i].width; |
138 | | |
139 | 282k | return width; |
140 | 282k | } |
141 | | |
142 | | /* Extract the bits corresponding to FIELD from OPCODE. */ |
143 | | |
144 | | static unsigned int |
145 | | tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field) |
146 | 91.9M | { |
147 | 91.9M | unsigned int i; |
148 | 91.9M | unsigned int val = 0; |
149 | | |
150 | 91.9M | if (!field->num_bitfields) |
151 | 0 | return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1); |
152 | | |
153 | 183M | for (i = 0 ; i < field->num_bitfields ; i++) |
154 | 92.0M | val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1)) |
155 | 92.0M | << field->bitfields[i].pos; |
156 | | |
157 | 91.9M | return val; |
158 | 91.9M | } |
159 | | |
160 | | /* Extract a 32-bit value read from the instruction stream. */ |
161 | | |
162 | | static unsigned int |
163 | | tic6x_extract_32 (unsigned char *p, struct disassemble_info *info) |
164 | 4.24M | { |
165 | 4.24M | if (info->endian == BFD_ENDIAN_LITTLE) |
166 | 123 | return p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned) p[3] << 24); |
167 | 4.23M | else |
168 | 4.23M | return p[3] | (p[2] << 8) | (p[1] << 16) | ((unsigned) p[0] << 24); |
169 | 4.24M | } |
170 | | |
171 | | /* Extract a 16-bit value read from the instruction stream. */ |
172 | | |
173 | | static unsigned int |
174 | | tic6x_extract_16 (unsigned char *p, tic6x_fetch_packet_header *header, |
175 | | struct disassemble_info *info) |
176 | 70.9k | { |
177 | 70.9k | unsigned int op16; |
178 | | |
179 | 70.9k | if (info->endian == BFD_ENDIAN_LITTLE) |
180 | 31 | op16 = (p[0]) | (p[1] << 8); |
181 | 70.8k | else |
182 | 70.8k | op16 = (p[1]) | (p[0] << 8); |
183 | 70.9k | op16 |= (header->sat << TIC6X_COMPACT_SAT_POS); |
184 | 70.9k | op16 |= (header->br << TIC6X_COMPACT_BR_POS); |
185 | 70.9k | op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS); |
186 | 70.9k | return op16; |
187 | 70.9k | } |
188 | | |
189 | | /* FP points to a fetch packet. Return whether it is header-based; if |
190 | | it is, fill in HEADER. */ |
191 | | |
192 | | static bool |
193 | | tic6x_check_fetch_packet_header (unsigned char *fp, |
194 | | tic6x_fetch_packet_header *header, |
195 | | struct disassemble_info *info) |
196 | 1.69M | { |
197 | 1.69M | int i; |
198 | | |
199 | 1.69M | header->header = tic6x_extract_32 (fp + 28, info); |
200 | | |
201 | 1.69M | if ((header->header & 0xf0000000) != 0xe0000000) |
202 | 1.58M | { |
203 | 1.58M | header->prot = 0; |
204 | 1.58M | header->rs = 0; |
205 | 1.58M | header->dsz = 0; |
206 | 1.58M | header->br = 0; |
207 | 1.58M | header->sat = 0; |
208 | 12.7M | for (i = 0; i < 7; i++) |
209 | 11.1M | header->word_compact[i] = false; |
210 | 23.8M | for (i = 0; i < 14; i++) |
211 | 22.2M | header->p_bits[i] = false; |
212 | 1.58M | return false; |
213 | 1.58M | } |
214 | | |
215 | 882k | for (i = 0; i < 7; i++) |
216 | 772k | header->word_compact[i] |
217 | 772k | = (header->header & (1u << (21 + i))) != 0; |
218 | | |
219 | 110k | header->prot = (header->header & (1u << 20)) != 0; |
220 | 110k | header->rs = (header->header & (1u << 19)) != 0; |
221 | 110k | header->dsz = (header->header >> 16) & 0x7; |
222 | 110k | header->br = (header->header & (1u << 15)) != 0; |
223 | 110k | header->sat = (header->header & (1u << 14)) != 0; |
224 | | |
225 | 1.65M | for (i = 0; i < 14; i++) |
226 | 1.54M | header->p_bits[i] = (header->header & (1u << i)) != 0; |
227 | | |
228 | 110k | return true; |
229 | 1.69M | } |
230 | | |
231 | | /* Disassemble the instruction at ADDR and print it using |
232 | | INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes |
233 | | consumed. */ |
234 | | |
235 | | int |
236 | | print_insn_tic6x (bfd_vma addr, struct disassemble_info *info) |
237 | 1.56M | { |
238 | 1.56M | int status; |
239 | 1.56M | bfd_vma fp_addr; |
240 | 1.56M | bfd_vma fp_offset; |
241 | 1.56M | unsigned char fp[32]; |
242 | 1.56M | unsigned int opcode; |
243 | 1.56M | tic6x_opcode_id opcode_id; |
244 | 1.56M | bool fetch_packet_header_based; |
245 | 1.56M | tic6x_fetch_packet_header header; |
246 | 1.56M | unsigned int num_bits; |
247 | 1.56M | bool bad_offset = false; |
248 | | |
249 | 1.56M | fp_offset = addr & 0x1f; |
250 | 1.56M | fp_addr = addr - fp_offset; |
251 | | /* Read in a block of instructions. Since there might be a |
252 | | symbol in the middle of this block, disable stop_vma. */ |
253 | 1.56M | info->stop_vma = 0; |
254 | 1.56M | status = info->read_memory_func (fp_addr, fp, 32, info); |
255 | 1.56M | if (status) |
256 | 696 | { |
257 | 696 | info->memory_error_func (status, addr, info); |
258 | 696 | return -1; |
259 | 696 | } |
260 | | |
261 | 1.56M | fetch_packet_header_based |
262 | 1.56M | = tic6x_check_fetch_packet_header (fp, &header, info); |
263 | 1.56M | if (fetch_packet_header_based) |
264 | 104k | { |
265 | 104k | if (fp_offset & 0x1) |
266 | 15 | bad_offset = true; |
267 | 104k | if ((fp_offset & 0x3) && (fp_offset >= 28 |
268 | 31.8k | || !header.word_compact[fp_offset >> 2])) |
269 | 30 | bad_offset = true; |
270 | 104k | if (fp_offset == 28) |
271 | 9.39k | { |
272 | 9.39k | info->bytes_per_chunk = 4; |
273 | 9.39k | info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>", |
274 | 9.39k | header.header); |
275 | 9.39k | return 4; |
276 | 9.39k | } |
277 | 94.8k | num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32); |
278 | 94.8k | } |
279 | 1.45M | else |
280 | 1.45M | { |
281 | 1.45M | num_bits = 32; |
282 | 1.45M | if (fp_offset & 0x3) |
283 | 9 | bad_offset = true; |
284 | 1.45M | } |
285 | | |
286 | 1.55M | if (bad_offset) |
287 | 39 | { |
288 | 39 | info->bytes_per_chunk = 1; |
289 | 39 | info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]); |
290 | 39 | return 1; |
291 | 39 | } |
292 | | |
293 | 1.55M | if (num_bits == 16) |
294 | 63.6k | { |
295 | | /* The least-significant part of a 32-bit word comes logically |
296 | | before the most-significant part. For big-endian, follow the |
297 | | TI assembler in showing instructions in logical order by |
298 | | pretending that the two halves of the word are in opposite |
299 | | locations to where they actually are. */ |
300 | 63.6k | if (info->endian == BFD_ENDIAN_LITTLE) |
301 | 31 | opcode = tic6x_extract_16 (fp + fp_offset, &header, info); |
302 | 63.6k | else |
303 | 63.6k | opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info); |
304 | 63.6k | } |
305 | 1.48M | else |
306 | 1.48M | opcode = tic6x_extract_32 (fp + fp_offset, info); |
307 | | |
308 | 637M | for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++) |
309 | 636M | { |
310 | 636M | const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id]; |
311 | 636M | const tic6x_insn_format *const fmt |
312 | 636M | = &tic6x_insn_format_table[opc->format]; |
313 | 636M | const tic6x_insn_field *creg_field; |
314 | 636M | bool p_bit; |
315 | 636M | const char *parallel; |
316 | 636M | const char *cond = ""; |
317 | 636M | const char *func_unit; |
318 | 636M | char func_unit_buf[8]; |
319 | 636M | unsigned int func_unit_side = 0; |
320 | 636M | unsigned int func_unit_data_side = 0; |
321 | 636M | unsigned int func_unit_cross = 0; |
322 | 636M | unsigned int t_val = 0; |
323 | | /* The maximum length of the text of a non-PC-relative operand |
324 | | is 24 bytes (SPMASK masking all eight functional units, with |
325 | | separating commas and trailing NUL). */ |
326 | 636M | char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } }; |
327 | 636M | bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 }; |
328 | 636M | bool operands_text[TIC6X_MAX_OPERANDS] = { false }; |
329 | 636M | bool operands_pcrel[TIC6X_MAX_OPERANDS] = { false }; |
330 | 636M | unsigned int fix; |
331 | 636M | unsigned int num_operands; |
332 | 636M | unsigned int op_num; |
333 | 636M | bool fixed_ok; |
334 | 636M | bool operands_ok; |
335 | 636M | bool have_t = false; |
336 | | |
337 | 636M | if (opc->flags & TIC6X_FLAG_MACRO) |
338 | 67.7M | continue; |
339 | 569M | if (fmt->num_bits != num_bits) |
340 | 186M | continue; |
341 | 382M | if ((opcode & fmt->mask) != fmt->cst_bits) |
342 | 352M | continue; |
343 | | |
344 | | /* If the format has a creg field, it is only a candidate for a |
345 | | match if the creg and z fields have values indicating a valid |
346 | | condition; reserved values indicate either an instruction |
347 | | format without a creg field, or an invalid instruction. */ |
348 | 29.8M | creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg); |
349 | 29.8M | if (creg_field) |
350 | 29.4M | { |
351 | 29.4M | const tic6x_insn_field *z_field; |
352 | 29.4M | unsigned int creg_value, z_value; |
353 | 29.4M | static const char *const conds[8][2] = |
354 | 29.4M | { |
355 | 29.4M | { "", NULL }, |
356 | 29.4M | { "[b0] ", "[!b0] " }, |
357 | 29.4M | { "[b1] ", "[!b1] " }, |
358 | 29.4M | { "[b2] ", "[!b2] " }, |
359 | 29.4M | { "[a1] ", "[!a1] " }, |
360 | 29.4M | { "[a2] ", "[!a2] " }, |
361 | 29.4M | { "[a0] ", "[!a0] " }, |
362 | 29.4M | { NULL, NULL } |
363 | 29.4M | }; |
364 | | |
365 | | /* A creg field is not meaningful without a z field, so if |
366 | | the z field is not present this is an error in the format |
367 | | table. */ |
368 | 29.4M | z_field = tic6x_field_from_fmt (fmt, tic6x_field_z); |
369 | 29.4M | if (!z_field) |
370 | 0 | { |
371 | 0 | printf ("*** opcode %x: missing z field", opcode); |
372 | 0 | abort (); |
373 | 0 | } |
374 | | |
375 | 29.4M | creg_value = tic6x_field_bits (opcode, creg_field); |
376 | 29.4M | z_value = tic6x_field_bits (opcode, z_field); |
377 | 29.4M | cond = conds[creg_value][z_value]; |
378 | 29.4M | if (cond == NULL) |
379 | 5.95M | continue; |
380 | 29.4M | } |
381 | | |
382 | 23.9M | if (opc->flags & TIC6X_FLAG_INSN16_SPRED) |
383 | 14.4k | { |
384 | 14.4k | const tic6x_insn_field *cc_field; |
385 | 14.4k | unsigned int s_value = 0; |
386 | 14.4k | unsigned int z_value = 0; |
387 | 14.4k | bool cond_known = false; |
388 | 14.4k | static const char *const conds[2][2] = |
389 | 14.4k | { |
390 | 14.4k | { "[a0] ", "[!a0] " }, |
391 | 14.4k | { "[b0] ", "[!b0] " } |
392 | 14.4k | }; |
393 | | |
394 | 14.4k | cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc); |
395 | | |
396 | 14.4k | if (cc_field) |
397 | 407 | { |
398 | 407 | unsigned int cc_value; |
399 | | |
400 | 407 | cc_value = tic6x_field_bits (opcode, cc_field); |
401 | 407 | s_value = (cc_value & 0x2) >> 1; |
402 | 407 | z_value = (cc_value & 0x1); |
403 | 407 | cond_known = true; |
404 | 407 | } |
405 | 14.0k | else |
406 | 14.0k | { |
407 | 14.0k | const tic6x_insn_field *z_field; |
408 | 14.0k | const tic6x_insn_field *s_field; |
409 | | |
410 | 14.0k | s_field = tic6x_field_from_fmt (fmt, tic6x_field_s); |
411 | | |
412 | 14.0k | if (!s_field) |
413 | 0 | { |
414 | 0 | printf ("opcode %x: missing compact insn predicate register field (s field)\n", |
415 | 0 | opcode); |
416 | 0 | abort (); |
417 | 0 | } |
418 | 14.0k | s_value = tic6x_field_bits (opcode, s_field); |
419 | 14.0k | z_field = tic6x_field_from_fmt (fmt, tic6x_field_z); |
420 | 14.0k | if (!z_field) |
421 | 0 | { |
422 | 0 | printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode); |
423 | 0 | abort (); |
424 | 0 | } |
425 | | |
426 | 14.0k | z_value = tic6x_field_bits (opcode, z_field); |
427 | 14.0k | cond_known = true; |
428 | 14.0k | } |
429 | | |
430 | 14.4k | if (!cond_known) |
431 | 0 | { |
432 | 0 | printf ("opcode %x: unspecified ompact insn predicate\n", opcode); |
433 | 0 | abort (); |
434 | 0 | } |
435 | 14.4k | cond = conds[s_value][z_value]; |
436 | 14.4k | } |
437 | | |
438 | | /* All fixed fields must have matching values; all fields with |
439 | | restricted ranges must have values within those ranges. */ |
440 | 23.9M | fixed_ok = true; |
441 | 25.5M | for (fix = 0; fix < opc->num_fixed_fields; fix++) |
442 | 24.5M | { |
443 | 24.5M | unsigned int field_bits; |
444 | 24.5M | const tic6x_insn_field *const field |
445 | 24.5M | = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id); |
446 | | |
447 | 24.5M | if (!field) |
448 | 0 | { |
449 | 0 | printf ("opcode %x: missing field #%d for FIX #%d\n", |
450 | 0 | opcode, opc->fixed_fields[fix].field_id, fix); |
451 | 0 | abort (); |
452 | 0 | } |
453 | | |
454 | 24.5M | field_bits = tic6x_field_bits (opcode, field); |
455 | 24.5M | if (field_bits < opc->fixed_fields[fix].min_val |
456 | 24.5M | || field_bits > opc->fixed_fields[fix].max_val) |
457 | 22.9M | { |
458 | 22.9M | fixed_ok = false; |
459 | 22.9M | break; |
460 | 22.9M | } |
461 | 24.5M | } |
462 | 23.9M | if (!fixed_ok) |
463 | 22.9M | continue; |
464 | | |
465 | | /* The instruction matches. */ |
466 | | |
467 | | /* The p-bit indicates whether this instruction is in parallel |
468 | | with the *next* instruction, whereas the parallel bars |
469 | | indicate the instruction is in parallel with the *previous* |
470 | | instruction. Thus, we must find the p-bit for the previous |
471 | | instruction. */ |
472 | 1.02M | if (num_bits == 16 && (fp_offset & 0x2) == 2) |
473 | 29.0k | { |
474 | | /* This is the logically second (most significant; second in |
475 | | fp_offset terms because fp_offset relates to logical not |
476 | | physical addresses) instruction of a compact pair; find |
477 | | the p-bit for the first (least significant). */ |
478 | 29.0k | p_bit = header.p_bits[(fp_offset >> 2) << 1]; |
479 | 29.0k | } |
480 | 997k | else if (fp_offset >= 4) |
481 | 869k | { |
482 | | /* Find the last instruction of the previous word in this |
483 | | fetch packet. For compact instructions, this is the most |
484 | | significant 16 bits. */ |
485 | 869k | if (fetch_packet_header_based |
486 | 869k | && header.word_compact[(fp_offset >> 2) - 1]) |
487 | 17.9k | p_bit = header.p_bits[(fp_offset >> 1) - 1]; |
488 | 852k | else |
489 | 852k | { |
490 | 852k | unsigned int prev_opcode |
491 | 852k | = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info); |
492 | 852k | p_bit = (prev_opcode & 0x1) != 0; |
493 | 852k | } |
494 | 869k | } |
495 | 127k | else |
496 | 127k | { |
497 | | /* Find the last instruction of the previous fetch |
498 | | packet. */ |
499 | 127k | unsigned char fp_prev[32]; |
500 | | |
501 | 127k | status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info); |
502 | 127k | if (status) |
503 | | /* No previous instruction to be parallel with. */ |
504 | 548 | p_bit = false; |
505 | 126k | else |
506 | 126k | { |
507 | 126k | bool prev_header_based; |
508 | 126k | tic6x_fetch_packet_header prev_header; |
509 | | |
510 | 126k | prev_header_based |
511 | 126k | = tic6x_check_fetch_packet_header (fp_prev, &prev_header, info); |
512 | 126k | if (prev_header_based) |
513 | 5.22k | { |
514 | 5.22k | if (prev_header.word_compact[6]) |
515 | 3.40k | p_bit = prev_header.p_bits[13]; |
516 | 1.81k | else |
517 | 1.81k | { |
518 | 1.81k | unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 24, |
519 | 1.81k | info); |
520 | 1.81k | p_bit = (prev_opcode & 0x1) != 0; |
521 | 1.81k | } |
522 | 5.22k | } |
523 | 121k | else |
524 | 121k | { |
525 | 121k | unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28, |
526 | 121k | info); |
527 | 121k | p_bit = (prev_opcode & 0x1) != 0; |
528 | 121k | } |
529 | 126k | } |
530 | 127k | } |
531 | 1.02M | parallel = p_bit ? "|| " : ""; |
532 | | |
533 | 1.02M | if (opc->func_unit == tic6x_func_unit_nfu) |
534 | 112k | func_unit = ""; |
535 | 913k | else |
536 | 913k | { |
537 | 913k | unsigned int fld_num; |
538 | 913k | char func_unit_char; |
539 | 913k | const char *data_str; |
540 | 913k | bool have_areg = false; |
541 | 913k | bool have_cross = false; |
542 | | |
543 | 913k | func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0; |
544 | 913k | func_unit_cross = 0; |
545 | 913k | func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0; |
546 | | |
547 | 5.13M | for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++) |
548 | 4.22M | { |
549 | 4.22M | const tic6x_coding_field *const enc = &opc->variable_fields[fld_num]; |
550 | 4.22M | const tic6x_insn_field *field; |
551 | 4.22M | unsigned int fld_val; |
552 | | |
553 | 4.22M | field = tic6x_field_from_fmt (fmt, enc->field_id); |
554 | | |
555 | 4.22M | if (!field) |
556 | 0 | { |
557 | 0 | printf ("opcode %x: could not retrieve field (field_id:%d)\n", |
558 | 0 | opcode, fld_num); |
559 | 0 | abort (); |
560 | 0 | } |
561 | | |
562 | 4.22M | fld_val = tic6x_field_bits (opcode, field); |
563 | | |
564 | 4.22M | switch (enc->coding_method) |
565 | 4.22M | { |
566 | 714k | case tic6x_coding_fu: |
567 | | /* The side must be specified exactly once. */ |
568 | 714k | if (func_unit_side) |
569 | 0 | { |
570 | 0 | printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n", |
571 | 0 | opcode, fld_num); |
572 | 0 | abort (); |
573 | 0 | } |
574 | 714k | func_unit_side = (fld_val ? 2 : 1); |
575 | 714k | break; |
576 | | |
577 | 373k | case tic6x_coding_data_fu: |
578 | | /* The data side must be specified exactly once. */ |
579 | 373k | if (func_unit_data_side) |
580 | 0 | { |
581 | 0 | printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n", |
582 | 0 | opcode, fld_num); |
583 | 0 | abort (); |
584 | 0 | } |
585 | 373k | func_unit_data_side = (fld_val ? 2 : 1); |
586 | 373k | break; |
587 | | |
588 | 325k | case tic6x_coding_xpath: |
589 | | /* Cross path use must be specified exactly |
590 | | once. */ |
591 | 325k | if (have_cross) |
592 | 0 | { |
593 | 0 | printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n", |
594 | 0 | opcode, fld_num); |
595 | 0 | abort (); |
596 | 0 | } |
597 | 325k | have_cross = true; |
598 | 325k | func_unit_cross = fld_val; |
599 | 325k | break; |
600 | | |
601 | 9.80k | case tic6x_coding_rside: |
602 | | /* If the format has a t field, use it for src/dst register side. */ |
603 | 9.80k | have_t = true; |
604 | 9.80k | t_val = fld_val; |
605 | 9.80k | func_unit_data_side = (t_val ? 2 : 1); |
606 | 9.80k | break; |
607 | | |
608 | 203k | case tic6x_coding_areg: |
609 | 203k | have_areg = true; |
610 | 203k | break; |
611 | | |
612 | 2.59M | default: |
613 | | /* Don't relate to functional units. */ |
614 | 2.59M | break; |
615 | 4.22M | } |
616 | 4.22M | } |
617 | | |
618 | | /* The side of the functional unit used must now have been |
619 | | determined either from the flags or from an instruction |
620 | | field. */ |
621 | 913k | if (func_unit_side != 1 && func_unit_side != 2) |
622 | 0 | { |
623 | 0 | printf ("opcode %x: func_unit_side is not encoded!\n", opcode); |
624 | 0 | abort (); |
625 | 0 | } |
626 | | |
627 | | /* Cross paths are not applicable when sides are specified |
628 | | for both address and data paths. */ |
629 | 913k | if (func_unit_data_side && have_cross) |
630 | 0 | { |
631 | 0 | printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n", |
632 | 0 | opcode); |
633 | 0 | abort (); |
634 | 0 | } |
635 | | |
636 | | /* Separate address and data paths are only applicable for |
637 | | the D unit. */ |
638 | 913k | if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d) |
639 | 0 | { |
640 | 0 | printf ("opcode %x: separate address and data paths only applicable for D unit!\n", |
641 | 0 | opcode); |
642 | 0 | abort (); |
643 | 0 | } |
644 | | |
645 | | /* If an address register is being used but in ADDA rather |
646 | | than a load or store, it uses a cross path for side-A |
647 | | instructions, and the cross path use is not specified by |
648 | | an instruction field. */ |
649 | 913k | if (have_areg && !func_unit_data_side) |
650 | 4.60k | { |
651 | 4.60k | if (have_cross) |
652 | 0 | { |
653 | 0 | printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode); |
654 | 0 | abort (); |
655 | 0 | } |
656 | 4.60k | func_unit_cross = func_unit_side == 1; |
657 | 4.60k | } |
658 | | |
659 | 913k | switch (opc->func_unit) |
660 | 913k | { |
661 | 402k | case tic6x_func_unit_d: |
662 | 402k | func_unit_char = 'D'; |
663 | 402k | break; |
664 | | |
665 | 67.6k | case tic6x_func_unit_l: |
666 | 67.6k | func_unit_char = 'L'; |
667 | 67.6k | break; |
668 | | |
669 | 204k | case tic6x_func_unit_m: |
670 | 204k | func_unit_char = 'M'; |
671 | 204k | break; |
672 | | |
673 | 239k | case tic6x_func_unit_s: |
674 | 239k | func_unit_char = 'S'; |
675 | 239k | break; |
676 | | |
677 | 0 | default: |
678 | 0 | printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit); |
679 | 0 | abort (); |
680 | 913k | } |
681 | | |
682 | 913k | switch (func_unit_data_side) |
683 | 913k | { |
684 | 530k | case 0: |
685 | 530k | data_str = ""; |
686 | 530k | break; |
687 | | |
688 | 191k | case 1: |
689 | 191k | data_str = "T1"; |
690 | 191k | break; |
691 | | |
692 | 191k | case 2: |
693 | 191k | data_str = "T2"; |
694 | 191k | break; |
695 | | |
696 | 0 | default: |
697 | 0 | printf ("opcode %x: illegal data func_unit specifier %d\n", |
698 | 0 | opcode, func_unit_data_side); |
699 | 0 | abort (); |
700 | 913k | } |
701 | | |
702 | 913k | if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1) |
703 | 137 | func_unit_cross = 1; |
704 | | |
705 | 913k | snprintf (func_unit_buf, sizeof func_unit_buf, " .%c%u%s%s", |
706 | 913k | func_unit_char, func_unit_side, |
707 | 913k | (func_unit_cross ? "X" : ""), data_str); |
708 | 913k | func_unit = func_unit_buf; |
709 | 913k | } |
710 | | |
711 | | /* For each operand there must be one or more fields set based |
712 | | on that operand, that can together be used to derive the |
713 | | operand value. */ |
714 | 1.02M | operands_ok = true; |
715 | 1.02M | num_operands = opc->num_operands; |
716 | 3.36M | for (op_num = 0; op_num < num_operands; op_num++) |
717 | 2.34M | { |
718 | 2.34M | unsigned int fld_num; |
719 | 2.34M | unsigned int mem_base_reg = 0; |
720 | 2.34M | bool mem_base_reg_known = false; |
721 | 2.34M | bool mem_base_reg_known_long = false; |
722 | 2.34M | unsigned int mem_offset = 0; |
723 | 2.34M | bool mem_offset_known = false; |
724 | 2.34M | bool mem_offset_known_long = false; |
725 | 2.34M | unsigned int mem_mode = 0; |
726 | 2.34M | bool mem_mode_known = false; |
727 | 2.34M | unsigned int mem_scaled = 0; |
728 | 2.34M | bool mem_scaled_known = false; |
729 | 2.34M | unsigned int crlo = 0; |
730 | 2.34M | bool crlo_known = false; |
731 | 2.34M | unsigned int crhi = 0; |
732 | 2.34M | bool crhi_known = false; |
733 | 2.34M | bool spmask_skip_operand = false; |
734 | 2.34M | unsigned int fcyc_bits = 0; |
735 | 2.34M | bool prev_sploop_found = false; |
736 | | |
737 | 2.34M | switch (opc->operand_info[op_num].form) |
738 | 2.34M | { |
739 | 261 | case tic6x_operand_b15reg: |
740 | | /* Fully determined by the functional unit. */ |
741 | 261 | operands_text[op_num] = true; |
742 | 261 | snprintf (operands[op_num], 24, "b15"); |
743 | 261 | continue; |
744 | | |
745 | 853 | case tic6x_operand_zreg: |
746 | | /* Fully determined by the functional unit. */ |
747 | 853 | operands_text[op_num] = true; |
748 | 853 | snprintf (operands[op_num], 24, "%c0", |
749 | 853 | (func_unit_side == 2 ? 'b' : 'a')); |
750 | 853 | continue; |
751 | | |
752 | 2.42k | case tic6x_operand_retreg: |
753 | | /* Fully determined by the functional unit. */ |
754 | 2.42k | operands_text[op_num] = true; |
755 | 2.42k | snprintf (operands[op_num], 24, "%c3", |
756 | 2.42k | (func_unit_side == 2 ? 'b' : 'a')); |
757 | 2.42k | continue; |
758 | | |
759 | 0 | case tic6x_operand_irp: |
760 | 0 | operands_text[op_num] = true; |
761 | 0 | snprintf (operands[op_num], 24, "irp"); |
762 | 0 | continue; |
763 | | |
764 | 0 | case tic6x_operand_nrp: |
765 | 0 | operands_text[op_num] = true; |
766 | 0 | snprintf (operands[op_num], 24, "nrp"); |
767 | 0 | continue; |
768 | | |
769 | 28 | case tic6x_operand_ilc: |
770 | 28 | operands_text[op_num] = true; |
771 | 28 | snprintf (operands[op_num], 24, "ilc"); |
772 | 28 | continue; |
773 | | |
774 | 7 | case tic6x_operand_hw_const_minus_1: |
775 | 7 | operands_text[op_num] = true; |
776 | 7 | snprintf (operands[op_num], 24, "-1"); |
777 | 7 | continue; |
778 | | |
779 | 2 | case tic6x_operand_hw_const_0: |
780 | 2 | operands_text[op_num] = true; |
781 | 2 | snprintf (operands[op_num], 24, "0"); |
782 | 2 | continue; |
783 | | |
784 | 182 | case tic6x_operand_hw_const_1: |
785 | 182 | operands_text[op_num] = true; |
786 | 182 | snprintf (operands[op_num], 24, "1"); |
787 | 182 | continue; |
788 | | |
789 | 13.1k | case tic6x_operand_hw_const_5: |
790 | 13.1k | operands_text[op_num] = true; |
791 | 13.1k | snprintf (operands[op_num], 24, "5"); |
792 | 13.1k | continue; |
793 | | |
794 | 1.40k | case tic6x_operand_hw_const_16: |
795 | 1.40k | operands_text[op_num] = true; |
796 | 1.40k | snprintf (operands[op_num], 24, "16"); |
797 | 1.40k | continue; |
798 | | |
799 | 122 | case tic6x_operand_hw_const_24: |
800 | 122 | operands_text[op_num] = true; |
801 | 122 | snprintf (operands[op_num], 24, "24"); |
802 | 122 | continue; |
803 | | |
804 | 853 | case tic6x_operand_hw_const_31: |
805 | 853 | operands_text[op_num] = true; |
806 | 853 | snprintf (operands[op_num], 24, "31"); |
807 | 853 | continue; |
808 | | |
809 | 2.32M | default: |
810 | 2.32M | break; |
811 | 2.34M | } |
812 | | |
813 | 8.81M | for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++) |
814 | 8.81M | { |
815 | 8.81M | const tic6x_coding_field *const enc |
816 | 8.81M | = &opc->variable_fields[fld_num]; |
817 | 8.81M | const tic6x_insn_field *field; |
818 | 8.81M | unsigned int fld_val; |
819 | 8.81M | unsigned int reg_base = 0; |
820 | 8.81M | signed int signed_fld_val; |
821 | 8.81M | char reg_side = '?'; |
822 | | |
823 | 8.81M | if (enc->operand_num != op_num) |
824 | 4.48M | continue; |
825 | 4.32M | field = tic6x_field_from_fmt (fmt, enc->field_id); |
826 | 4.32M | if (!field) |
827 | 0 | { |
828 | 0 | printf ("opcode %x: missing field (field_id:%d) in format\n", opcode, enc->field_id); |
829 | 0 | abort (); |
830 | 0 | } |
831 | 4.32M | fld_val = tic6x_field_bits (opcode, field); |
832 | 4.32M | switch (enc->coding_method) |
833 | 4.32M | { |
834 | 698 | case tic6x_coding_cst_s3i: |
835 | 698 | (fld_val == 0x00) && (fld_val = 0x10); |
836 | 698 | (fld_val == 0x07) && (fld_val = 0x08); |
837 | | /* Fall through. */ |
838 | 111k | case tic6x_coding_ucst: |
839 | 166k | case tic6x_coding_ulcst_dpr_byte: |
840 | 224k | case tic6x_coding_ulcst_dpr_half: |
841 | 314k | case tic6x_coding_ulcst_dpr_word: |
842 | 314k | case tic6x_coding_lcst_low16: |
843 | 314k | switch (opc->operand_info[op_num].form) |
844 | 314k | { |
845 | 109k | case tic6x_operand_asm_const: |
846 | 115k | case tic6x_operand_link_const: |
847 | 115k | operands_text[op_num] = true; |
848 | 115k | snprintf (operands[op_num], 24, "%u", fld_val); |
849 | 115k | break; |
850 | | |
851 | 198k | case tic6x_operand_mem_long: |
852 | 198k | mem_offset = fld_val; |
853 | 198k | mem_offset_known_long = true; |
854 | 198k | break; |
855 | | |
856 | 0 | default: |
857 | 0 | printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num); |
858 | 0 | abort (); |
859 | 314k | } |
860 | 314k | break; |
861 | | |
862 | 314k | case tic6x_coding_lcst_high16: |
863 | 31.6k | operands_text[op_num] = true; |
864 | 31.6k | snprintf (operands[op_num], 24, "%u", fld_val << 16); |
865 | 31.6k | break; |
866 | | |
867 | 3.49k | case tic6x_coding_scst_l3i: |
868 | 3.49k | operands_text[op_num] = true; |
869 | 3.49k | if (fld_val == 0) |
870 | 667 | { |
871 | 667 | signed_fld_val = 8; |
872 | 667 | } |
873 | 2.83k | else |
874 | 2.83k | { |
875 | 2.83k | signed_fld_val = (signed int) fld_val; |
876 | 2.83k | signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); |
877 | 2.83k | signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); |
878 | 2.83k | } |
879 | 3.49k | snprintf (operands[op_num], 24, "%d", signed_fld_val); |
880 | 3.49k | break; |
881 | | |
882 | 99.0k | case tic6x_coding_scst: |
883 | 99.0k | operands_text[op_num] = true; |
884 | 99.0k | signed_fld_val = (signed int) fld_val; |
885 | 99.0k | signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); |
886 | 99.0k | signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); |
887 | 99.0k | snprintf (operands[op_num], 24, "%d", signed_fld_val); |
888 | 99.0k | break; |
889 | | |
890 | 95.2k | case tic6x_coding_ucst_minus_one: |
891 | 95.2k | operands_text[op_num] = true; |
892 | 95.2k | snprintf (operands[op_num], 24, "%u", fld_val + 1); |
893 | 95.2k | break; |
894 | | |
895 | 38.1k | case tic6x_coding_pcrel: |
896 | 39.5k | case tic6x_coding_pcrel_half: |
897 | 39.5k | signed_fld_val = (signed int) fld_val; |
898 | 39.5k | signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); |
899 | 39.5k | signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); |
900 | 39.5k | if (fetch_packet_header_based |
901 | 39.5k | && enc->coding_method == tic6x_coding_pcrel_half) |
902 | 1.34k | signed_fld_val *= 2; |
903 | 38.2k | else |
904 | 38.2k | signed_fld_val *= 4; |
905 | 39.5k | operands_pcrel[op_num] = true; |
906 | 39.5k | operands_addresses[op_num] = fp_addr + signed_fld_val; |
907 | 39.5k | break; |
908 | | |
909 | 2.41k | case tic6x_coding_regpair_msb: |
910 | 2.41k | if (opc->operand_info[op_num].form != tic6x_operand_regpair) |
911 | 0 | abort (); |
912 | 2.41k | operands_text[op_num] = true; |
913 | 2.41k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
914 | 2.41k | (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1), |
915 | 2.41k | (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1); |
916 | 2.41k | break; |
917 | | |
918 | 13.1k | case tic6x_coding_pcrel_half_unsigned: |
919 | 13.1k | operands_pcrel[op_num] = true; |
920 | 13.1k | operands_addresses[op_num] = fp_addr + 2 * fld_val; |
921 | 13.1k | break; |
922 | | |
923 | 27.6k | case tic6x_coding_reg_shift: |
924 | 27.6k | fld_val <<= 1; |
925 | | /* Fall through. */ |
926 | 1.69M | case tic6x_coding_reg: |
927 | 1.69M | if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS)) |
928 | 46.2k | { |
929 | 46.2k | reg_base = 16; |
930 | 46.2k | } |
931 | 1.69M | switch (opc->operand_info[op_num].form) |
932 | 1.69M | { |
933 | 6.99k | case tic6x_operand_treg: |
934 | 6.99k | if (!have_t) |
935 | 0 | { |
936 | 0 | printf ("opcode %x: operand treg but missing t field\n", opcode); |
937 | 0 | abort (); |
938 | 0 | } |
939 | 6.99k | operands_text[op_num] = true; |
940 | 6.99k | reg_side = t_val ? 'b' : 'a'; |
941 | 6.99k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
942 | 6.99k | break; |
943 | | |
944 | 715k | case tic6x_operand_reg: |
945 | 715k | operands_text[op_num] = true; |
946 | 715k | reg_side = (func_unit_side == 2) ? 'b' : 'a'; |
947 | 715k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
948 | 715k | break; |
949 | | |
950 | 1.64k | case tic6x_operand_reg_nors: |
951 | 1.64k | operands_text[op_num] = true; |
952 | 1.64k | reg_side = (func_unit_side == 2) ? 'b' : 'a'; |
953 | 1.64k | snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val); |
954 | 1.64k | break; |
955 | | |
956 | 28 | case tic6x_operand_reg_bside: |
957 | 28 | operands_text[op_num] = true; |
958 | 28 | snprintf (operands[op_num], 24, "b%u", reg_base + fld_val); |
959 | 28 | break; |
960 | | |
961 | 224 | case tic6x_operand_reg_bside_nors: |
962 | 224 | operands_text[op_num] = true; |
963 | 224 | snprintf (operands[op_num], 24, "b%u", fld_val); |
964 | 224 | break; |
965 | | |
966 | 316k | case tic6x_operand_xreg: |
967 | 316k | operands_text[op_num] = true; |
968 | 316k | reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a'; |
969 | 316k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
970 | 316k | break; |
971 | | |
972 | 328k | case tic6x_operand_dreg: |
973 | 328k | operands_text[op_num] = true; |
974 | 328k | reg_side = (func_unit_data_side == 2) ? 'b' : 'a'; |
975 | 328k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
976 | 328k | break; |
977 | | |
978 | 98.4k | case tic6x_operand_regpair: |
979 | 98.4k | operands_text[op_num] = true; |
980 | 98.4k | if (fld_val & 1) |
981 | 22.4k | operands_ok = false; |
982 | 98.4k | reg_side = (func_unit_side == 2) ? 'b' : 'a'; |
983 | 98.4k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
984 | 98.4k | reg_side, reg_base + fld_val + 1, |
985 | 98.4k | reg_side, reg_base + fld_val); |
986 | 98.4k | break; |
987 | | |
988 | 7.41k | case tic6x_operand_xregpair: |
989 | 7.41k | operands_text[op_num] = true; |
990 | 7.41k | if (fld_val & 1) |
991 | 2.76k | operands_ok = false; |
992 | 7.41k | reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a'; |
993 | 7.41k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
994 | 7.41k | reg_side, reg_base + fld_val + 1, |
995 | 7.41k | reg_side, reg_base + fld_val); |
996 | 7.41k | break; |
997 | | |
998 | 2.80k | case tic6x_operand_tregpair: |
999 | 2.80k | if (!have_t) |
1000 | 0 | { |
1001 | 0 | printf ("opcode %x: operand tregpair but missing t field\n", opcode); |
1002 | 0 | abort (); |
1003 | 0 | } |
1004 | 2.80k | operands_text[op_num] = true; |
1005 | 2.80k | if (fld_val & 1) |
1006 | 49 | operands_ok = false; |
1007 | 2.80k | reg_side = t_val ? 'b' : 'a'; |
1008 | 2.80k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
1009 | 2.80k | reg_side, reg_base + fld_val + 1, |
1010 | 2.80k | reg_side, reg_base + fld_val); |
1011 | 2.80k | break; |
1012 | | |
1013 | 44.3k | case tic6x_operand_dregpair: |
1014 | 44.3k | operands_text[op_num] = true; |
1015 | 44.3k | if (fld_val & 1) |
1016 | 7.43k | operands_ok = false; |
1017 | 44.3k | reg_side = (func_unit_data_side) == 2 ? 'b' : 'a'; |
1018 | 44.3k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
1019 | 44.3k | reg_side, reg_base + fld_val + 1, |
1020 | 44.3k | reg_side, reg_base + fld_val); |
1021 | 44.3k | break; |
1022 | | |
1023 | 7 | case tic6x_operand_mem_deref: |
1024 | 7 | operands_text[op_num] = true; |
1025 | 7 | reg_side = func_unit_side == 2 ? 'b' : 'a'; |
1026 | 7 | snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val); |
1027 | 7 | break; |
1028 | | |
1029 | 153k | case tic6x_operand_mem_short: |
1030 | 174k | case tic6x_operand_mem_ndw: |
1031 | 174k | mem_base_reg = fld_val; |
1032 | 174k | mem_base_reg_known = true; |
1033 | 174k | break; |
1034 | | |
1035 | 0 | default: |
1036 | 0 | printf ("opcode %x: unexpected operand form %d for operand #%d", |
1037 | 0 | opcode, opc->operand_info[op_num].form, op_num); |
1038 | 0 | abort (); |
1039 | 1.69M | } |
1040 | 1.69M | break; |
1041 | | |
1042 | 1.69M | case tic6x_coding_reg_ptr: |
1043 | 9.02k | switch (opc->operand_info[op_num].form) |
1044 | 9.02k | { |
1045 | 8.11k | case tic6x_operand_mem_short: |
1046 | 9.02k | case tic6x_operand_mem_ndw: |
1047 | 9.02k | if (fld_val > 0x3u) |
1048 | 0 | { |
1049 | 0 | printf("opcode %x: illegal field value for ptr register of operand #%d (%d)", |
1050 | 0 | opcode, op_num, fld_val); |
1051 | 0 | abort (); |
1052 | 0 | } |
1053 | 9.02k | mem_base_reg = 0x4 | fld_val; |
1054 | 9.02k | mem_base_reg_known = true; |
1055 | 9.02k | break; |
1056 | | |
1057 | 0 | default: |
1058 | 0 | printf ("opcode %x: unexpected operand form %d for operand #%d", |
1059 | 0 | opcode, opc->operand_info[op_num].form, op_num); |
1060 | 0 | abort (); |
1061 | 9.02k | } |
1062 | 9.02k | break; |
1063 | | |
1064 | 203k | case tic6x_coding_areg: |
1065 | 203k | switch (opc->operand_info[op_num].form) |
1066 | 203k | { |
1067 | 4.60k | case tic6x_operand_areg: |
1068 | 4.60k | operands_text[op_num] = true; |
1069 | 4.60k | snprintf (operands[op_num], 24, "b%u", |
1070 | 4.60k | fld_val ? 15u : 14u); |
1071 | 4.60k | break; |
1072 | | |
1073 | 198k | case tic6x_operand_mem_long: |
1074 | 198k | mem_base_reg = fld_val ? 15u : 14u; |
1075 | 198k | mem_base_reg_known_long = true; |
1076 | 198k | break; |
1077 | | |
1078 | 0 | default: |
1079 | 0 | printf ("opcode %x: bad operand form\n", opcode); |
1080 | 0 | abort (); |
1081 | 203k | } |
1082 | 203k | break; |
1083 | | |
1084 | 203k | case tic6x_coding_mem_offset_minus_one_noscale: |
1085 | 1.96k | case tic6x_coding_mem_offset_minus_one: |
1086 | 1.96k | fld_val += 1; |
1087 | | /* Fall through. */ |
1088 | 23.4k | case tic6x_coding_mem_offset_noscale: |
1089 | 184k | case tic6x_coding_mem_offset: |
1090 | 184k | mem_offset = fld_val; |
1091 | 184k | mem_offset_known = true; |
1092 | 184k | if (num_bits == 16) |
1093 | 9.80k | { |
1094 | 9.80k | mem_mode_known = true; |
1095 | 9.80k | mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags); |
1096 | 9.80k | mem_scaled_known = true; |
1097 | 9.80k | mem_scaled = true; |
1098 | 9.80k | if (opc->flags & TIC6X_FLAG_INSN16_B15PTR) |
1099 | 779 | { |
1100 | 779 | mem_base_reg_known = true; |
1101 | 779 | mem_base_reg = 15; |
1102 | 779 | } |
1103 | 9.80k | if ( enc->coding_method == tic6x_coding_mem_offset_noscale |
1104 | 9.80k | || enc->coding_method == tic6x_coding_mem_offset_noscale ) |
1105 | 874 | mem_scaled = false; |
1106 | 9.80k | } |
1107 | 184k | break; |
1108 | | |
1109 | 174k | case tic6x_coding_mem_mode: |
1110 | 174k | mem_mode = fld_val; |
1111 | 174k | mem_mode_known = true; |
1112 | 174k | break; |
1113 | | |
1114 | 20.6k | case tic6x_coding_scaled: |
1115 | 20.6k | mem_scaled = fld_val; |
1116 | 20.6k | mem_scaled_known = true; |
1117 | 20.6k | break; |
1118 | | |
1119 | 652 | case tic6x_coding_crlo: |
1120 | 652 | crlo = fld_val; |
1121 | 652 | crlo_known = true; |
1122 | 652 | break; |
1123 | | |
1124 | 652 | case tic6x_coding_crhi: |
1125 | 652 | crhi = fld_val; |
1126 | 652 | crhi_known = true; |
1127 | 652 | break; |
1128 | | |
1129 | 128 | case tic6x_coding_fstg: |
1130 | 256 | case tic6x_coding_fcyc: |
1131 | 256 | if (!prev_sploop_found) |
1132 | 256 | { |
1133 | 256 | bfd_vma search_fp_addr = fp_addr; |
1134 | 256 | bfd_vma search_fp_offset = fp_offset; |
1135 | 256 | bool search_fp_header_based |
1136 | 256 | = fetch_packet_header_based; |
1137 | 256 | tic6x_fetch_packet_header search_fp_header = header; |
1138 | 256 | unsigned char search_fp[32]; |
1139 | 256 | unsigned int search_num_bits; |
1140 | 256 | unsigned int search_opcode; |
1141 | 256 | unsigned int sploop_ii = 0; |
1142 | 256 | int i; |
1143 | | |
1144 | 256 | memcpy (search_fp, fp, 32); |
1145 | | |
1146 | | /* To interpret these bits in an SPKERNEL |
1147 | | instruction, we must find the previous |
1148 | | SPLOOP-family instruction. It may come up to |
1149 | | 48 execute packets earlier. */ |
1150 | 85.1k | for (i = 0; i < 48 * 8; i++) |
1151 | 84.9k | { |
1152 | | /* Find the previous instruction. */ |
1153 | 84.9k | if (search_fp_offset & 2) |
1154 | 3.64k | search_fp_offset -= 2; |
1155 | 81.2k | else if (search_fp_offset >= 4) |
1156 | 70.9k | { |
1157 | 70.9k | if (search_fp_header_based |
1158 | 70.9k | && (search_fp_header.word_compact |
1159 | 5.79k | [(search_fp_offset >> 2) - 1])) |
1160 | 3.05k | search_fp_offset -= 2; |
1161 | 67.8k | else |
1162 | 67.8k | search_fp_offset -= 4; |
1163 | 70.9k | } |
1164 | 10.3k | else |
1165 | 10.3k | { |
1166 | 10.3k | search_fp_addr -= 32; |
1167 | 10.3k | status = info->read_memory_func (search_fp_addr, |
1168 | 10.3k | search_fp, |
1169 | 10.3k | 32, info); |
1170 | 10.3k | if (status) |
1171 | | /* No previous SPLOOP instruction. */ |
1172 | 70 | break; |
1173 | 10.2k | search_fp_header_based |
1174 | 10.2k | = (tic6x_check_fetch_packet_header |
1175 | 10.2k | (search_fp, &search_fp_header, info)); |
1176 | 10.2k | if (search_fp_header_based) |
1177 | 900 | search_fp_offset |
1178 | 900 | = search_fp_header.word_compact[6] ? 26 : 24; |
1179 | 9.39k | else |
1180 | 9.39k | search_fp_offset = 28; |
1181 | 10.2k | } |
1182 | | |
1183 | | /* Extract the previous instruction. */ |
1184 | 84.8k | if (search_fp_header_based) |
1185 | 10.3k | search_num_bits |
1186 | 10.3k | = (search_fp_header.word_compact[search_fp_offset |
1187 | 10.3k | >> 2] |
1188 | 10.3k | ? 16 |
1189 | 10.3k | : 32); |
1190 | 74.5k | else |
1191 | 74.5k | search_num_bits = 32; |
1192 | 84.8k | if (search_num_bits == 16) |
1193 | 7.25k | { |
1194 | 7.25k | if (info->endian == BFD_ENDIAN_LITTLE) |
1195 | 0 | search_opcode |
1196 | 0 | = (tic6x_extract_16 |
1197 | 0 | (search_fp + search_fp_offset, &header, info)); |
1198 | 7.25k | else |
1199 | 7.25k | search_opcode |
1200 | 7.25k | = (tic6x_extract_16 |
1201 | 7.25k | (search_fp + (search_fp_offset ^ 2), &header, |
1202 | 7.25k | info)); |
1203 | 7.25k | } |
1204 | 77.6k | else |
1205 | 77.6k | search_opcode |
1206 | 77.6k | = tic6x_extract_32 (search_fp + search_fp_offset, |
1207 | 77.6k | info); |
1208 | | |
1209 | | /* Check whether it is an SPLOOP-family |
1210 | | instruction. */ |
1211 | 84.8k | if (search_num_bits == 32 |
1212 | 84.8k | && ((search_opcode & 0x003ffffe) == 0x00038000 |
1213 | 77.6k | || (search_opcode & 0x003ffffe) == 0x0003a000 |
1214 | 77.6k | || ((search_opcode & 0x003ffffe) |
1215 | 77.6k | == 0x0003e000))) |
1216 | 2 | { |
1217 | 2 | prev_sploop_found = true; |
1218 | 2 | sploop_ii = ((search_opcode >> 23) & 0x1f) + 1; |
1219 | 2 | } |
1220 | 84.8k | else if (search_num_bits == 16 |
1221 | 84.8k | && (search_opcode & 0x3c7e) == 0x0c66) |
1222 | 4 | { |
1223 | 4 | prev_sploop_found = true; |
1224 | 4 | sploop_ii |
1225 | 4 | = (((search_opcode >> 7) & 0x7) |
1226 | 4 | | ((search_opcode >> 11) & 0x8)) + 1; |
1227 | 4 | } |
1228 | 84.8k | if (prev_sploop_found) |
1229 | 6 | { |
1230 | 6 | if (sploop_ii <= 0) |
1231 | 0 | { |
1232 | 0 | printf ("opcode %x: sloop index not found (%d)\n", opcode, sploop_ii); |
1233 | 0 | abort (); |
1234 | 0 | } |
1235 | 6 | else if (sploop_ii <= 1) |
1236 | 0 | fcyc_bits = 0; |
1237 | 6 | else if (sploop_ii <= 2) |
1238 | 0 | fcyc_bits = 1; |
1239 | 6 | else if (sploop_ii <= 4) |
1240 | 0 | fcyc_bits = 2; |
1241 | 6 | else if (sploop_ii <= 8) |
1242 | 2 | fcyc_bits = 3; |
1243 | 4 | else if (sploop_ii <= 14) |
1244 | 4 | fcyc_bits = 4; |
1245 | 0 | else |
1246 | 0 | prev_sploop_found = false; |
1247 | 6 | } |
1248 | 84.8k | if (prev_sploop_found) |
1249 | 6 | break; |
1250 | 84.8k | } |
1251 | 256 | } |
1252 | 256 | if (!prev_sploop_found) |
1253 | 250 | { |
1254 | 250 | operands_ok = false; |
1255 | 250 | operands_text[op_num] = true; |
1256 | 250 | break; |
1257 | 250 | } |
1258 | 6 | if (fcyc_bits > tic6x_field_width(field)) |
1259 | 0 | { |
1260 | 0 | printf ("opcode %x: illegal fcyc value (%d)\n", opcode, fcyc_bits); |
1261 | 0 | abort (); |
1262 | 0 | } |
1263 | 6 | if (enc->coding_method == tic6x_coding_fstg) |
1264 | 3 | { |
1265 | 3 | int i, t; |
1266 | 10 | for (t = 0, i = fcyc_bits; i < 6; i++) |
1267 | 7 | t = (t << 1) | ((fld_val >> i) & 1); |
1268 | 3 | operands_text[op_num] = true; |
1269 | 3 | snprintf (operands[op_num], 24, "%u", t); |
1270 | 3 | } |
1271 | 3 | else |
1272 | 3 | { |
1273 | 3 | operands_text[op_num] = true; |
1274 | 3 | snprintf (operands[op_num], 24, "%u", |
1275 | 3 | fld_val & ((1 << fcyc_bits) - 1)); |
1276 | 3 | } |
1277 | 6 | break; |
1278 | | |
1279 | 12.5k | case tic6x_coding_spmask: |
1280 | 12.5k | if (fld_val == 0) |
1281 | 611 | spmask_skip_operand = true; |
1282 | 11.9k | else |
1283 | 11.9k | { |
1284 | 11.9k | char *p; |
1285 | 11.9k | unsigned int i; |
1286 | | |
1287 | 11.9k | operands_text[op_num] = true; |
1288 | 11.9k | p = operands[op_num]; |
1289 | 107k | for (i = 0; i < 8; i++) |
1290 | 95.8k | if (fld_val & (1 << i)) |
1291 | 36.5k | { |
1292 | 36.5k | *p++ = "LSDM"[i/2]; |
1293 | 36.5k | *p++ = '1' + (i & 1); |
1294 | 36.5k | *p++ = ','; |
1295 | 36.5k | } |
1296 | 11.9k | p[-1] = 0; |
1297 | 11.9k | } |
1298 | 12.5k | break; |
1299 | | |
1300 | 713k | case tic6x_coding_fu: |
1301 | 1.08M | case tic6x_coding_data_fu: |
1302 | 1.40M | case tic6x_coding_xpath: |
1303 | 1.41M | case tic6x_coding_rside: |
1304 | | /* Don't relate to operands, so operand number is |
1305 | | meaningless. */ |
1306 | 1.41M | break; |
1307 | | |
1308 | 0 | default: |
1309 | 0 | printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method); |
1310 | 0 | abort (); |
1311 | 4.32M | } |
1312 | | |
1313 | 4.32M | if (mem_base_reg_known_long && mem_offset_known_long) |
1314 | 198k | { |
1315 | 198k | if (operands_text[op_num] || operands_pcrel[op_num]) |
1316 | 0 | { |
1317 | 0 | printf ("opcode %x: long access but operands already known ?\n", opcode); |
1318 | 0 | abort (); |
1319 | 0 | } |
1320 | 198k | operands_text[op_num] = true; |
1321 | 198k | snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg, |
1322 | 198k | mem_offset * opc->operand_info[op_num].size); |
1323 | 198k | } |
1324 | | |
1325 | 4.32M | if (mem_base_reg_known && mem_offset_known && mem_mode_known |
1326 | 4.32M | && (mem_scaled_known |
1327 | 204k | || (opc->operand_info[op_num].form |
1328 | 174k | != tic6x_operand_mem_ndw))) |
1329 | 184k | { |
1330 | 184k | char side; |
1331 | 184k | char base[4]; |
1332 | 184k | bool offset_is_reg; |
1333 | 184k | bool offset_scaled; |
1334 | 184k | char offset[4]; |
1335 | 184k | char offsetp[6]; |
1336 | | |
1337 | 184k | if (operands_text[op_num] || operands_pcrel[op_num]) |
1338 | 0 | { |
1339 | 0 | printf ("opcode %x: mem access operands already known ?\n", opcode); |
1340 | 0 | abort (); |
1341 | 0 | } |
1342 | | |
1343 | 184k | side = func_unit_side == 2 ? 'b' : 'a'; |
1344 | 184k | snprintf (base, 4, "%c%u", side, mem_base_reg); |
1345 | | |
1346 | 184k | offset_is_reg = (mem_mode & 4) != 0; |
1347 | 184k | if (offset_is_reg) |
1348 | 60.9k | { |
1349 | | |
1350 | 60.9k | if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS)) |
1351 | 570 | { |
1352 | 570 | reg_base = 16; |
1353 | 570 | } |
1354 | 60.9k | snprintf (offset, 4, "%c%u", side, reg_base + mem_offset); |
1355 | 60.9k | if (opc->operand_info[op_num].form |
1356 | 60.9k | == tic6x_operand_mem_ndw) |
1357 | 8.24k | offset_scaled = mem_scaled != 0; |
1358 | 52.7k | else |
1359 | 52.7k | offset_scaled = true; |
1360 | 60.9k | } |
1361 | 123k | else |
1362 | 123k | { |
1363 | 123k | if (opc->operand_info[op_num].form |
1364 | 123k | == tic6x_operand_mem_ndw) |
1365 | 13.3k | { |
1366 | 13.3k | offset_scaled = mem_scaled != 0; |
1367 | 13.3k | snprintf (offset, 4, "%u", mem_offset); |
1368 | 13.3k | } |
1369 | 110k | else |
1370 | 110k | { |
1371 | 110k | offset_scaled = false; |
1372 | 110k | snprintf (offset, 4, "%u", |
1373 | 110k | (mem_offset |
1374 | 110k | * opc->operand_info[op_num].size)); |
1375 | 110k | } |
1376 | 123k | } |
1377 | | |
1378 | 184k | if (offset_scaled) |
1379 | 59.9k | snprintf (offsetp, 6, "[%s]", offset); |
1380 | 124k | else |
1381 | 124k | snprintf (offsetp, 6, "(%s)", offset); |
1382 | | |
1383 | 184k | operands_text[op_num] = true; |
1384 | 184k | switch (mem_mode & ~4u) |
1385 | 184k | { |
1386 | 53.6k | case 0: |
1387 | 53.6k | snprintf (operands[op_num], 24, "*-%s%s", base, offsetp); |
1388 | 53.6k | break; |
1389 | | |
1390 | 21.2k | case 1: |
1391 | 21.2k | snprintf (operands[op_num], 24, "*+%s%s", base, offsetp); |
1392 | 21.2k | break; |
1393 | | |
1394 | 23.7k | case 2: |
1395 | 41.7k | case 3: |
1396 | 41.7k | operands_ok = false; |
1397 | 41.7k | break; |
1398 | | |
1399 | 16.3k | case 8: |
1400 | 16.3k | snprintf (operands[op_num], 24, "*--%s%s", base, |
1401 | 16.3k | offsetp); |
1402 | 16.3k | break; |
1403 | | |
1404 | 15.7k | case 9: |
1405 | 15.7k | snprintf (operands[op_num], 24, "*++%s%s", base, |
1406 | 15.7k | offsetp); |
1407 | 15.7k | break; |
1408 | | |
1409 | 13.9k | case 10: |
1410 | 13.9k | snprintf (operands[op_num], 24, "*%s--%s", base, |
1411 | 13.9k | offsetp); |
1412 | 13.9k | break; |
1413 | | |
1414 | 21.7k | case 11: |
1415 | 21.7k | snprintf (operands[op_num], 24, "*%s++%s", base, |
1416 | 21.7k | offsetp); |
1417 | 21.7k | break; |
1418 | | |
1419 | 0 | default: |
1420 | 0 | printf ("*** unknown mem_mode : %d \n", mem_mode); |
1421 | 0 | abort (); |
1422 | 184k | } |
1423 | 184k | } |
1424 | | |
1425 | 4.32M | if (crlo_known && crhi_known) |
1426 | 652 | { |
1427 | 652 | tic6x_rw rw; |
1428 | 652 | tic6x_ctrl_id crid; |
1429 | | |
1430 | 652 | if (operands_text[op_num] || operands_pcrel[op_num]) |
1431 | 0 | { |
1432 | 0 | printf ("*** abort crlo crli\n"); |
1433 | 0 | abort (); |
1434 | 0 | } |
1435 | | |
1436 | 652 | rw = opc->operand_info[op_num].rw; |
1437 | 652 | if (rw != tic6x_rw_read |
1438 | 652 | && rw != tic6x_rw_write) |
1439 | 0 | { |
1440 | 0 | printf ("*** abort rw : %d\n", rw); |
1441 | 0 | abort (); |
1442 | 0 | } |
1443 | | |
1444 | 19.1k | for (crid = 0; crid < tic6x_ctrl_max; crid++) |
1445 | 18.5k | { |
1446 | 18.5k | if (crlo == tic6x_ctrl_table[crid].crlo |
1447 | 18.5k | && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0 |
1448 | 18.5k | && (rw == tic6x_rw_read |
1449 | 24 | ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read |
1450 | 14 | || (tic6x_ctrl_table[crid].rw |
1451 | 14 | == tic6x_rw_read_write)) |
1452 | 24 | : (tic6x_ctrl_table[crid].rw == tic6x_rw_write |
1453 | 10 | || (tic6x_ctrl_table[crid].rw |
1454 | 2 | == tic6x_rw_read_write)))) |
1455 | 24 | break; |
1456 | 18.5k | } |
1457 | 652 | if (crid == tic6x_ctrl_max) |
1458 | 628 | { |
1459 | 628 | operands_text[op_num] = true; |
1460 | 628 | operands_ok = false; |
1461 | 628 | } |
1462 | 24 | else |
1463 | 24 | { |
1464 | 24 | operands_text[op_num] = true; |
1465 | 24 | snprintf (operands[op_num], 24, "%s", |
1466 | 24 | tic6x_ctrl_table[crid].name); |
1467 | 24 | } |
1468 | 652 | } |
1469 | | |
1470 | 4.32M | if (operands_text[op_num] || operands_pcrel[op_num] |
1471 | 4.32M | || spmask_skip_operand) |
1472 | 2.32M | break; |
1473 | 4.32M | } |
1474 | | /* end for fld_num */ |
1475 | | |
1476 | 2.32M | if (spmask_skip_operand) |
1477 | 611 | { |
1478 | | /* SPMASK operands are only valid as the single operand |
1479 | | in the opcode table. */ |
1480 | 611 | if (num_operands != 1) |
1481 | 0 | { |
1482 | 0 | printf ("opcode: %x, num_operands != 1 : %d\n", opcode, num_operands); |
1483 | 0 | abort (); |
1484 | 0 | } |
1485 | 611 | num_operands = 0; |
1486 | 611 | break; |
1487 | 611 | } |
1488 | | |
1489 | | /* The operand must by now have been decoded. */ |
1490 | 2.32M | if (!operands_text[op_num] && !operands_pcrel[op_num]) |
1491 | 0 | { |
1492 | 0 | printf ("opcode: %x, operand #%d not decoded\n", opcode, op_num); |
1493 | 0 | abort (); |
1494 | 0 | } |
1495 | 2.32M | } |
1496 | | /* end for op_num */ |
1497 | | |
1498 | 1.02M | if (!operands_ok) |
1499 | 70.5k | continue; |
1500 | | |
1501 | 955k | info->bytes_per_chunk = num_bits / 8; |
1502 | 955k | info->fprintf_func (info->stream, "%s", parallel); |
1503 | 955k | info->fprintf_func (info->stream, "%s%s%s", cond, opc->name, |
1504 | 955k | func_unit); |
1505 | 3.13M | for (op_num = 0; op_num < num_operands; op_num++) |
1506 | 2.18M | { |
1507 | 2.18M | info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ',')); |
1508 | 2.18M | if (operands_pcrel[op_num]) |
1509 | 52.7k | info->print_address_func (operands_addresses[op_num], info); |
1510 | 2.12M | else |
1511 | 2.12M | info->fprintf_func (info->stream, "%s", operands[op_num]); |
1512 | 2.18M | } |
1513 | 955k | if (fetch_packet_header_based && header.prot) |
1514 | 23.8k | info->fprintf_func (info->stream, " || nop 5"); |
1515 | | |
1516 | 955k | return num_bits / 8; |
1517 | 1.02M | } |
1518 | | |
1519 | 596k | info->bytes_per_chunk = num_bits / 8; |
1520 | 596k | info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>", |
1521 | 596k | (int) num_bits / 4, opcode); |
1522 | 596k | return num_bits / 8; |
1523 | 1.55M | } |