PR ld/11843
[binutils.git] / opcodes / tic6x-dis.c
blob80320848770e8ce649ad092eab54749ae87175b4
1 /* TI C6X disassembler.
2 Copyright 2010
3 Free Software Foundation, Inc.
5 This file is part of libopcodes.
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.
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.
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. */
22 #include "sysdep.h"
23 #include "dis-asm.h"
24 #include "opcode/tic6x.h"
25 #include "libiberty.h"
27 /* Define the instruction format table. */
28 const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
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
36 /* Define the control register table. */
37 const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
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 \
47 #include "opcode/tic6x-control-registers.h"
48 #undef CTRL
51 /* Define the opcode table. */
52 const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
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 \
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 \
78 #include "opcode/tic6x-opcode-table.h"
79 #undef INSN
80 #undef INSNE
83 /* If instruction format FMT has a field FIELD, return a pointer to
84 the description of that field; otherwise return NULL. */
86 const tic6x_insn_field *
87 tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
89 unsigned int f;
91 for (f = 0; f < fmt->num_fields; f++)
92 if (fmt->fields[f].field_id == field)
93 return &fmt->fields[f];
95 return NULL;
98 /* Extract the bits corresponding to FIELD from OPCODE. */
100 static unsigned int
101 tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
103 return (opcode >> field->low_pos) & ((1u << field->width) - 1);
106 /* Extract a 32-bit value read from the instruction stream. */
108 static unsigned int
109 tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
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);
117 /* Extract a 16-bit value read from the instruction stream. */
119 static unsigned int
120 tic6x_extract_16 (unsigned char *p, struct disassemble_info *info)
122 if (info->endian == BFD_ENDIAN_LITTLE)
123 return (p[0]) | (p[1] << 8);
124 else
125 return (p[1]) | (p[0] << 8);
128 /* FP points to a fetch packet. Return whether it is header-based; if
129 it is, fill in HEADER. */
131 static bfd_boolean
132 tic6x_check_fetch_packet_header (unsigned char *fp,
133 tic6x_fetch_packet_header *header,
134 struct disassemble_info *info)
136 int i;
138 header->header = tic6x_extract_32 (fp + 28, info);
139 if ((header->header & 0xf0000000) != 0xe0000000)
140 return FALSE;
142 for (i = 0; i < 7; i++)
143 header->word_compact[i]
144 = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
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;
152 for (i = 0; i < 14; i++)
153 header->p_bits[i]
154 = (header->header & (1u << i)) ? TRUE : FALSE;
156 return TRUE;
159 /* Disassemble the instruction at ADDR and print it using
160 INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
161 consumed. */
164 print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
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;
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)
182 info->memory_error_func (status, addr, info);
183 return -1;
186 fetch_packet_header_based
187 = tic6x_check_fetch_packet_header (fp, &header, info);
188 if (fetch_packet_header_based)
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)
197 info->bytes_per_chunk = 4;
198 info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
199 header.header);
200 return 4;
202 num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
204 else
206 num_bits = 32;
207 if (fp_offset & 0x3)
208 bad_offset = TRUE;
211 if (bad_offset)
213 info->bytes_per_chunk = 1;
214 info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
215 return 1;
218 if (num_bits == 16)
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);
230 else
231 opcode = tic6x_extract_32 (fp + fp_offset, info);
233 for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
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;
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;
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)
274 const tic6x_insn_field *z_field;
275 unsigned int creg_value, z_value;
276 static const char *const conds[8][2] =
278 { "", NULL },
279 { "[b0] ", "[!b0] " },
280 { "[b1] ", "[!b1] " },
281 { "[b2] ", "[!b2] " },
282 { "[a1] ", "[!a1] " },
283 { "[a2] ", "[!a2] " },
284 { "[a0] ", "[!a0] " },
285 { NULL, NULL }
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 ();
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;
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++)
307 unsigned int field_bits;
308 const tic6x_insn_field *const field
309 = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
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)
317 fixed_ok = FALSE;
318 break;
321 if (!fixed_ok)
322 continue;
324 /* The instruction matches. */
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)
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];
339 else if (fp_offset >= 4)
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
349 unsigned int prev_opcode
350 = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
351 p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
354 else
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
365 bfd_boolean prev_header_based;
366 tic6x_fetch_packet_header prev_header;
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
374 unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
375 info);
376 p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
380 parallel = p_bit ? "|| " : "";
382 if (opc->func_unit == tic6x_func_unit_nfu)
383 func_unit = "";
384 else
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;
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;
396 for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
398 const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
399 const tic6x_insn_field *field;
400 unsigned int fld_val;
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)
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;
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;
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;
431 case tic6x_coding_areg:
432 have_areg = TRUE;
433 break;
435 default:
436 /* Don't relate to functional units. */
437 break;
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 ();
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 ();
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 ();
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)
463 if (have_cross)
464 abort ();
465 func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
468 switch (opc->func_unit)
470 case tic6x_func_unit_d:
471 func_unit_char = 'D';
472 break;
474 case tic6x_func_unit_l:
475 func_unit_char = 'L';
476 break;
478 case tic6x_func_unit_m:
479 func_unit_char = 'M';
480 break;
482 case tic6x_func_unit_s:
483 func_unit_char = 'S';
484 break;
486 default:
487 abort ();
490 switch (func_unit_data_side)
492 case 0:
493 data_str = "";
494 break;
496 case 1:
497 data_str = "T1";
498 break;
500 case 2:
501 data_str = "T2";
502 break;
504 default:
505 abort ();
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;
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++)
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;
539 switch (opc->operand_info[op_num].form)
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;
548 case tic6x_operand_irp:
549 operands_text[op_num] = TRUE;
550 snprintf (operands[op_num], 24, "irp");
551 continue;
553 case tic6x_operand_nrp:
554 operands_text[op_num] = TRUE;
555 snprintf (operands[op_num], 24, "nrp");
556 continue;
558 default:
559 break;
562 for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
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;
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)
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)
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;
591 case tic6x_operand_mem_long:
592 mem_offset = fld_val;
593 mem_offset_known_long = TRUE;
594 break;
596 default:
597 abort ();
599 break;
601 case tic6x_coding_lcst_high16:
602 operands_text[op_num] = TRUE;
603 snprintf (operands[op_num], 24, "%u", fld_val << 16);
604 break;
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;
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;
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;
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)
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;
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;
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;
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;
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;
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;
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;
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;
705 default:
706 abort ();
708 break;
710 case tic6x_coding_areg:
711 switch (opc->operand_info[op_num].form)
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;
719 case tic6x_operand_mem_long:
720 mem_base_reg = fld_val ? 15u : 14u;
721 mem_base_reg_known_long = TRUE;
722 break;
724 default:
725 abort ();
727 break;
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;
735 case tic6x_coding_mem_mode:
736 mem_mode = fld_val;
737 mem_mode_known = TRUE;
738 break;
740 case tic6x_coding_scaled:
741 mem_scaled = fld_val;
742 mem_scaled_known = TRUE;
743 break;
745 case tic6x_coding_crlo:
746 crlo = fld_val;
747 crlo_known = TRUE;
748 break;
750 case tic6x_coding_crhi:
751 crhi = fld_val;
752 crhi_known = TRUE;
753 break;
755 case tic6x_coding_fstg:
756 case tic6x_coding_fcyc:
757 if (!prev_sploop_found)
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;
770 memcpy (search_fp, fp, 32);
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++)
778 /* Find the previous instruction. */
779 if (search_fp_offset & 2)
780 search_fp_offset -= 2;
781 else if (search_fp_offset >= 4)
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;
790 else
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;
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)
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));
830 else
831 search_opcode
832 = tic6x_extract_32 (search_fp + search_fp_offset,
833 info);
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)))
843 prev_sploop_found = TRUE;
844 sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
846 else if (search_num_bits == 16
847 && (search_opcode & 0x3c7e) == 0x0c66)
849 prev_sploop_found = TRUE;
850 sploop_ii
851 = (((search_opcode >> 7) & 0x7)
852 | ((search_opcode >> 11) & 0x8)) + 1;
854 if (prev_sploop_found)
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;
871 if (prev_sploop_found)
872 break;
875 if (!prev_sploop_found)
877 operands_ok = FALSE;
878 operands_text[op_num] = TRUE;
879 break;
881 if (fcyc_bits > field->width)
882 abort ();
883 if (enc->coding_method == tic6x_coding_fstg)
885 operands_text[op_num] = TRUE;
886 snprintf (operands[op_num], 24, "%u",
887 fld_val >> fcyc_bits);
889 else
891 operands_text[op_num] = TRUE;
892 snprintf (operands[op_num], 24, "%u",
893 fld_val & ((1 << fcyc_bits) - 1));
895 break;
897 case tic6x_coding_spmask:
898 if (fld_val == 0)
899 spmask_skip_operand = TRUE;
900 else
902 char *p;
903 unsigned int i;
905 operands_text[op_num] = TRUE;
906 p = operands[op_num];
907 for (i = 0; i < 8; i++)
908 if (fld_val & (1 << i))
910 *p++ = "LSDM"[i/2];
911 *p++ = '1' + (i & 1);
912 *p++ = ',';
914 p[-1] = 0;
916 break;
918 case tic6x_coding_fu:
919 case tic6x_coding_data_fu:
920 case tic6x_coding_xpath:
921 /* Don't relate to operands, so operand number is
922 meaningless. */
923 break;
925 default:
926 abort ();
929 if (mem_base_reg_known_long && mem_offset_known_long)
931 if (operands_text[op_num] || operands_pcrel[op_num])
932 abort ();
933 operands_text[op_num] = TRUE;
934 snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
935 mem_offset * opc->operand_info[op_num].size);
938 if (mem_base_reg_known && mem_offset_known && mem_mode_known
939 && (mem_scaled_known
940 || (opc->operand_info[op_num].form
941 != tic6x_operand_mem_ndw)))
943 char side;
944 char base[4];
945 bfd_boolean offset_is_reg;
946 bfd_boolean offset_scaled;
947 char offset[4];
948 char offsetp[6];
950 if (operands_text[op_num] || operands_pcrel[op_num])
951 abort ();
953 side = func_unit_side == 2 ? 'b' : 'a';
954 snprintf (base, 4, "%c%u", side, mem_base_reg);
956 offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
957 if (offset_is_reg)
959 snprintf (offset, 4, "%c%u", side, mem_offset);
960 if (opc->operand_info[op_num].form
961 == tic6x_operand_mem_ndw)
962 offset_scaled = mem_scaled ? TRUE : FALSE;
963 else
964 offset_scaled = TRUE;
966 else
968 if (opc->operand_info[op_num].form
969 == tic6x_operand_mem_ndw)
971 offset_scaled = mem_scaled ? TRUE : FALSE;
972 snprintf (offset, 4, "%u", mem_offset);
974 else
976 offset_scaled = FALSE;
977 snprintf (offset, 4, "%u",
978 (mem_offset
979 * opc->operand_info[op_num].size));
983 if (offset_scaled)
984 snprintf (offsetp, 6, "[%s]", offset);
985 else
986 snprintf (offsetp, 6, "(%s)", offset);
988 operands_text[op_num] = TRUE;
989 switch (mem_mode & ~4u)
991 case 0:
992 snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
993 break;
995 case 1:
996 snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
997 break;
999 case 2:
1000 case 3:
1001 operands_ok = FALSE;
1002 break;
1004 case 8:
1005 snprintf (operands[op_num], 24, "*--%s%s", base,
1006 offsetp);
1007 break;
1009 case 9:
1010 snprintf (operands[op_num], 24, "*++%s%s", base,
1011 offsetp);
1012 break;
1014 case 10:
1015 snprintf (operands[op_num], 24, "*%s--%s", base,
1016 offsetp);
1017 break;
1019 case 11:
1020 snprintf (operands[op_num], 24, "*%s++%s", base,
1021 offsetp);
1022 break;
1024 default:
1025 abort ();
1029 if (crlo_known && crhi_known)
1031 tic6x_rw rw;
1032 tic6x_ctrl_id crid;
1034 if (operands_text[op_num] || operands_pcrel[op_num])
1035 abort ();
1037 rw = opc->operand_info[op_num].rw;
1038 if (rw != tic6x_rw_read
1039 && rw != tic6x_rw_write)
1040 abort ();
1042 for (crid = 0; crid < tic6x_ctrl_max; crid++)
1044 if (crlo == tic6x_ctrl_table[crid].crlo
1045 && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
1046 && (rw == tic6x_rw_read
1047 ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
1048 || (tic6x_ctrl_table[crid].rw
1049 == tic6x_rw_read_write))
1050 : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
1051 || (tic6x_ctrl_table[crid].rw
1052 == tic6x_rw_read_write))))
1053 break;
1055 if (crid == tic6x_ctrl_max)
1057 operands_text[op_num] = TRUE;
1058 operands_ok = FALSE;
1060 else
1062 operands_text[op_num] = TRUE;
1063 snprintf (operands[op_num], 24, "%s",
1064 tic6x_ctrl_table[crid].name);
1068 if (operands_text[op_num] || operands_pcrel[op_num]
1069 || spmask_skip_operand)
1070 break;
1072 if (spmask_skip_operand)
1074 /* SPMASK operands are only valid as the single operand
1075 in the opcode table. */
1076 if (num_operands != 1)
1077 abort ();
1078 num_operands = 0;
1079 break;
1081 /* The operand must by now have been decoded. */
1082 if (!operands_text[op_num] && !operands_pcrel[op_num])
1083 abort ();
1086 if (!operands_ok)
1087 continue;
1089 info->bytes_per_chunk = num_bits / 8;
1090 info->fprintf_func (info->stream, "%s%s%s%s", parallel, cond,
1091 opc->name, func_unit);
1092 for (op_num = 0; op_num < num_operands; op_num++)
1094 info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
1095 if (operands_pcrel[op_num])
1096 info->print_address_func (operands_addresses[op_num], info);
1097 else
1098 info->fprintf_func (info->stream, "%s", operands[op_num]);
1100 if (fetch_packet_header_based && header.prot)
1101 info->fprintf_func (info->stream, " || nop 5");
1103 return num_bits / 8;
1106 info->bytes_per_chunk = num_bits / 8;
1107 info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
1108 (int) num_bits / 4, opcode);
1109 return num_bits / 8;