gas/
[deliverable/binutils-gdb.git] / opcodes / tic6x-dis.c
1 /* TI C6X disassembler.
2 Copyright 2010
3 Free Software Foundation, Inc.
4
5 This file is part of libopcodes.
6
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
22 #include "sysdep.h"
23 #include "dis-asm.h"
24 #include "opcode/tic6x.h"
25 #include "libiberty.h"
26
27 /* Define the instruction format table. */
28 const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
29 {
30 #define FMT(name, num_bits, cst_bits, mask, fields) \
31 { num_bits, cst_bits, mask, fields },
32 #include "opcode/tic6x-insn-formats.h"
33 #undef FMT
34 };
35
36 /* Define the control register table. */
37 const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
38 {
39 #define CTRL(name, isa, rw, crlo, crhi_mask) \
40 { \
41 STRINGX(name), \
42 CONCAT2(TIC6X_INSN_,isa), \
43 CONCAT2(tic6x_rw_,rw), \
44 crlo, \
45 crhi_mask \
46 },
47 #include "opcode/tic6x-control-registers.h"
48 #undef CTRL
49 };
50
51 /* Define the opcode table. */
52 const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
53 {
54 #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
55 { \
56 STRINGX(name), \
57 CONCAT2(tic6x_func_unit_,func_unit), \
58 CONCAT4(tic6x_insn_format_,func_unit,_,format), \
59 CONCAT2(tic6x_pipeline_,type), \
60 CONCAT2(TIC6X_INSN_,isa), \
61 flags, \
62 fixed, \
63 ops, \
64 var \
65 },
66 #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
67 { \
68 STRINGX(name), \
69 CONCAT2(tic6x_func_unit_,func_unit), \
70 CONCAT4(tic6x_insn_format_,func_unit,_,format), \
71 CONCAT2(tic6x_pipeline_,type), \
72 CONCAT2(TIC6X_INSN_,isa), \
73 flags, \
74 fixed, \
75 ops, \
76 var \
77 },
78 #include "opcode/tic6x-opcode-table.h"
79 #undef INSN
80 #undef INSNE
81 };
82
83 /* If instruction format FMT has a field FIELD, return a pointer to
84 the description of that field; otherwise return NULL. */
85
86 const tic6x_insn_field *
87 tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
88 {
89 unsigned int f;
90
91 for (f = 0; f < fmt->num_fields; f++)
92 if (fmt->fields[f].field_id == field)
93 return &fmt->fields[f];
94
95 return NULL;
96 }
97
98 /* Extract the bits corresponding to FIELD from OPCODE. */
99
100 static unsigned int
101 tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
102 {
103 return (opcode >> field->low_pos) & ((1u << field->width) - 1);
104 }
105
106 /* Extract a 32-bit value read from the instruction stream. */
107
108 static unsigned int
109 tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
110 {
111 if (info->endian == BFD_ENDIAN_LITTLE)
112 return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
113 else
114 return (p[3]) | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
115 }
116
117 /* Extract a 16-bit value read from the instruction stream. */
118
119 static unsigned int
120 tic6x_extract_16 (unsigned char *p, struct disassemble_info *info)
121 {
122 if (info->endian == BFD_ENDIAN_LITTLE)
123 return (p[0]) | (p[1] << 8);
124 else
125 return (p[1]) | (p[0] << 8);
126 }
127
128 /* FP points to a fetch packet. Return whether it is header-based; if
129 it is, fill in HEADER. */
130
131 static bfd_boolean
132 tic6x_check_fetch_packet_header (unsigned char *fp,
133 tic6x_fetch_packet_header *header,
134 struct disassemble_info *info)
135 {
136 int i;
137
138 header->header = tic6x_extract_32 (fp + 28, info);
139 if ((header->header & 0xf0000000) != 0xe0000000)
140 return FALSE;
141
142 for (i = 0; i < 7; i++)
143 header->word_compact[i]
144 = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
145
146 header->prot = (header->header & (1u << 20)) ? TRUE : FALSE;
147 header->rs = (header->header & (1u << 19)) ? TRUE : FALSE;
148 header->dsz = (header->header >> 16) & 0x7;
149 header->br = (header->header & (1u << 15)) ? TRUE : FALSE;
150 header->sat = (header->header & (1u << 14)) ? TRUE : FALSE;
151
152 for (i = 0; i < 14; i++)
153 header->p_bits[i]
154 = (header->header & (1u << i)) ? TRUE : FALSE;
155
156 return TRUE;
157 }
158
159 /* Disassemble the instruction at ADDR and print it using
160 INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
161 consumed. */
162
163 int
164 print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
165 {
166 int status;
167 bfd_vma fp_addr;
168 bfd_vma fp_offset;
169 unsigned char fp[32];
170 unsigned int opcode;
171 tic6x_opcode_id opcode_id;
172 bfd_boolean fetch_packet_header_based;
173 tic6x_fetch_packet_header header;
174 unsigned int num_bits;
175 bfd_boolean bad_offset = FALSE;
176
177 fp_offset = addr & 0x1f;
178 fp_addr = addr - fp_offset;
179 status = info->read_memory_func (fp_addr, fp, 32, info);
180 if (status)
181 {
182 info->memory_error_func (status, addr, info);
183 return -1;
184 }
185
186 fetch_packet_header_based
187 = tic6x_check_fetch_packet_header (fp, &header, info);
188 if (fetch_packet_header_based)
189 {
190 if (fp_offset & 0x1)
191 bad_offset = TRUE;
192 if ((fp_offset & 0x3) && (fp_offset >= 28
193 || !header.word_compact[fp_offset >> 2]))
194 bad_offset = TRUE;
195 if (fp_offset == 28)
196 {
197 info->bytes_per_chunk = 4;
198 info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
199 header.header);
200 return 4;
201 }
202 num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
203 }
204 else
205 {
206 num_bits = 32;
207 if (fp_offset & 0x3)
208 bad_offset = TRUE;
209 }
210
211 if (bad_offset)
212 {
213 info->bytes_per_chunk = 1;
214 info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
215 return 1;
216 }
217
218 if (num_bits == 16)
219 {
220 /* The least-significant part of a 32-bit word comes logically
221 before the most-significant part. For big-endian, follow the
222 TI assembler in showing instructions in logical order by
223 pretending that the two halves of the word are in opposite
224 locations to where they actually are. */
225 if (info->endian == BFD_ENDIAN_LITTLE)
226 opcode = tic6x_extract_16 (fp + fp_offset, info);
227 else
228 opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), info);
229 }
230 else
231 opcode = tic6x_extract_32 (fp + fp_offset, info);
232
233 for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
234 {
235 const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id];
236 const tic6x_insn_format *const fmt
237 = &tic6x_insn_format_table[opc->format];
238 const tic6x_insn_field *creg_field;
239 bfd_boolean p_bit;
240 const char *parallel;
241 const char *cond = "";
242 const char *func_unit;
243 char func_unit_buf[7];
244 unsigned int func_unit_side = 0;
245 unsigned int func_unit_data_side = 0;
246 unsigned int func_unit_cross = 0;
247 /* The maximum length of the text of a non-PC-relative operand
248 is 24 bytes (SPMASK masking all eight functional units, with
249 separating commas and trailing NUL). */
250 char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } };
251 bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 };
252 bfd_boolean operands_text[TIC6X_MAX_OPERANDS] = { FALSE };
253 bfd_boolean operands_pcrel[TIC6X_MAX_OPERANDS] = { FALSE };
254 unsigned int fix;
255 unsigned int num_operands;
256 unsigned int op_num;
257 bfd_boolean fixed_ok;
258 bfd_boolean operands_ok;
259
260 if (opc->flags & TIC6X_FLAG_MACRO)
261 continue;
262 if (fmt->num_bits != num_bits)
263 continue;
264 if ((opcode & fmt->mask) != fmt->cst_bits)
265 continue;
266
267 /* If the format has a creg field, it is only a candidate for a
268 match if the creg and z fields have values indicating a valid
269 condition; reserved values indicate either an instruction
270 format without a creg field, or an invalid instruction. */
271 creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg);
272 if (creg_field)
273 {
274 const tic6x_insn_field *z_field;
275 unsigned int creg_value, z_value;
276 static const char *const conds[8][2] =
277 {
278 { "", NULL },
279 { "[b0] ", "[!b0] " },
280 { "[b1] ", "[!b1] " },
281 { "[b2] ", "[!b2] " },
282 { "[a1] ", "[!a1] " },
283 { "[a2] ", "[!a2] " },
284 { "[a0] ", "[!a0] " },
285 { NULL, NULL }
286 };
287
288 /* A creg field is not meaningful without a z field, so if
289 the z field is not present this is an error in the format
290 table. */
291 z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
292 if (!z_field)
293 abort ();
294
295 creg_value = tic6x_field_bits (opcode, creg_field);
296 z_value = tic6x_field_bits (opcode, z_field);
297 cond = conds[creg_value][z_value];
298 if (cond == NULL)
299 continue;
300 }
301
302 /* All fixed fields must have matching values; all fields with
303 restricted ranges must have values within those ranges. */
304 fixed_ok = TRUE;
305 for (fix = 0; fix < opc->num_fixed_fields; fix++)
306 {
307 unsigned int field_bits;
308 const tic6x_insn_field *const field
309 = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
310
311 if (!field)
312 abort ();
313 field_bits = tic6x_field_bits (opcode, field);
314 if (field_bits < opc->fixed_fields[fix].min_val
315 || field_bits > opc->fixed_fields[fix].max_val)
316 {
317 fixed_ok = FALSE;
318 break;
319 }
320 }
321 if (!fixed_ok)
322 continue;
323
324 /* The instruction matches. */
325
326 /* The p-bit indicates whether this instruction is in parallel
327 with the *next* instruction, whereas the parallel bars
328 indicate the instruction is in parallel with the *previous*
329 instruction. Thus, we must find the p-bit for the previous
330 instruction. */
331 if (num_bits == 16 && (fp_offset & 0x2) == 2)
332 {
333 /* This is the logically second (most significant; second in
334 fp_offset terms because fp_offset relates to logical not
335 physical addresses) instruction of a compact pair; find
336 the p-bit for the first (least significant). */
337 p_bit = header.p_bits[(fp_offset >> 2) << 1];
338 }
339 else if (fp_offset >= 4)
340 {
341 /* Find the last instruction of the previous word in this
342 fetch packet. For compact instructions, this is the most
343 significant 16 bits. */
344 if (fetch_packet_header_based
345 && header.word_compact[(fp_offset >> 2) - 1])
346 p_bit = header.p_bits[(fp_offset >> 1) - 1];
347 else
348 {
349 unsigned int prev_opcode
350 = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
351 p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
352 }
353 }
354 else
355 {
356 /* Find the last instruction of the previous fetch
357 packet. */
358 unsigned char fp_prev[32];
359 status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info);
360 if (status)
361 /* No previous instruction to be parallel with. */
362 p_bit = FALSE;
363 else
364 {
365 bfd_boolean prev_header_based;
366 tic6x_fetch_packet_header prev_header;
367
368 prev_header_based
369 = tic6x_check_fetch_packet_header (fp_prev, &prev_header, info);
370 if (prev_header_based && prev_header.word_compact[6])
371 p_bit = prev_header.p_bits[13];
372 else
373 {
374 unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
375 info);
376 p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
377 }
378 }
379 }
380 parallel = p_bit ? "|| " : "";
381
382 if (opc->func_unit == tic6x_func_unit_nfu)
383 func_unit = "";
384 else
385 {
386 unsigned int fld_num;
387 char func_unit_char;
388 const char *data_str;
389 bfd_boolean have_areg = FALSE;
390 bfd_boolean have_cross = FALSE;
391
392 func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0;
393 func_unit_cross = 0;
394 func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0;
395
396 for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
397 {
398 const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
399 const tic6x_insn_field *field;
400 unsigned int fld_val;
401
402 field = tic6x_field_from_fmt (fmt, enc->field_id);
403 if (!field)
404 abort ();
405 fld_val = tic6x_field_bits (opcode, field);
406 switch (enc->coding_method)
407 {
408 case tic6x_coding_fu:
409 /* The side must be specified exactly once. */
410 if (func_unit_side)
411 abort ();
412 func_unit_side = (fld_val ? 2 : 1);
413 break;
414
415 case tic6x_coding_data_fu:
416 /* The data side must be specified exactly once. */
417 if (func_unit_data_side)
418 abort ();
419 func_unit_data_side = (fld_val ? 2 : 1);
420 break;
421
422 case tic6x_coding_xpath:
423 /* Cross path use must be specified exactly
424 once. */
425 if (have_cross)
426 abort ();
427 have_cross = TRUE;
428 func_unit_cross = fld_val;
429 break;
430
431 case tic6x_coding_areg:
432 have_areg = TRUE;
433 break;
434
435 default:
436 /* Don't relate to functional units. */
437 break;
438 }
439 }
440
441 /* The side of the functional unit used must now have been
442 determined either from the flags or from an instruction
443 field. */
444 if (func_unit_side != 1 && func_unit_side != 2)
445 abort ();
446
447 /* Cross paths are not applicable when sides are specified
448 for both address and data paths. */
449 if (func_unit_data_side && have_cross)
450 abort ();
451
452 /* Separate address and data paths are only applicable for
453 the D unit. */
454 if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d)
455 abort ();
456
457 /* If an address register is being used but in ADDA rather
458 than a load or store, it uses a cross path for side-A
459 instructions, and the cross path use is not specified by
460 an instruction field. */
461 if (have_areg && !func_unit_data_side)
462 {
463 if (have_cross)
464 abort ();
465 func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
466 }
467
468 switch (opc->func_unit)
469 {
470 case tic6x_func_unit_d:
471 func_unit_char = 'D';
472 break;
473
474 case tic6x_func_unit_l:
475 func_unit_char = 'L';
476 break;
477
478 case tic6x_func_unit_m:
479 func_unit_char = 'M';
480 break;
481
482 case tic6x_func_unit_s:
483 func_unit_char = 'S';
484 break;
485
486 default:
487 abort ();
488 }
489
490 switch (func_unit_data_side)
491 {
492 case 0:
493 data_str = "";
494 break;
495
496 case 1:
497 data_str = "T1";
498 break;
499
500 case 2:
501 data_str = "T2";
502 break;
503
504 default:
505 abort ();
506 }
507
508 snprintf (func_unit_buf, 7, " .%c%u%s%s", func_unit_char,
509 func_unit_side, (func_unit_cross ? "X" : ""), data_str);
510 func_unit = func_unit_buf;
511 }
512
513 /* For each operand there must be one or more fields set based
514 on that operand, that can together be used to derive the
515 operand value. */
516 operands_ok = TRUE;
517 num_operands = opc->num_operands;
518 for (op_num = 0; op_num < num_operands; op_num++)
519 {
520 unsigned int fld_num;
521 unsigned int mem_base_reg = 0;
522 bfd_boolean mem_base_reg_known = FALSE;
523 bfd_boolean mem_base_reg_known_long = FALSE;
524 unsigned int mem_offset = 0;
525 bfd_boolean mem_offset_known = FALSE;
526 bfd_boolean mem_offset_known_long = FALSE;
527 unsigned int mem_mode = 0;
528 bfd_boolean mem_mode_known = FALSE;
529 unsigned int mem_scaled = 0;
530 bfd_boolean mem_scaled_known = FALSE;
531 unsigned int crlo = 0;
532 bfd_boolean crlo_known = FALSE;
533 unsigned int crhi = 0;
534 bfd_boolean crhi_known = FALSE;
535 bfd_boolean spmask_skip_operand = FALSE;
536 unsigned int fcyc_bits = 0;
537 bfd_boolean prev_sploop_found = FALSE;
538
539 switch (opc->operand_info[op_num].form)
540 {
541 case tic6x_operand_retreg:
542 /* Fully determined by the functional unit. */
543 operands_text[op_num] = TRUE;
544 snprintf (operands[op_num], 24, "%c3",
545 (func_unit_side == 2 ? 'b' : 'a'));
546 continue;
547
548 case tic6x_operand_irp:
549 operands_text[op_num] = TRUE;
550 snprintf (operands[op_num], 24, "irp");
551 continue;
552
553 case tic6x_operand_nrp:
554 operands_text[op_num] = TRUE;
555 snprintf (operands[op_num], 24, "nrp");
556 continue;
557
558 default:
559 break;
560 }
561
562 for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
563 {
564 const tic6x_coding_field *const enc
565 = &opc->variable_fields[fld_num];
566 const tic6x_insn_field *field;
567 unsigned int fld_val;
568 signed int signed_fld_val;
569
570 if (enc->operand_num != op_num)
571 continue;
572 field = tic6x_field_from_fmt (fmt, enc->field_id);
573 if (!field)
574 abort ();
575 fld_val = tic6x_field_bits (opcode, field);
576 switch (enc->coding_method)
577 {
578 case tic6x_coding_ucst:
579 case tic6x_coding_ulcst_dpr_byte:
580 case tic6x_coding_ulcst_dpr_half:
581 case tic6x_coding_ulcst_dpr_word:
582 case tic6x_coding_lcst_low16:
583 switch (opc->operand_info[op_num].form)
584 {
585 case tic6x_operand_asm_const:
586 case tic6x_operand_link_const:
587 operands_text[op_num] = TRUE;
588 snprintf (operands[op_num], 24, "%u", fld_val);
589 break;
590
591 case tic6x_operand_mem_long:
592 mem_offset = fld_val;
593 mem_offset_known_long = TRUE;
594 break;
595
596 default:
597 abort ();
598 }
599 break;
600
601 case tic6x_coding_lcst_high16:
602 operands_text[op_num] = TRUE;
603 snprintf (operands[op_num], 24, "%u", fld_val << 16);
604 break;
605
606 case tic6x_coding_scst:
607 operands_text[op_num] = TRUE;
608 signed_fld_val = (signed int) fld_val;
609 signed_fld_val ^= (1 << (field->width - 1));
610 signed_fld_val -= (1 << (field->width - 1));
611 snprintf (operands[op_num], 24, "%d", signed_fld_val);
612 break;
613
614 case tic6x_coding_ucst_minus_one:
615 operands_text[op_num] = TRUE;
616 snprintf (operands[op_num], 24, "%u", fld_val + 1);
617 break;
618
619 case tic6x_coding_pcrel:
620 case tic6x_coding_pcrel_half:
621 signed_fld_val = (signed int) fld_val;
622 signed_fld_val ^= (1 << (field->width - 1));
623 signed_fld_val -= (1 << (field->width - 1));
624 if (fetch_packet_header_based
625 && enc->coding_method == tic6x_coding_pcrel_half)
626 signed_fld_val *= 2;
627 else
628 signed_fld_val *= 4;
629 operands_pcrel[op_num] = TRUE;
630 operands_addresses[op_num] = fp_addr + signed_fld_val;
631 break;
632
633 case tic6x_coding_reg_shift:
634 fld_val <<= 1;
635 /* Fall through. */
636 case tic6x_coding_reg:
637 switch (opc->operand_info[op_num].form)
638 {
639 case tic6x_operand_reg:
640 operands_text[op_num] = TRUE;
641 snprintf (operands[op_num], 24, "%c%u",
642 (func_unit_side == 2 ? 'b' : 'a'), fld_val);
643 break;
644
645 case tic6x_operand_xreg:
646 operands_text[op_num] = TRUE;
647 snprintf (operands[op_num], 24, "%c%u",
648 (((func_unit_side == 2) ^ func_unit_cross)
649 ? 'b'
650 : 'a'), fld_val);
651 break;
652
653 case tic6x_operand_dreg:
654 operands_text[op_num] = TRUE;
655 snprintf (operands[op_num], 24, "%c%u",
656 (func_unit_data_side == 2 ? 'b' : 'a'),
657 fld_val);
658 break;
659
660 case tic6x_operand_regpair:
661 operands_text[op_num] = TRUE;
662 if (fld_val & 1)
663 operands_ok = FALSE;
664 snprintf (operands[op_num], 24, "%c%u:%c%u",
665 (func_unit_side == 2 ? 'b' : 'a'), fld_val + 1,
666 (func_unit_side == 2 ? 'b' : 'a'), fld_val);
667 break;
668
669 case tic6x_operand_xregpair:
670 operands_text[op_num] = TRUE;
671 if (fld_val & 1)
672 operands_ok = FALSE;
673 snprintf (operands[op_num], 24, "%c%u:%c%u",
674 (((func_unit_side == 2) ^ func_unit_cross)
675 ? 'b'
676 : 'a'), fld_val + 1,
677 (((func_unit_side == 2) ^ func_unit_cross)
678 ? 'b'
679 : 'a'), fld_val);
680 break;
681
682 case tic6x_operand_dregpair:
683 operands_text[op_num] = TRUE;
684 if (fld_val & 1)
685 operands_ok = FALSE;
686 snprintf (operands[op_num], 24, "%c%u:%c%u",
687 (func_unit_data_side == 2 ? 'b' : 'a'),
688 fld_val + 1,
689 (func_unit_data_side == 2 ? 'b' : 'a'),
690 fld_val);
691 break;
692
693 case tic6x_operand_mem_deref:
694 operands_text[op_num] = TRUE;
695 snprintf (operands[op_num], 24, "*%c%u",
696 (func_unit_side == 2 ? 'b' : 'a'), fld_val);
697 break;
698
699 case tic6x_operand_mem_short:
700 case tic6x_operand_mem_ndw:
701 mem_base_reg = fld_val;
702 mem_base_reg_known = TRUE;
703 break;
704
705 default:
706 abort ();
707 }
708 break;
709
710 case tic6x_coding_areg:
711 switch (opc->operand_info[op_num].form)
712 {
713 case tic6x_operand_areg:
714 operands_text[op_num] = TRUE;
715 snprintf (operands[op_num], 24, "b%u",
716 fld_val ? 15u : 14u);
717 break;
718
719 case tic6x_operand_mem_long:
720 mem_base_reg = fld_val ? 15u : 14u;
721 mem_base_reg_known_long = TRUE;
722 break;
723
724 default:
725 abort ();
726 }
727 break;
728
729 case tic6x_coding_mem_offset:
730 case tic6x_coding_mem_offset_noscale:
731 mem_offset = fld_val;
732 mem_offset_known = TRUE;
733 break;
734
735 case tic6x_coding_mem_mode:
736 mem_mode = fld_val;
737 mem_mode_known = TRUE;
738 break;
739
740 case tic6x_coding_scaled:
741 mem_scaled = fld_val;
742 mem_scaled_known = TRUE;
743 break;
744
745 case tic6x_coding_crlo:
746 crlo = fld_val;
747 crlo_known = TRUE;
748 break;
749
750 case tic6x_coding_crhi:
751 crhi = fld_val;
752 crhi_known = TRUE;
753 break;
754
755 case tic6x_coding_fstg:
756 case tic6x_coding_fcyc:
757 if (!prev_sploop_found)
758 {
759 bfd_vma search_fp_addr = fp_addr;
760 bfd_vma search_fp_offset = fp_offset;
761 bfd_boolean search_fp_header_based
762 = fetch_packet_header_based;
763 tic6x_fetch_packet_header search_fp_header = header;
764 unsigned char search_fp[32];
765 unsigned int search_num_bits;
766 unsigned int search_opcode;
767 unsigned int sploop_ii = 0;
768 int i;
769
770 memcpy (search_fp, fp, 32);
771
772 /* To interpret these bits in an SPKERNEL
773 instruction, we must find the previous
774 SPLOOP-family instruction. It may come up to
775 48 execute packets earlier. */
776 for (i = 0; i < 48 * 8; i++)
777 {
778 /* Find the previous instruction. */
779 if (search_fp_offset & 2)
780 search_fp_offset -= 2;
781 else if (search_fp_offset >= 4)
782 {
783 if (search_fp_header_based
784 && (search_fp_header.word_compact
785 [(search_fp_offset >> 2) - 1]))
786 search_fp_offset -= 2;
787 else
788 search_fp_offset -= 4;
789 }
790 else
791 {
792 search_fp_addr -= 32;
793 status = info->read_memory_func (search_fp_addr,
794 search_fp,
795 32, info);
796 if (status)
797 /* No previous SPLOOP instruction. */
798 break;
799 search_fp_header_based
800 = (tic6x_check_fetch_packet_header
801 (search_fp, &search_fp_header, info));
802 if (search_fp_header_based)
803 search_fp_offset
804 = search_fp_header.word_compact[6] ? 26 : 24;
805 else
806 search_fp_offset = 28;
807 }
808
809 /* Extract the previous instruction. */
810 if (search_fp_header_based)
811 search_num_bits
812 = (search_fp_header.word_compact[search_fp_offset
813 >> 2]
814 ? 16
815 : 32);
816 else
817 search_num_bits = 32;
818 if (search_num_bits == 16)
819 {
820 if (info->endian == BFD_ENDIAN_LITTLE)
821 search_opcode
822 = (tic6x_extract_16
823 (search_fp + search_fp_offset, info));
824 else
825 search_opcode
826 = (tic6x_extract_16
827 (search_fp + (search_fp_offset ^ 2),
828 info));
829 }
830 else
831 search_opcode
832 = tic6x_extract_32 (search_fp + search_fp_offset,
833 info);
834
835 /* Check whether it is an SPLOOP-family
836 instruction. */
837 if (search_num_bits == 32
838 && ((search_opcode & 0x003ffffe) == 0x00038000
839 || (search_opcode & 0x003ffffe) == 0x0003a000
840 || ((search_opcode & 0x003ffffe)
841 == 0x0003e000)))
842 {
843 prev_sploop_found = TRUE;
844 sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
845 }
846 else if (search_num_bits == 16
847 && (search_opcode & 0x3c7e) == 0x0c66)
848 {
849 prev_sploop_found = TRUE;
850 sploop_ii
851 = (((search_opcode >> 7) & 0x7)
852 | ((search_opcode >> 11) & 0x8)) + 1;
853 }
854 if (prev_sploop_found)
855 {
856 if (sploop_ii <= 0)
857 abort ();
858 else if (sploop_ii <= 1)
859 fcyc_bits = 0;
860 else if (sploop_ii <= 2)
861 fcyc_bits = 1;
862 else if (sploop_ii <= 4)
863 fcyc_bits = 2;
864 else if (sploop_ii <= 8)
865 fcyc_bits = 3;
866 else if (sploop_ii <= 14)
867 fcyc_bits = 4;
868 else
869 prev_sploop_found = FALSE;
870 }
871 if (prev_sploop_found)
872 break;
873 }
874 }
875 if (!prev_sploop_found)
876 {
877 operands_ok = FALSE;
878 operands_text[op_num] = TRUE;
879 break;
880 }
881 if (fcyc_bits > field->width)
882 abort ();
883 if (enc->coding_method == tic6x_coding_fstg)
884 {
885 int i, t;
886 for (t = 0, i = fcyc_bits; i < 6; i++)
887 t = (t << 1) | ((fld_val >> i) & 1);
888 operands_text[op_num] = TRUE;
889 snprintf (operands[op_num], 24, "%u", t);
890 }
891 else
892 {
893 operands_text[op_num] = TRUE;
894 snprintf (operands[op_num], 24, "%u",
895 fld_val & ((1 << fcyc_bits) - 1));
896 }
897 break;
898
899 case tic6x_coding_spmask:
900 if (fld_val == 0)
901 spmask_skip_operand = TRUE;
902 else
903 {
904 char *p;
905 unsigned int i;
906
907 operands_text[op_num] = TRUE;
908 p = operands[op_num];
909 for (i = 0; i < 8; i++)
910 if (fld_val & (1 << i))
911 {
912 *p++ = "LSDM"[i/2];
913 *p++ = '1' + (i & 1);
914 *p++ = ',';
915 }
916 p[-1] = 0;
917 }
918 break;
919
920 case tic6x_coding_fu:
921 case tic6x_coding_data_fu:
922 case tic6x_coding_xpath:
923 /* Don't relate to operands, so operand number is
924 meaningless. */
925 break;
926
927 default:
928 abort ();
929 }
930
931 if (mem_base_reg_known_long && mem_offset_known_long)
932 {
933 if (operands_text[op_num] || operands_pcrel[op_num])
934 abort ();
935 operands_text[op_num] = TRUE;
936 snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
937 mem_offset * opc->operand_info[op_num].size);
938 }
939
940 if (mem_base_reg_known && mem_offset_known && mem_mode_known
941 && (mem_scaled_known
942 || (opc->operand_info[op_num].form
943 != tic6x_operand_mem_ndw)))
944 {
945 char side;
946 char base[4];
947 bfd_boolean offset_is_reg;
948 bfd_boolean offset_scaled;
949 char offset[4];
950 char offsetp[6];
951
952 if (operands_text[op_num] || operands_pcrel[op_num])
953 abort ();
954
955 side = func_unit_side == 2 ? 'b' : 'a';
956 snprintf (base, 4, "%c%u", side, mem_base_reg);
957
958 offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
959 if (offset_is_reg)
960 {
961 snprintf (offset, 4, "%c%u", side, mem_offset);
962 if (opc->operand_info[op_num].form
963 == tic6x_operand_mem_ndw)
964 offset_scaled = mem_scaled ? TRUE : FALSE;
965 else
966 offset_scaled = TRUE;
967 }
968 else
969 {
970 if (opc->operand_info[op_num].form
971 == tic6x_operand_mem_ndw)
972 {
973 offset_scaled = mem_scaled ? TRUE : FALSE;
974 snprintf (offset, 4, "%u", mem_offset);
975 }
976 else
977 {
978 offset_scaled = FALSE;
979 snprintf (offset, 4, "%u",
980 (mem_offset
981 * opc->operand_info[op_num].size));
982 }
983 }
984
985 if (offset_scaled)
986 snprintf (offsetp, 6, "[%s]", offset);
987 else
988 snprintf (offsetp, 6, "(%s)", offset);
989
990 operands_text[op_num] = TRUE;
991 switch (mem_mode & ~4u)
992 {
993 case 0:
994 snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
995 break;
996
997 case 1:
998 snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
999 break;
1000
1001 case 2:
1002 case 3:
1003 operands_ok = FALSE;
1004 break;
1005
1006 case 8:
1007 snprintf (operands[op_num], 24, "*--%s%s", base,
1008 offsetp);
1009 break;
1010
1011 case 9:
1012 snprintf (operands[op_num], 24, "*++%s%s", base,
1013 offsetp);
1014 break;
1015
1016 case 10:
1017 snprintf (operands[op_num], 24, "*%s--%s", base,
1018 offsetp);
1019 break;
1020
1021 case 11:
1022 snprintf (operands[op_num], 24, "*%s++%s", base,
1023 offsetp);
1024 break;
1025
1026 default:
1027 abort ();
1028 }
1029 }
1030
1031 if (crlo_known && crhi_known)
1032 {
1033 tic6x_rw rw;
1034 tic6x_ctrl_id crid;
1035
1036 if (operands_text[op_num] || operands_pcrel[op_num])
1037 abort ();
1038
1039 rw = opc->operand_info[op_num].rw;
1040 if (rw != tic6x_rw_read
1041 && rw != tic6x_rw_write)
1042 abort ();
1043
1044 for (crid = 0; crid < tic6x_ctrl_max; crid++)
1045 {
1046 if (crlo == tic6x_ctrl_table[crid].crlo
1047 && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
1048 && (rw == tic6x_rw_read
1049 ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
1050 || (tic6x_ctrl_table[crid].rw
1051 == tic6x_rw_read_write))
1052 : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
1053 || (tic6x_ctrl_table[crid].rw
1054 == tic6x_rw_read_write))))
1055 break;
1056 }
1057 if (crid == tic6x_ctrl_max)
1058 {
1059 operands_text[op_num] = TRUE;
1060 operands_ok = FALSE;
1061 }
1062 else
1063 {
1064 operands_text[op_num] = TRUE;
1065 snprintf (operands[op_num], 24, "%s",
1066 tic6x_ctrl_table[crid].name);
1067 }
1068 }
1069
1070 if (operands_text[op_num] || operands_pcrel[op_num]
1071 || spmask_skip_operand)
1072 break;
1073 }
1074 if (spmask_skip_operand)
1075 {
1076 /* SPMASK operands are only valid as the single operand
1077 in the opcode table. */
1078 if (num_operands != 1)
1079 abort ();
1080 num_operands = 0;
1081 break;
1082 }
1083 /* The operand must by now have been decoded. */
1084 if (!operands_text[op_num] && !operands_pcrel[op_num])
1085 abort ();
1086 }
1087
1088 if (!operands_ok)
1089 continue;
1090
1091 info->bytes_per_chunk = num_bits / 8;
1092 info->fprintf_func (info->stream, "%s%s%s%s", parallel, cond,
1093 opc->name, func_unit);
1094 for (op_num = 0; op_num < num_operands; op_num++)
1095 {
1096 info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
1097 if (operands_pcrel[op_num])
1098 info->print_address_func (operands_addresses[op_num], info);
1099 else
1100 info->fprintf_func (info->stream, "%s", operands[op_num]);
1101 }
1102 if (fetch_packet_header_based && header.prot)
1103 info->fprintf_func (info->stream, " || nop 5");
1104
1105 return num_bits / 8;
1106 }
1107
1108 info->bytes_per_chunk = num_bits / 8;
1109 info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
1110 (int) num_bits / 4, opcode);
1111 return num_bits / 8;
1112 }
This page took 0.099701 seconds and 5 git commands to generate.