/src/binutils-gdb/opcodes/tic6x-dis.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* TI C6X disassembler. |
2 | | Copyright (C) 2010-2023 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 | 20.6M | { |
116 | 20.6M | unsigned int f; |
117 | | |
118 | 74.1M | for (f = 0; f < fmt->num_fields; f++) |
119 | 74.0M | if (fmt->fields[f].field_id == field) |
120 | 20.5M | return &fmt->fields[f]; |
121 | | |
122 | 103k | return NULL; |
123 | 20.6M | } |
124 | | |
125 | | /* Extract the field width. */ |
126 | | |
127 | | static unsigned int |
128 | | tic6x_field_width (const tic6x_insn_field *field) |
129 | 75.3k | { |
130 | 75.3k | unsigned int i; |
131 | 75.3k | unsigned int width = 0; |
132 | | |
133 | 75.3k | if (!field->num_bitfields) |
134 | 0 | return field->bitfields[0].width; |
135 | | |
136 | 151k | for (i = 0 ; i < field->num_bitfields ; i++) |
137 | 76.5k | width += field->bitfields[i].width; |
138 | | |
139 | 75.3k | return width; |
140 | 75.3k | } |
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 | 20.5M | { |
147 | 20.5M | unsigned int i; |
148 | 20.5M | unsigned int val = 0; |
149 | | |
150 | 20.5M | if (!field->num_bitfields) |
151 | 0 | return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1); |
152 | | |
153 | 41.0M | for (i = 0 ; i < field->num_bitfields ; i++) |
154 | 20.5M | val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1)) |
155 | 20.5M | << field->bitfields[i].pos; |
156 | | |
157 | 20.5M | return val; |
158 | 20.5M | } |
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 | 989k | { |
165 | 989k | if (info->endian == BFD_ENDIAN_LITTLE) |
166 | 92 | return p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned) p[3] << 24); |
167 | 989k | else |
168 | 989k | return p[3] | (p[2] << 8) | (p[1] << 16) | ((unsigned) p[0] << 24); |
169 | 989k | } |
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 | 14.8k | { |
177 | 14.8k | unsigned int op16; |
178 | | |
179 | 14.8k | if (info->endian == BFD_ENDIAN_LITTLE) |
180 | 28 | op16 = (p[0]) | (p[1] << 8); |
181 | 14.8k | else |
182 | 14.8k | op16 = (p[1]) | (p[0] << 8); |
183 | 14.8k | op16 |= (header->sat << TIC6X_COMPACT_SAT_POS); |
184 | 14.8k | op16 |= (header->br << TIC6X_COMPACT_BR_POS); |
185 | 14.8k | op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS); |
186 | 14.8k | return op16; |
187 | 14.8k | } |
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 | 390k | { |
197 | 390k | int i; |
198 | | |
199 | 390k | header->header = tic6x_extract_32 (fp + 28, info); |
200 | | |
201 | 390k | if ((header->header & 0xf0000000) != 0xe0000000) |
202 | 366k | { |
203 | 366k | header->prot = 0; |
204 | 366k | header->rs = 0; |
205 | 366k | header->dsz = 0; |
206 | 366k | header->br = 0; |
207 | 366k | header->sat = 0; |
208 | 2.93M | for (i = 0; i < 7; i++) |
209 | 2.56M | header->word_compact[i] = false; |
210 | 5.50M | for (i = 0; i < 14; i++) |
211 | 5.13M | header->p_bits[i] = false; |
212 | 366k | return false; |
213 | 366k | } |
214 | | |
215 | 190k | for (i = 0; i < 7; i++) |
216 | 166k | header->word_compact[i] |
217 | 166k | = (header->header & (1u << (21 + i))) != 0; |
218 | | |
219 | 23.7k | header->prot = (header->header & (1u << 20)) != 0; |
220 | 23.7k | header->rs = (header->header & (1u << 19)) != 0; |
221 | 23.7k | header->dsz = (header->header >> 16) & 0x7; |
222 | 23.7k | header->br = (header->header & (1u << 15)) != 0; |
223 | 23.7k | header->sat = (header->header & (1u << 14)) != 0; |
224 | | |
225 | 356k | for (i = 0; i < 14; i++) |
226 | 332k | header->p_bits[i] = (header->header & (1u << i)) != 0; |
227 | | |
228 | 23.7k | return true; |
229 | 390k | } |
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 | 357k | { |
238 | 357k | int status; |
239 | 357k | bfd_vma fp_addr; |
240 | 357k | bfd_vma fp_offset; |
241 | 357k | unsigned char fp[32]; |
242 | 357k | unsigned int opcode; |
243 | 357k | tic6x_opcode_id opcode_id; |
244 | 357k | bool fetch_packet_header_based; |
245 | 357k | tic6x_fetch_packet_header header; |
246 | 357k | unsigned int num_bits; |
247 | 357k | bool bad_offset = false; |
248 | | |
249 | 357k | fp_offset = addr & 0x1f; |
250 | 357k | 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 | 357k | info->stop_vma = 0; |
254 | 357k | status = info->read_memory_func (fp_addr, fp, 32, info); |
255 | 357k | if (status) |
256 | 464 | { |
257 | 464 | info->memory_error_func (status, addr, info); |
258 | 464 | return -1; |
259 | 464 | } |
260 | | |
261 | 357k | fetch_packet_header_based |
262 | 357k | = tic6x_check_fetch_packet_header (fp, &header, info); |
263 | 357k | if (fetch_packet_header_based) |
264 | 22.4k | { |
265 | 22.4k | if (fp_offset & 0x1) |
266 | 20 | bad_offset = true; |
267 | 22.4k | if ((fp_offset & 0x3) && (fp_offset >= 28 |
268 | 7.17k | || !header.word_compact[fp_offset >> 2])) |
269 | 40 | bad_offset = true; |
270 | 22.4k | if (fp_offset == 28) |
271 | 1.95k | { |
272 | 1.95k | info->bytes_per_chunk = 4; |
273 | 1.95k | info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>", |
274 | 1.95k | header.header); |
275 | 1.95k | return 4; |
276 | 1.95k | } |
277 | 20.4k | num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32); |
278 | 20.4k | } |
279 | 334k | else |
280 | 334k | { |
281 | 334k | num_bits = 32; |
282 | 334k | if (fp_offset & 0x3) |
283 | 4 | bad_offset = true; |
284 | 334k | } |
285 | | |
286 | 355k | if (bad_offset) |
287 | 44 | { |
288 | 44 | info->bytes_per_chunk = 1; |
289 | 44 | info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]); |
290 | 44 | return 1; |
291 | 44 | } |
292 | | |
293 | 355k | if (num_bits == 16) |
294 | 14.3k | { |
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 | 14.3k | if (info->endian == BFD_ENDIAN_LITTLE) |
301 | 28 | opcode = tic6x_extract_16 (fp + fp_offset, &header, info); |
302 | 14.2k | else |
303 | 14.2k | opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info); |
304 | 14.3k | } |
305 | 340k | else |
306 | 340k | opcode = tic6x_extract_32 (fp + fp_offset, info); |
307 | | |
308 | 139M | for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++) |
309 | 139M | { |
310 | 139M | const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id]; |
311 | 139M | const tic6x_insn_format *const fmt |
312 | 139M | = &tic6x_insn_format_table[opc->format]; |
313 | 139M | const tic6x_insn_field *creg_field; |
314 | 139M | bool p_bit; |
315 | 139M | const char *parallel; |
316 | 139M | const char *cond = ""; |
317 | 139M | const char *func_unit; |
318 | 139M | char func_unit_buf[8]; |
319 | 139M | unsigned int func_unit_side = 0; |
320 | 139M | unsigned int func_unit_data_side = 0; |
321 | 139M | unsigned int func_unit_cross = 0; |
322 | 139M | 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 | 139M | char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } }; |
327 | 139M | bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 }; |
328 | 139M | bool operands_text[TIC6X_MAX_OPERANDS] = { false }; |
329 | 139M | bool operands_pcrel[TIC6X_MAX_OPERANDS] = { false }; |
330 | 139M | unsigned int fix; |
331 | 139M | unsigned int num_operands; |
332 | 139M | unsigned int op_num; |
333 | 139M | bool fixed_ok; |
334 | 139M | bool operands_ok; |
335 | 139M | bool have_t = false; |
336 | | |
337 | 139M | if (opc->flags & TIC6X_FLAG_MACRO) |
338 | 14.8M | continue; |
339 | 124M | if (fmt->num_bits != num_bits) |
340 | 40.8M | continue; |
341 | 83.8M | if ((opcode & fmt->mask) != fmt->cst_bits) |
342 | 77.2M | 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 | 6.53M | creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg); |
349 | 6.53M | if (creg_field) |
350 | 6.43M | { |
351 | 6.43M | const tic6x_insn_field *z_field; |
352 | 6.43M | unsigned int creg_value, z_value; |
353 | 6.43M | static const char *const conds[8][2] = |
354 | 6.43M | { |
355 | 6.43M | { "", NULL }, |
356 | 6.43M | { "[b0] ", "[!b0] " }, |
357 | 6.43M | { "[b1] ", "[!b1] " }, |
358 | 6.43M | { "[b2] ", "[!b2] " }, |
359 | 6.43M | { "[a1] ", "[!a1] " }, |
360 | 6.43M | { "[a2] ", "[!a2] " }, |
361 | 6.43M | { "[a0] ", "[!a0] " }, |
362 | 6.43M | { NULL, NULL } |
363 | 6.43M | }; |
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 | 6.43M | z_field = tic6x_field_from_fmt (fmt, tic6x_field_z); |
369 | 6.43M | if (!z_field) |
370 | 0 | { |
371 | 0 | printf ("*** opcode %x: missing z field", opcode); |
372 | 0 | abort (); |
373 | 0 | } |
374 | | |
375 | 6.43M | creg_value = tic6x_field_bits (opcode, creg_field); |
376 | 6.43M | z_value = tic6x_field_bits (opcode, z_field); |
377 | 6.43M | cond = conds[creg_value][z_value]; |
378 | 6.43M | if (cond == NULL) |
379 | 1.15M | continue; |
380 | 6.43M | } |
381 | | |
382 | 5.38M | if (opc->flags & TIC6X_FLAG_INSN16_SPRED) |
383 | 2.44k | { |
384 | 2.44k | const tic6x_insn_field *cc_field; |
385 | 2.44k | unsigned int s_value = 0; |
386 | 2.44k | unsigned int z_value = 0; |
387 | 2.44k | bool cond_known = false; |
388 | 2.44k | static const char *const conds[2][2] = |
389 | 2.44k | { |
390 | 2.44k | { "[a0] ", "[!a0] " }, |
391 | 2.44k | { "[b0] ", "[!b0] " } |
392 | 2.44k | }; |
393 | | |
394 | 2.44k | cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc); |
395 | | |
396 | 2.44k | if (cc_field) |
397 | 144 | { |
398 | 144 | unsigned int cc_value; |
399 | | |
400 | 144 | cc_value = tic6x_field_bits (opcode, cc_field); |
401 | 144 | s_value = (cc_value & 0x2) >> 1; |
402 | 144 | z_value = (cc_value & 0x1); |
403 | 144 | cond_known = true; |
404 | 144 | } |
405 | 2.30k | else |
406 | 2.30k | { |
407 | 2.30k | const tic6x_insn_field *z_field; |
408 | 2.30k | const tic6x_insn_field *s_field; |
409 | | |
410 | 2.30k | s_field = tic6x_field_from_fmt (fmt, tic6x_field_s); |
411 | | |
412 | 2.30k | 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 | 2.30k | s_value = tic6x_field_bits (opcode, s_field); |
419 | 2.30k | z_field = tic6x_field_from_fmt (fmt, tic6x_field_z); |
420 | 2.30k | 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 | 2.30k | z_value = tic6x_field_bits (opcode, z_field); |
427 | 2.30k | cond_known = true; |
428 | 2.30k | } |
429 | | |
430 | 2.44k | if (!cond_known) |
431 | 0 | { |
432 | 0 | printf ("opcode %x: unspecified ompact insn predicate\n", opcode); |
433 | 0 | abort (); |
434 | 0 | } |
435 | 2.44k | cond = conds[s_value][z_value]; |
436 | 2.44k | } |
437 | | |
438 | | /* All fixed fields must have matching values; all fields with |
439 | | restricted ranges must have values within those ranges. */ |
440 | 5.38M | fixed_ok = true; |
441 | 5.77M | for (fix = 0; fix < opc->num_fixed_fields; fix++) |
442 | 5.51M | { |
443 | 5.51M | unsigned int field_bits; |
444 | 5.51M | const tic6x_insn_field *const field |
445 | 5.51M | = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id); |
446 | | |
447 | 5.51M | 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 | 5.51M | field_bits = tic6x_field_bits (opcode, field); |
455 | 5.51M | if (field_bits < opc->fixed_fields[fix].min_val |
456 | 5.51M | || field_bits > opc->fixed_fields[fix].max_val) |
457 | 5.13M | { |
458 | 5.13M | fixed_ok = false; |
459 | 5.13M | break; |
460 | 5.13M | } |
461 | 5.51M | } |
462 | 5.38M | if (!fixed_ok) |
463 | 5.13M | 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 | 252k | if (num_bits == 16 && (fp_offset & 0x2) == 2) |
473 | 6.19k | { |
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 | 6.19k | p_bit = header.p_bits[(fp_offset >> 2) << 1]; |
479 | 6.19k | } |
480 | 246k | else if (fp_offset >= 4) |
481 | 214k | { |
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 | 214k | if (fetch_packet_header_based |
486 | 214k | && header.word_compact[(fp_offset >> 2) - 1]) |
487 | 4.36k | p_bit = header.p_bits[(fp_offset >> 1) - 1]; |
488 | 210k | else |
489 | 210k | { |
490 | 210k | unsigned int prev_opcode |
491 | 210k | = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info); |
492 | 210k | p_bit = (prev_opcode & 0x1) != 0; |
493 | 210k | } |
494 | 214k | } |
495 | 31.9k | else |
496 | 31.9k | { |
497 | | /* Find the last instruction of the previous fetch |
498 | | packet. */ |
499 | 31.9k | unsigned char fp_prev[32]; |
500 | | |
501 | 31.9k | status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info); |
502 | 31.9k | if (status) |
503 | | /* No previous instruction to be parallel with. */ |
504 | 657 | p_bit = false; |
505 | 31.2k | else |
506 | 31.2k | { |
507 | 31.2k | bool prev_header_based; |
508 | 31.2k | tic6x_fetch_packet_header prev_header; |
509 | | |
510 | 31.2k | prev_header_based |
511 | 31.2k | = tic6x_check_fetch_packet_header (fp_prev, &prev_header, info); |
512 | 31.2k | if (prev_header_based) |
513 | 1.24k | { |
514 | 1.24k | if (prev_header.word_compact[6]) |
515 | 655 | p_bit = prev_header.p_bits[13]; |
516 | 590 | else |
517 | 590 | { |
518 | 590 | unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 24, |
519 | 590 | info); |
520 | 590 | p_bit = (prev_opcode & 0x1) != 0; |
521 | 590 | } |
522 | 1.24k | } |
523 | 30.0k | else |
524 | 30.0k | { |
525 | 30.0k | unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28, |
526 | 30.0k | info); |
527 | 30.0k | p_bit = (prev_opcode & 0x1) != 0; |
528 | 30.0k | } |
529 | 31.2k | } |
530 | 31.9k | } |
531 | 252k | parallel = p_bit ? "|| " : ""; |
532 | | |
533 | 252k | if (opc->func_unit == tic6x_func_unit_nfu) |
534 | 24.8k | func_unit = ""; |
535 | 228k | else |
536 | 228k | { |
537 | 228k | unsigned int fld_num; |
538 | 228k | char func_unit_char; |
539 | 228k | const char *data_str; |
540 | 228k | bool have_areg = false; |
541 | 228k | bool have_cross = false; |
542 | | |
543 | 228k | func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0; |
544 | 228k | func_unit_cross = 0; |
545 | 228k | func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0; |
546 | | |
547 | 1.27M | for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++) |
548 | 1.05M | { |
549 | 1.05M | const tic6x_coding_field *const enc = &opc->variable_fields[fld_num]; |
550 | 1.05M | const tic6x_insn_field *field; |
551 | 1.05M | unsigned int fld_val; |
552 | | |
553 | 1.05M | field = tic6x_field_from_fmt (fmt, enc->field_id); |
554 | | |
555 | 1.05M | 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 | 1.05M | fld_val = tic6x_field_bits (opcode, field); |
563 | | |
564 | 1.05M | switch (enc->coding_method) |
565 | 1.05M | { |
566 | 177k | case tic6x_coding_fu: |
567 | | /* The side must be specified exactly once. */ |
568 | 177k | 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 | 177k | func_unit_side = (fld_val ? 2 : 1); |
575 | 177k | break; |
576 | | |
577 | 94.1k | case tic6x_coding_data_fu: |
578 | | /* The data side must be specified exactly once. */ |
579 | 94.1k | 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 | 94.1k | func_unit_data_side = (fld_val ? 2 : 1); |
586 | 94.1k | break; |
587 | | |
588 | 75.4k | case tic6x_coding_xpath: |
589 | | /* Cross path use must be specified exactly |
590 | | once. */ |
591 | 75.4k | 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 | 75.4k | have_cross = true; |
598 | 75.4k | func_unit_cross = fld_val; |
599 | 75.4k | break; |
600 | | |
601 | 2.76k | case tic6x_coding_rside: |
602 | | /* If the format has a t field, use it for src/dst register side. */ |
603 | 2.76k | have_t = true; |
604 | 2.76k | t_val = fld_val; |
605 | 2.76k | func_unit_data_side = (t_val ? 2 : 1); |
606 | 2.76k | break; |
607 | | |
608 | 51.3k | case tic6x_coding_areg: |
609 | 51.3k | have_areg = true; |
610 | 51.3k | break; |
611 | | |
612 | 649k | default: |
613 | | /* Don't relate to functional units. */ |
614 | 649k | break; |
615 | 1.05M | } |
616 | 1.05M | } |
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 | 228k | 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 | 228k | 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 | 228k | 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 | 228k | if (have_areg && !func_unit_data_side) |
650 | 1.25k | { |
651 | 1.25k | 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 | 1.25k | func_unit_cross = func_unit_side == 1; |
657 | 1.25k | } |
658 | | |
659 | 228k | switch (opc->func_unit) |
660 | 228k | { |
661 | 102k | case tic6x_func_unit_d: |
662 | 102k | func_unit_char = 'D'; |
663 | 102k | break; |
664 | | |
665 | 16.8k | case tic6x_func_unit_l: |
666 | 16.8k | func_unit_char = 'L'; |
667 | 16.8k | break; |
668 | | |
669 | 45.9k | case tic6x_func_unit_m: |
670 | 45.9k | func_unit_char = 'M'; |
671 | 45.9k | break; |
672 | | |
673 | 62.9k | case tic6x_func_unit_s: |
674 | 62.9k | func_unit_char = 'S'; |
675 | 62.9k | break; |
676 | | |
677 | 0 | default: |
678 | 0 | printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit); |
679 | 0 | abort (); |
680 | 228k | } |
681 | | |
682 | 228k | switch (func_unit_data_side) |
683 | 228k | { |
684 | 131k | case 0: |
685 | 131k | data_str = ""; |
686 | 131k | break; |
687 | | |
688 | 47.8k | case 1: |
689 | 47.8k | data_str = "T1"; |
690 | 47.8k | break; |
691 | | |
692 | 49.0k | case 2: |
693 | 49.0k | data_str = "T2"; |
694 | 49.0k | 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 | 228k | } |
701 | | |
702 | 228k | if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1) |
703 | 38 | func_unit_cross = 1; |
704 | | |
705 | 228k | snprintf (func_unit_buf, sizeof func_unit_buf, " .%c%u%s%s", |
706 | 228k | func_unit_char, func_unit_side, |
707 | 228k | (func_unit_cross ? "X" : ""), data_str); |
708 | 228k | func_unit = func_unit_buf; |
709 | 228k | } |
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 | 252k | operands_ok = true; |
715 | 252k | num_operands = opc->num_operands; |
716 | 835k | for (op_num = 0; op_num < num_operands; op_num++) |
717 | 582k | { |
718 | 582k | unsigned int fld_num; |
719 | 582k | unsigned int mem_base_reg = 0; |
720 | 582k | bool mem_base_reg_known = false; |
721 | 582k | bool mem_base_reg_known_long = false; |
722 | 582k | unsigned int mem_offset = 0; |
723 | 582k | bool mem_offset_known = false; |
724 | 582k | bool mem_offset_known_long = false; |
725 | 582k | unsigned int mem_mode = 0; |
726 | 582k | bool mem_mode_known = false; |
727 | 582k | unsigned int mem_scaled = 0; |
728 | 582k | bool mem_scaled_known = false; |
729 | 582k | unsigned int crlo = 0; |
730 | 582k | bool crlo_known = false; |
731 | 582k | unsigned int crhi = 0; |
732 | 582k | bool crhi_known = false; |
733 | 582k | bool spmask_skip_operand = false; |
734 | 582k | unsigned int fcyc_bits = 0; |
735 | 582k | bool prev_sploop_found = false; |
736 | | |
737 | 582k | switch (opc->operand_info[op_num].form) |
738 | 582k | { |
739 | 99 | case tic6x_operand_b15reg: |
740 | | /* Fully determined by the functional unit. */ |
741 | 99 | operands_text[op_num] = true; |
742 | 99 | snprintf (operands[op_num], 24, "b15"); |
743 | 99 | continue; |
744 | | |
745 | 122 | case tic6x_operand_zreg: |
746 | | /* Fully determined by the functional unit. */ |
747 | 122 | operands_text[op_num] = true; |
748 | 122 | snprintf (operands[op_num], 24, "%c0", |
749 | 122 | (func_unit_side == 2 ? 'b' : 'a')); |
750 | 122 | continue; |
751 | | |
752 | 1.56k | case tic6x_operand_retreg: |
753 | | /* Fully determined by the functional unit. */ |
754 | 1.56k | operands_text[op_num] = true; |
755 | 1.56k | snprintf (operands[op_num], 24, "%c3", |
756 | 1.56k | (func_unit_side == 2 ? 'b' : 'a')); |
757 | 1.56k | continue; |
758 | | |
759 | 7 | case tic6x_operand_irp: |
760 | 7 | operands_text[op_num] = true; |
761 | 7 | snprintf (operands[op_num], 24, "irp"); |
762 | 7 | 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 | 3 | case tic6x_operand_ilc: |
770 | 3 | operands_text[op_num] = true; |
771 | 3 | snprintf (operands[op_num], 24, "ilc"); |
772 | 3 | continue; |
773 | | |
774 | 3 | case tic6x_operand_hw_const_minus_1: |
775 | 3 | operands_text[op_num] = true; |
776 | 3 | snprintf (operands[op_num], 24, "-1"); |
777 | 3 | continue; |
778 | | |
779 | 1 | case tic6x_operand_hw_const_0: |
780 | 1 | operands_text[op_num] = true; |
781 | 1 | snprintf (operands[op_num], 24, "0"); |
782 | 1 | continue; |
783 | | |
784 | 22 | case tic6x_operand_hw_const_1: |
785 | 22 | operands_text[op_num] = true; |
786 | 22 | snprintf (operands[op_num], 24, "1"); |
787 | 22 | continue; |
788 | | |
789 | 2.05k | case tic6x_operand_hw_const_5: |
790 | 2.05k | operands_text[op_num] = true; |
791 | 2.05k | snprintf (operands[op_num], 24, "5"); |
792 | 2.05k | continue; |
793 | | |
794 | 512 | case tic6x_operand_hw_const_16: |
795 | 512 | operands_text[op_num] = true; |
796 | 512 | snprintf (operands[op_num], 24, "16"); |
797 | 512 | continue; |
798 | | |
799 | 58 | case tic6x_operand_hw_const_24: |
800 | 58 | operands_text[op_num] = true; |
801 | 58 | snprintf (operands[op_num], 24, "24"); |
802 | 58 | continue; |
803 | | |
804 | 122 | case tic6x_operand_hw_const_31: |
805 | 122 | operands_text[op_num] = true; |
806 | 122 | snprintf (operands[op_num], 24, "31"); |
807 | 122 | continue; |
808 | | |
809 | 577k | default: |
810 | 577k | break; |
811 | 582k | } |
812 | | |
813 | 2.19M | for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++) |
814 | 2.19M | { |
815 | 2.19M | const tic6x_coding_field *const enc |
816 | 2.19M | = &opc->variable_fields[fld_num]; |
817 | 2.19M | const tic6x_insn_field *field; |
818 | 2.19M | unsigned int fld_val; |
819 | 2.19M | unsigned int reg_base = 0; |
820 | 2.19M | signed int signed_fld_val; |
821 | 2.19M | char reg_side = '?'; |
822 | | |
823 | 2.19M | if (enc->operand_num != op_num) |
824 | 1.11M | continue; |
825 | 1.07M | field = tic6x_field_from_fmt (fmt, enc->field_id); |
826 | 1.07M | 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 | 1.07M | fld_val = tic6x_field_bits (opcode, field); |
832 | 1.07M | switch (enc->coding_method) |
833 | 1.07M | { |
834 | 209 | case tic6x_coding_cst_s3i: |
835 | 209 | (fld_val == 0x00) && (fld_val = 0x10); |
836 | 209 | (fld_val == 0x07) && (fld_val = 0x08); |
837 | | /* Fall through. */ |
838 | 36.1k | case tic6x_coding_ucst: |
839 | 50.9k | case tic6x_coding_ulcst_dpr_byte: |
840 | 69.4k | case tic6x_coding_ulcst_dpr_half: |
841 | 87.4k | case tic6x_coding_ulcst_dpr_word: |
842 | 87.4k | case tic6x_coding_lcst_low16: |
843 | 87.4k | switch (opc->operand_info[op_num].form) |
844 | 87.4k | { |
845 | 35.6k | case tic6x_operand_asm_const: |
846 | 37.3k | case tic6x_operand_link_const: |
847 | 37.3k | operands_text[op_num] = true; |
848 | 37.3k | snprintf (operands[op_num], 24, "%u", fld_val); |
849 | 37.3k | break; |
850 | | |
851 | 50.0k | case tic6x_operand_mem_long: |
852 | 50.0k | mem_offset = fld_val; |
853 | 50.0k | mem_offset_known_long = true; |
854 | 50.0k | break; |
855 | | |
856 | 0 | default: |
857 | 0 | printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num); |
858 | 0 | abort (); |
859 | 87.4k | } |
860 | 87.4k | break; |
861 | | |
862 | 87.4k | case tic6x_coding_lcst_high16: |
863 | 6.24k | operands_text[op_num] = true; |
864 | 6.24k | snprintf (operands[op_num], 24, "%u", fld_val << 16); |
865 | 6.24k | break; |
866 | | |
867 | 604 | case tic6x_coding_scst_l3i: |
868 | 604 | operands_text[op_num] = true; |
869 | 604 | if (fld_val == 0) |
870 | 80 | { |
871 | 80 | signed_fld_val = 8; |
872 | 80 | } |
873 | 524 | else |
874 | 524 | { |
875 | 524 | signed_fld_val = (signed int) fld_val; |
876 | 524 | signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); |
877 | 524 | signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); |
878 | 524 | } |
879 | 604 | snprintf (operands[op_num], 24, "%d", signed_fld_val); |
880 | 604 | break; |
881 | | |
882 | 25.4k | case tic6x_coding_scst: |
883 | 25.4k | operands_text[op_num] = true; |
884 | 25.4k | signed_fld_val = (signed int) fld_val; |
885 | 25.4k | signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); |
886 | 25.4k | signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); |
887 | 25.4k | snprintf (operands[op_num], 24, "%d", signed_fld_val); |
888 | 25.4k | break; |
889 | | |
890 | 21.8k | case tic6x_coding_ucst_minus_one: |
891 | 21.8k | operands_text[op_num] = true; |
892 | 21.8k | snprintf (operands[op_num], 24, "%u", fld_val + 1); |
893 | 21.8k | break; |
894 | | |
895 | 11.2k | case tic6x_coding_pcrel: |
896 | 11.7k | case tic6x_coding_pcrel_half: |
897 | 11.7k | signed_fld_val = (signed int) fld_val; |
898 | 11.7k | signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); |
899 | 11.7k | signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); |
900 | 11.7k | if (fetch_packet_header_based |
901 | 11.7k | && enc->coding_method == tic6x_coding_pcrel_half) |
902 | 397 | signed_fld_val *= 2; |
903 | 11.3k | else |
904 | 11.3k | signed_fld_val *= 4; |
905 | 11.7k | operands_pcrel[op_num] = true; |
906 | 11.7k | operands_addresses[op_num] = fp_addr + signed_fld_val; |
907 | 11.7k | break; |
908 | | |
909 | 548 | case tic6x_coding_regpair_msb: |
910 | 548 | if (opc->operand_info[op_num].form != tic6x_operand_regpair) |
911 | 0 | abort (); |
912 | 548 | operands_text[op_num] = true; |
913 | 548 | snprintf (operands[op_num], 24, "%c%u:%c%u", |
914 | 548 | (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1), |
915 | 548 | (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1); |
916 | 548 | break; |
917 | | |
918 | 2.05k | case tic6x_coding_pcrel_half_unsigned: |
919 | 2.05k | operands_pcrel[op_num] = true; |
920 | 2.05k | operands_addresses[op_num] = fp_addr + 2 * fld_val; |
921 | 2.05k | break; |
922 | | |
923 | 7.21k | case tic6x_coding_reg_shift: |
924 | 7.21k | fld_val <<= 1; |
925 | | /* Fall through. */ |
926 | 415k | case tic6x_coding_reg: |
927 | 415k | if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS)) |
928 | 11.4k | { |
929 | 11.4k | reg_base = 16; |
930 | 11.4k | } |
931 | 415k | switch (opc->operand_info[op_num].form) |
932 | 415k | { |
933 | 1.68k | case tic6x_operand_treg: |
934 | 1.68k | if (!have_t) |
935 | 0 | { |
936 | 0 | printf ("opcode %x: operand treg but missing t field\n", opcode); |
937 | 0 | abort (); |
938 | 0 | } |
939 | 1.68k | operands_text[op_num] = true; |
940 | 1.68k | reg_side = t_val ? 'b' : 'a'; |
941 | 1.68k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
942 | 1.68k | break; |
943 | | |
944 | 175k | case tic6x_operand_reg: |
945 | 175k | operands_text[op_num] = true; |
946 | 175k | reg_side = (func_unit_side == 2) ? 'b' : 'a'; |
947 | 175k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
948 | 175k | break; |
949 | | |
950 | 742 | case tic6x_operand_reg_nors: |
951 | 742 | operands_text[op_num] = true; |
952 | 742 | reg_side = (func_unit_side == 2) ? 'b' : 'a'; |
953 | 742 | snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val); |
954 | 742 | break; |
955 | | |
956 | 3 | case tic6x_operand_reg_bside: |
957 | 3 | operands_text[op_num] = true; |
958 | 3 | snprintf (operands[op_num], 24, "b%u", reg_base + fld_val); |
959 | 3 | break; |
960 | | |
961 | 25 | case tic6x_operand_reg_bside_nors: |
962 | 25 | operands_text[op_num] = true; |
963 | 25 | snprintf (operands[op_num], 24, "b%u", fld_val); |
964 | 25 | break; |
965 | | |
966 | 72.8k | case tic6x_operand_xreg: |
967 | 72.8k | operands_text[op_num] = true; |
968 | 72.8k | reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a'; |
969 | 72.8k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
970 | 72.8k | break; |
971 | | |
972 | 83.8k | case tic6x_operand_dreg: |
973 | 83.8k | operands_text[op_num] = true; |
974 | 83.8k | reg_side = (func_unit_data_side == 2) ? 'b' : 'a'; |
975 | 83.8k | snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); |
976 | 83.8k | break; |
977 | | |
978 | 22.9k | case tic6x_operand_regpair: |
979 | 22.9k | operands_text[op_num] = true; |
980 | 22.9k | if (fld_val & 1) |
981 | 5.86k | operands_ok = false; |
982 | 22.9k | reg_side = (func_unit_side == 2) ? 'b' : 'a'; |
983 | 22.9k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
984 | 22.9k | reg_side, reg_base + fld_val + 1, |
985 | 22.9k | reg_side, reg_base + fld_val); |
986 | 22.9k | break; |
987 | | |
988 | 2.32k | case tic6x_operand_xregpair: |
989 | 2.32k | operands_text[op_num] = true; |
990 | 2.32k | if (fld_val & 1) |
991 | 637 | operands_ok = false; |
992 | 2.32k | reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a'; |
993 | 2.32k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
994 | 2.32k | reg_side, reg_base + fld_val + 1, |
995 | 2.32k | reg_side, reg_base + fld_val); |
996 | 2.32k | break; |
997 | | |
998 | 1.07k | case tic6x_operand_tregpair: |
999 | 1.07k | if (!have_t) |
1000 | 0 | { |
1001 | 0 | printf ("opcode %x: operand tregpair but missing t field\n", opcode); |
1002 | 0 | abort (); |
1003 | 0 | } |
1004 | 1.07k | operands_text[op_num] = true; |
1005 | 1.07k | if (fld_val & 1) |
1006 | 1 | operands_ok = false; |
1007 | 1.07k | reg_side = t_val ? 'b' : 'a'; |
1008 | 1.07k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
1009 | 1.07k | reg_side, reg_base + fld_val + 1, |
1010 | 1.07k | reg_side, reg_base + fld_val); |
1011 | 1.07k | break; |
1012 | | |
1013 | 10.3k | case tic6x_operand_dregpair: |
1014 | 10.3k | operands_text[op_num] = true; |
1015 | 10.3k | if (fld_val & 1) |
1016 | 1.54k | operands_ok = false; |
1017 | 10.3k | reg_side = (func_unit_data_side) == 2 ? 'b' : 'a'; |
1018 | 10.3k | snprintf (operands[op_num], 24, "%c%u:%c%u", |
1019 | 10.3k | reg_side, reg_base + fld_val + 1, |
1020 | 10.3k | reg_side, reg_base + fld_val); |
1021 | 10.3k | break; |
1022 | | |
1023 | 1 | case tic6x_operand_mem_deref: |
1024 | 1 | operands_text[op_num] = true; |
1025 | 1 | reg_side = func_unit_side == 2 ? 'b' : 'a'; |
1026 | 1 | snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val); |
1027 | 1 | break; |
1028 | | |
1029 | 38.8k | case tic6x_operand_mem_short: |
1030 | 44.1k | case tic6x_operand_mem_ndw: |
1031 | 44.1k | mem_base_reg = fld_val; |
1032 | 44.1k | mem_base_reg_known = true; |
1033 | 44.1k | 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 | 415k | } |
1040 | 415k | break; |
1041 | | |
1042 | 415k | case tic6x_coding_reg_ptr: |
1043 | 2.60k | switch (opc->operand_info[op_num].form) |
1044 | 2.60k | { |
1045 | 2.32k | case tic6x_operand_mem_short: |
1046 | 2.60k | case tic6x_operand_mem_ndw: |
1047 | 2.60k | 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 | 2.60k | mem_base_reg = 0x4 | fld_val; |
1054 | 2.60k | mem_base_reg_known = true; |
1055 | 2.60k | 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 | 2.60k | } |
1062 | 2.60k | break; |
1063 | | |
1064 | 51.3k | case tic6x_coding_areg: |
1065 | 51.3k | switch (opc->operand_info[op_num].form) |
1066 | 51.3k | { |
1067 | 1.25k | case tic6x_operand_areg: |
1068 | 1.25k | operands_text[op_num] = true; |
1069 | 1.25k | snprintf (operands[op_num], 24, "b%u", |
1070 | 1.25k | fld_val ? 15u : 14u); |
1071 | 1.25k | break; |
1072 | | |
1073 | 50.0k | case tic6x_operand_mem_long: |
1074 | 50.0k | mem_base_reg = fld_val ? 15u : 14u; |
1075 | 50.0k | mem_base_reg_known_long = true; |
1076 | 50.0k | break; |
1077 | | |
1078 | 0 | default: |
1079 | 0 | printf ("opcode %x: bad operand form\n", opcode); |
1080 | 0 | abort (); |
1081 | 51.3k | } |
1082 | 51.3k | break; |
1083 | | |
1084 | 51.3k | case tic6x_coding_mem_offset_minus_one_noscale: |
1085 | 455 | case tic6x_coding_mem_offset_minus_one: |
1086 | 455 | fld_val += 1; |
1087 | | /* Fall through. */ |
1088 | 5.89k | case tic6x_coding_mem_offset_noscale: |
1089 | 46.8k | case tic6x_coding_mem_offset: |
1090 | 46.8k | mem_offset = fld_val; |
1091 | 46.8k | mem_offset_known = true; |
1092 | 46.8k | if (num_bits == 16) |
1093 | 2.76k | { |
1094 | 2.76k | mem_mode_known = true; |
1095 | 2.76k | mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags); |
1096 | 2.76k | mem_scaled_known = true; |
1097 | 2.76k | mem_scaled = true; |
1098 | 2.76k | if (opc->flags & TIC6X_FLAG_INSN16_B15PTR) |
1099 | 156 | { |
1100 | 156 | mem_base_reg_known = true; |
1101 | 156 | mem_base_reg = 15; |
1102 | 156 | } |
1103 | 2.76k | if ( enc->coding_method == tic6x_coding_mem_offset_noscale |
1104 | 2.76k | || enc->coding_method == tic6x_coding_mem_offset_noscale ) |
1105 | 214 | mem_scaled = false; |
1106 | 2.76k | } |
1107 | 46.8k | break; |
1108 | | |
1109 | 44.1k | case tic6x_coding_mem_mode: |
1110 | 44.1k | mem_mode = fld_val; |
1111 | 44.1k | mem_mode_known = true; |
1112 | 44.1k | break; |
1113 | | |
1114 | 5.22k | case tic6x_coding_scaled: |
1115 | 5.22k | mem_scaled = fld_val; |
1116 | 5.22k | mem_scaled_known = true; |
1117 | 5.22k | break; |
1118 | | |
1119 | 263 | case tic6x_coding_crlo: |
1120 | 263 | crlo = fld_val; |
1121 | 263 | crlo_known = true; |
1122 | 263 | break; |
1123 | | |
1124 | 263 | case tic6x_coding_crhi: |
1125 | 263 | crhi = fld_val; |
1126 | 263 | crhi_known = true; |
1127 | 263 | break; |
1128 | | |
1129 | 23 | case tic6x_coding_fstg: |
1130 | 46 | case tic6x_coding_fcyc: |
1131 | 46 | if (!prev_sploop_found) |
1132 | 46 | { |
1133 | 46 | bfd_vma search_fp_addr = fp_addr; |
1134 | 46 | bfd_vma search_fp_offset = fp_offset; |
1135 | 46 | bool search_fp_header_based |
1136 | 46 | = fetch_packet_header_based; |
1137 | 46 | tic6x_fetch_packet_header search_fp_header = header; |
1138 | 46 | unsigned char search_fp[32]; |
1139 | 46 | unsigned int search_num_bits; |
1140 | 46 | unsigned int search_opcode; |
1141 | 46 | unsigned int sploop_ii = 0; |
1142 | 46 | int i; |
1143 | | |
1144 | 46 | 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 | 17.7k | for (i = 0; i < 48 * 8; i++) |
1151 | 17.6k | { |
1152 | | /* Find the previous instruction. */ |
1153 | 17.6k | if (search_fp_offset & 2) |
1154 | 264 | search_fp_offset -= 2; |
1155 | 17.4k | else if (search_fp_offset >= 4) |
1156 | 15.2k | { |
1157 | 15.2k | if (search_fp_header_based |
1158 | 15.2k | && (search_fp_header.word_compact |
1159 | 474 | [(search_fp_offset >> 2) - 1])) |
1160 | 184 | search_fp_offset -= 2; |
1161 | 15.0k | else |
1162 | 15.0k | search_fp_offset -= 4; |
1163 | 15.2k | } |
1164 | 2.19k | else |
1165 | 2.19k | { |
1166 | 2.19k | search_fp_addr -= 32; |
1167 | 2.19k | status = info->read_memory_func (search_fp_addr, |
1168 | 2.19k | search_fp, |
1169 | 2.19k | 32, info); |
1170 | 2.19k | if (status) |
1171 | | /* No previous SPLOOP instruction. */ |
1172 | 0 | break; |
1173 | 2.19k | search_fp_header_based |
1174 | 2.19k | = (tic6x_check_fetch_packet_header |
1175 | 2.19k | (search_fp, &search_fp_header, info)); |
1176 | 2.19k | if (search_fp_header_based) |
1177 | 78 | search_fp_offset |
1178 | 78 | = search_fp_header.word_compact[6] ? 26 : 24; |
1179 | 2.12k | else |
1180 | 2.12k | search_fp_offset = 28; |
1181 | 2.19k | } |
1182 | | |
1183 | | /* Extract the previous instruction. */ |
1184 | 17.6k | if (search_fp_header_based) |
1185 | 816 | search_num_bits |
1186 | 816 | = (search_fp_header.word_compact[search_fp_offset |
1187 | 816 | >> 2] |
1188 | 816 | ? 16 |
1189 | 816 | : 32); |
1190 | 16.8k | else |
1191 | 16.8k | search_num_bits = 32; |
1192 | 17.6k | if (search_num_bits == 16) |
1193 | 506 | { |
1194 | 506 | 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 | 506 | else |
1199 | 506 | search_opcode |
1200 | 506 | = (tic6x_extract_16 |
1201 | 506 | (search_fp + (search_fp_offset ^ 2), &header, |
1202 | 506 | info)); |
1203 | 506 | } |
1204 | 17.1k | else |
1205 | 17.1k | search_opcode |
1206 | 17.1k | = tic6x_extract_32 (search_fp + search_fp_offset, |
1207 | 17.1k | info); |
1208 | | |
1209 | | /* Check whether it is an SPLOOP-family |
1210 | | instruction. */ |
1211 | 17.6k | if (search_num_bits == 32 |
1212 | 17.6k | && ((search_opcode & 0x003ffffe) == 0x00038000 |
1213 | 17.1k | || (search_opcode & 0x003ffffe) == 0x0003a000 |
1214 | 17.1k | || ((search_opcode & 0x003ffffe) |
1215 | 17.1k | == 0x0003e000))) |
1216 | 0 | { |
1217 | 0 | prev_sploop_found = true; |
1218 | 0 | sploop_ii = ((search_opcode >> 23) & 0x1f) + 1; |
1219 | 0 | } |
1220 | 17.6k | else if (search_num_bits == 16 |
1221 | 17.6k | && (search_opcode & 0x3c7e) == 0x0c66) |
1222 | 0 | { |
1223 | 0 | prev_sploop_found = true; |
1224 | 0 | sploop_ii |
1225 | 0 | = (((search_opcode >> 7) & 0x7) |
1226 | 0 | | ((search_opcode >> 11) & 0x8)) + 1; |
1227 | 0 | } |
1228 | 17.6k | if (prev_sploop_found) |
1229 | 0 | { |
1230 | 0 | 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 | 0 | else if (sploop_ii <= 1) |
1236 | 0 | fcyc_bits = 0; |
1237 | 0 | else if (sploop_ii <= 2) |
1238 | 0 | fcyc_bits = 1; |
1239 | 0 | else if (sploop_ii <= 4) |
1240 | 0 | fcyc_bits = 2; |
1241 | 0 | else if (sploop_ii <= 8) |
1242 | 0 | fcyc_bits = 3; |
1243 | 0 | else if (sploop_ii <= 14) |
1244 | 0 | fcyc_bits = 4; |
1245 | 0 | else |
1246 | 0 | prev_sploop_found = false; |
1247 | 0 | } |
1248 | 17.6k | if (prev_sploop_found) |
1249 | 0 | break; |
1250 | 17.6k | } |
1251 | 46 | } |
1252 | 46 | if (!prev_sploop_found) |
1253 | 46 | { |
1254 | 46 | operands_ok = false; |
1255 | 46 | operands_text[op_num] = true; |
1256 | 46 | break; |
1257 | 46 | } |
1258 | 0 | 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 | 0 | if (enc->coding_method == tic6x_coding_fstg) |
1264 | 0 | { |
1265 | 0 | int i, t; |
1266 | 0 | for (t = 0, i = fcyc_bits; i < 6; i++) |
1267 | 0 | t = (t << 1) | ((fld_val >> i) & 1); |
1268 | 0 | operands_text[op_num] = true; |
1269 | 0 | snprintf (operands[op_num], 24, "%u", t); |
1270 | 0 | } |
1271 | 0 | else |
1272 | 0 | { |
1273 | 0 | operands_text[op_num] = true; |
1274 | 0 | snprintf (operands[op_num], 24, "%u", |
1275 | 0 | fld_val & ((1 << fcyc_bits) - 1)); |
1276 | 0 | } |
1277 | 0 | break; |
1278 | | |
1279 | 1.81k | case tic6x_coding_spmask: |
1280 | 1.81k | if (fld_val == 0) |
1281 | 317 | spmask_skip_operand = true; |
1282 | 1.50k | else |
1283 | 1.50k | { |
1284 | 1.50k | char *p; |
1285 | 1.50k | unsigned int i; |
1286 | | |
1287 | 1.50k | operands_text[op_num] = true; |
1288 | 1.50k | p = operands[op_num]; |
1289 | 13.5k | for (i = 0; i < 8; i++) |
1290 | 12.0k | if (fld_val & (1 << i)) |
1291 | 3.96k | { |
1292 | 3.96k | *p++ = "LSDM"[i/2]; |
1293 | 3.96k | *p++ = '1' + (i & 1); |
1294 | 3.96k | *p++ = ','; |
1295 | 3.96k | } |
1296 | 1.50k | p[-1] = 0; |
1297 | 1.50k | } |
1298 | 1.81k | break; |
1299 | | |
1300 | 177k | case tic6x_coding_fu: |
1301 | 271k | case tic6x_coding_data_fu: |
1302 | 346k | case tic6x_coding_xpath: |
1303 | 349k | case tic6x_coding_rside: |
1304 | | /* Don't relate to operands, so operand number is |
1305 | | meaningless. */ |
1306 | 349k | break; |
1307 | | |
1308 | 0 | default: |
1309 | 0 | printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method); |
1310 | 0 | abort (); |
1311 | 1.07M | } |
1312 | | |
1313 | 1.07M | if (mem_base_reg_known_long && mem_offset_known_long) |
1314 | 50.0k | { |
1315 | 50.0k | 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 | 50.0k | operands_text[op_num] = true; |
1321 | 50.0k | snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg, |
1322 | 50.0k | mem_offset * opc->operand_info[op_num].size); |
1323 | 50.0k | } |
1324 | | |
1325 | 1.07M | if (mem_base_reg_known && mem_offset_known && mem_mode_known |
1326 | 1.07M | && (mem_scaled_known |
1327 | 52.0k | || (opc->operand_info[op_num].form |
1328 | 44.1k | != tic6x_operand_mem_ndw))) |
1329 | 46.8k | { |
1330 | 46.8k | char side; |
1331 | 46.8k | char base[4]; |
1332 | 46.8k | bool offset_is_reg; |
1333 | 46.8k | bool offset_scaled; |
1334 | 46.8k | char offset[4]; |
1335 | 46.8k | char offsetp[6]; |
1336 | | |
1337 | 46.8k | 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 | 46.8k | side = func_unit_side == 2 ? 'b' : 'a'; |
1344 | 46.8k | snprintf (base, 4, "%c%u", side, mem_base_reg); |
1345 | | |
1346 | 46.8k | offset_is_reg = (mem_mode & 4) != 0; |
1347 | 46.8k | if (offset_is_reg) |
1348 | 17.4k | { |
1349 | | |
1350 | 17.4k | if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS)) |
1351 | 254 | { |
1352 | 254 | reg_base = 16; |
1353 | 254 | } |
1354 | 17.4k | snprintf (offset, 4, "%c%u", side, reg_base + mem_offset); |
1355 | 17.4k | if (opc->operand_info[op_num].form |
1356 | 17.4k | == tic6x_operand_mem_ndw) |
1357 | 2.74k | offset_scaled = mem_scaled != 0; |
1358 | 14.6k | else |
1359 | 14.6k | offset_scaled = true; |
1360 | 17.4k | } |
1361 | 29.4k | else |
1362 | 29.4k | { |
1363 | 29.4k | if (opc->operand_info[op_num].form |
1364 | 29.4k | == tic6x_operand_mem_ndw) |
1365 | 2.76k | { |
1366 | 2.76k | offset_scaled = mem_scaled != 0; |
1367 | 2.76k | snprintf (offset, 4, "%u", mem_offset); |
1368 | 2.76k | } |
1369 | 26.6k | else |
1370 | 26.6k | { |
1371 | 26.6k | offset_scaled = false; |
1372 | 26.6k | snprintf (offset, 4, "%u", |
1373 | 26.6k | (mem_offset |
1374 | 26.6k | * opc->operand_info[op_num].size)); |
1375 | 26.6k | } |
1376 | 29.4k | } |
1377 | | |
1378 | 46.8k | if (offset_scaled) |
1379 | 16.8k | snprintf (offsetp, 6, "[%s]", offset); |
1380 | 29.9k | else |
1381 | 29.9k | snprintf (offsetp, 6, "(%s)", offset); |
1382 | | |
1383 | 46.8k | operands_text[op_num] = true; |
1384 | 46.8k | switch (mem_mode & ~4u) |
1385 | 46.8k | { |
1386 | 12.0k | case 0: |
1387 | 12.0k | snprintf (operands[op_num], 24, "*-%s%s", base, offsetp); |
1388 | 12.0k | break; |
1389 | | |
1390 | 5.83k | case 1: |
1391 | 5.83k | snprintf (operands[op_num], 24, "*+%s%s", base, offsetp); |
1392 | 5.83k | break; |
1393 | | |
1394 | 5.20k | case 2: |
1395 | 9.13k | case 3: |
1396 | 9.13k | operands_ok = false; |
1397 | 9.13k | break; |
1398 | | |
1399 | 3.94k | case 8: |
1400 | 3.94k | snprintf (operands[op_num], 24, "*--%s%s", base, |
1401 | 3.94k | offsetp); |
1402 | 3.94k | break; |
1403 | | |
1404 | 4.21k | case 9: |
1405 | 4.21k | snprintf (operands[op_num], 24, "*++%s%s", base, |
1406 | 4.21k | offsetp); |
1407 | 4.21k | break; |
1408 | | |
1409 | 3.87k | case 10: |
1410 | 3.87k | snprintf (operands[op_num], 24, "*%s--%s", base, |
1411 | 3.87k | offsetp); |
1412 | 3.87k | break; |
1413 | | |
1414 | 7.84k | case 11: |
1415 | 7.84k | snprintf (operands[op_num], 24, "*%s++%s", base, |
1416 | 7.84k | offsetp); |
1417 | 7.84k | break; |
1418 | | |
1419 | 0 | default: |
1420 | 0 | printf ("*** unknown mem_mode : %d \n", mem_mode); |
1421 | 0 | abort (); |
1422 | 46.8k | } |
1423 | 46.8k | } |
1424 | | |
1425 | 1.07M | if (crlo_known && crhi_known) |
1426 | 263 | { |
1427 | 263 | tic6x_rw rw; |
1428 | 263 | tic6x_ctrl_id crid; |
1429 | | |
1430 | 263 | 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 | 263 | rw = opc->operand_info[op_num].rw; |
1437 | 263 | if (rw != tic6x_rw_read |
1438 | 263 | && rw != tic6x_rw_write) |
1439 | 0 | { |
1440 | 0 | printf ("*** abort rw : %d\n", rw); |
1441 | 0 | abort (); |
1442 | 0 | } |
1443 | | |
1444 | 7.71k | for (crid = 0; crid < tic6x_ctrl_max; crid++) |
1445 | 7.46k | { |
1446 | 7.46k | if (crlo == tic6x_ctrl_table[crid].crlo |
1447 | 7.46k | && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0 |
1448 | 7.46k | && (rw == tic6x_rw_read |
1449 | 14 | ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read |
1450 | 4 | || (tic6x_ctrl_table[crid].rw |
1451 | 4 | == tic6x_rw_read_write)) |
1452 | 14 | : (tic6x_ctrl_table[crid].rw == tic6x_rw_write |
1453 | 10 | || (tic6x_ctrl_table[crid].rw |
1454 | 10 | == tic6x_rw_read_write)))) |
1455 | 13 | break; |
1456 | 7.46k | } |
1457 | 263 | if (crid == tic6x_ctrl_max) |
1458 | 250 | { |
1459 | 250 | operands_text[op_num] = true; |
1460 | 250 | operands_ok = false; |
1461 | 250 | } |
1462 | 13 | else |
1463 | 13 | { |
1464 | 13 | operands_text[op_num] = true; |
1465 | 13 | snprintf (operands[op_num], 24, "%s", |
1466 | 13 | tic6x_ctrl_table[crid].name); |
1467 | 13 | } |
1468 | 263 | } |
1469 | | |
1470 | 1.07M | if (operands_text[op_num] || operands_pcrel[op_num] |
1471 | 1.07M | || spmask_skip_operand) |
1472 | 577k | break; |
1473 | 1.07M | } |
1474 | | /* end for fld_num */ |
1475 | | |
1476 | 577k | if (spmask_skip_operand) |
1477 | 317 | { |
1478 | | /* SPMASK operands are only valid as the single operand |
1479 | | in the opcode table. */ |
1480 | 317 | 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 | 317 | num_operands = 0; |
1486 | 317 | break; |
1487 | 317 | } |
1488 | | |
1489 | | /* The operand must by now have been decoded. */ |
1490 | 577k | 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 | 577k | } |
1496 | | /* end for op_num */ |
1497 | | |
1498 | 252k | if (!operands_ok) |
1499 | 16.0k | continue; |
1500 | | |
1501 | 236k | info->bytes_per_chunk = num_bits / 8; |
1502 | 236k | info->fprintf_func (info->stream, "%s", parallel); |
1503 | 236k | info->fprintf_func (info->stream, "%s%s%s", cond, opc->name, |
1504 | 236k | func_unit); |
1505 | 781k | for (op_num = 0; op_num < num_operands; op_num++) |
1506 | 544k | { |
1507 | 544k | info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ',')); |
1508 | 544k | if (operands_pcrel[op_num]) |
1509 | 13.8k | info->print_address_func (operands_addresses[op_num], info); |
1510 | 530k | else |
1511 | 530k | info->fprintf_func (info->stream, "%s", operands[op_num]); |
1512 | 544k | } |
1513 | 236k | if (fetch_packet_header_based && header.prot) |
1514 | 4.62k | info->fprintf_func (info->stream, " || nop 5"); |
1515 | | |
1516 | 236k | return num_bits / 8; |
1517 | 252k | } |
1518 | | |
1519 | 118k | info->bytes_per_chunk = num_bits / 8; |
1520 | 118k | info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>", |
1521 | 118k | (int) num_bits / 4, opcode); |
1522 | 118k | return num_bits / 8; |
1523 | 355k | } |