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