1 /* TI C6X disassembler.
2 Copyright (C) 2010-2024 Free Software Foundation, Inc.
3 Contributed by Joseph Myers <joseph@codesourcery.com>
4 Bernd Schmidt <bernds@codesourcery.com>
6 This file is part of libopcodes.
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.
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.
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. */
24 #include "disassemble.h"
25 #include "opcode/tic6x.h"
26 #include "libiberty.h"
28 /* Define the instruction format table. */
29 const tic6x_insn_format tic6x_insn_format_table
[tic6x_insn_format_max
] =
31 #define FMT(name, num_bits, cst_bits, mask, fields) \
32 { num_bits, cst_bits, mask, fields },
33 #include "opcode/tic6x-insn-formats.h"
37 /* Define the control register table. */
38 const tic6x_ctrl tic6x_ctrl_table
[tic6x_ctrl_max
] =
40 #define CTRL(name, isa, rw, crlo, crhi_mask) \
43 CONCAT2(TIC6X_INSN_,isa), \
44 CONCAT2(tic6x_rw_,rw), \
48 #include "opcode/tic6x-control-registers.h"
52 /* Define the opcode table. */
53 const tic6x_opcode tic6x_opcode_table
[tic6x_opcode_max
] =
55 #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \
58 CONCAT2(tic6x_func_unit_,func_unit), \
59 CONCAT3(tic6x_insn_format,_,format), \
60 CONCAT2(tic6x_pipeline_,type), \
61 CONCAT2(TIC6X_INSN_,isa), \
67 #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
70 CONCAT2(tic6x_func_unit_,func_unit), \
71 CONCAT3(tic6x_insn_format,_,format), \
72 CONCAT2(tic6x_pipeline_,type), \
73 CONCAT2(TIC6X_INSN_,isa), \
79 #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
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), \
91 #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
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), \
103 #include "opcode/tic6x-opcode-table.h"
110 /* If instruction format FMT has a field FIELD, return a pointer to
111 the description of that field; otherwise return NULL. */
113 const tic6x_insn_field
*
114 tic6x_field_from_fmt (const tic6x_insn_format
*fmt
, tic6x_insn_field_id field
)
118 for (f
= 0; f
< fmt
->num_fields
; f
++)
119 if (fmt
->fields
[f
].field_id
== field
)
120 return &fmt
->fields
[f
];
125 /* Extract the field width. */
128 tic6x_field_width (const tic6x_insn_field
*field
)
131 unsigned int width
= 0;
133 if (!field
->num_bitfields
)
134 return field
->bitfields
[0].width
;
136 for (i
= 0 ; i
< field
->num_bitfields
; i
++)
137 width
+= field
->bitfields
[i
].width
;
142 /* Extract the bits corresponding to FIELD from OPCODE. */
145 tic6x_field_bits (unsigned int opcode
, const tic6x_insn_field
*field
)
148 unsigned int val
= 0;
150 if (!field
->num_bitfields
)
151 return (opcode
>> field
->bitfields
[0].low_pos
) & ((1u << field
->bitfields
[0].width
) - 1);
153 for (i
= 0 ; i
< field
->num_bitfields
; i
++)
154 val
|= ((opcode
>> field
->bitfields
[i
].low_pos
) & ((1u << field
->bitfields
[i
].width
) - 1))
155 << field
->bitfields
[i
].pos
;
160 /* Extract a 32-bit value read from the instruction stream. */
163 tic6x_extract_32 (unsigned char *p
, struct disassemble_info
*info
)
165 if (info
->endian
== BFD_ENDIAN_LITTLE
)
166 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | ((unsigned) p
[3] << 24);
168 return p
[3] | (p
[2] << 8) | (p
[1] << 16) | ((unsigned) p
[0] << 24);
171 /* Extract a 16-bit value read from the instruction stream. */
174 tic6x_extract_16 (unsigned char *p
, tic6x_fetch_packet_header
*header
,
175 struct disassemble_info
*info
)
179 if (info
->endian
== BFD_ENDIAN_LITTLE
)
180 op16
= (p
[0]) | (p
[1] << 8);
182 op16
= (p
[1]) | (p
[0] << 8);
183 op16
|= (header
->sat
<< TIC6X_COMPACT_SAT_POS
);
184 op16
|= (header
->br
<< TIC6X_COMPACT_BR_POS
);
185 op16
|= (header
->dsz
<< TIC6X_COMPACT_DSZ_POS
);
189 /* FP points to a fetch packet. Return whether it is header-based; if
190 it is, fill in HEADER. */
193 tic6x_check_fetch_packet_header (unsigned char *fp
,
194 tic6x_fetch_packet_header
*header
,
195 struct disassemble_info
*info
)
199 header
->header
= tic6x_extract_32 (fp
+ 28, info
);
201 if ((header
->header
& 0xf0000000) != 0xe0000000)
208 for (i
= 0; i
< 7; i
++)
209 header
->word_compact
[i
] = false;
210 for (i
= 0; i
< 14; i
++)
211 header
->p_bits
[i
] = false;
215 for (i
= 0; i
< 7; i
++)
216 header
->word_compact
[i
]
217 = (header
->header
& (1u << (21 + i
))) != 0;
219 header
->prot
= (header
->header
& (1u << 20)) != 0;
220 header
->rs
= (header
->header
& (1u << 19)) != 0;
221 header
->dsz
= (header
->header
>> 16) & 0x7;
222 header
->br
= (header
->header
& (1u << 15)) != 0;
223 header
->sat
= (header
->header
& (1u << 14)) != 0;
225 for (i
= 0; i
< 14; i
++)
226 header
->p_bits
[i
] = (header
->header
& (1u << i
)) != 0;
231 /* Disassemble the instruction at ADDR and print it using
232 INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
236 print_insn_tic6x (bfd_vma addr
, struct disassemble_info
*info
)
241 unsigned char fp
[32];
243 tic6x_opcode_id opcode_id
;
244 bool fetch_packet_header_based
;
245 tic6x_fetch_packet_header header
;
246 unsigned int num_bits
;
247 bool bad_offset
= false;
249 fp_offset
= addr
& 0x1f;
250 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. */
254 status
= info
->read_memory_func (fp_addr
, fp
, 32, info
);
257 info
->memory_error_func (status
, addr
, info
);
261 fetch_packet_header_based
262 = tic6x_check_fetch_packet_header (fp
, &header
, info
);
263 if (fetch_packet_header_based
)
267 if ((fp_offset
& 0x3) && (fp_offset
>= 28
268 || !header
.word_compact
[fp_offset
>> 2]))
272 info
->bytes_per_chunk
= 4;
273 info
->fprintf_func (info
->stream
, "<fetch packet header 0x%.8x>",
277 num_bits
= (header
.word_compact
[fp_offset
>> 2] ? 16 : 32);
288 info
->bytes_per_chunk
= 1;
289 info
->fprintf_func (info
->stream
, ".byte 0x%.2x", fp
[fp_offset
]);
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 if (info
->endian
== BFD_ENDIAN_LITTLE
)
301 opcode
= tic6x_extract_16 (fp
+ fp_offset
, &header
, info
);
303 opcode
= tic6x_extract_16 (fp
+ (fp_offset
^ 2), &header
, info
);
306 opcode
= tic6x_extract_32 (fp
+ fp_offset
, info
);
308 for (opcode_id
= 0; opcode_id
< tic6x_opcode_max
; opcode_id
++)
310 const tic6x_opcode
*const opc
= &tic6x_opcode_table
[opcode_id
];
311 const tic6x_insn_format
*const fmt
312 = &tic6x_insn_format_table
[opc
->format
];
313 const tic6x_insn_field
*creg_field
;
315 const char *parallel
;
316 const char *cond
= "";
317 const char *func_unit
;
318 char func_unit_buf
[8];
319 unsigned int func_unit_side
= 0;
320 unsigned int func_unit_data_side
= 0;
321 unsigned int func_unit_cross
= 0;
322 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 char operands
[TIC6X_MAX_OPERANDS
][24] = { { 0 } };
327 bfd_vma operands_addresses
[TIC6X_MAX_OPERANDS
] = { 0 };
328 bool operands_text
[TIC6X_MAX_OPERANDS
] = { false };
329 bool operands_pcrel
[TIC6X_MAX_OPERANDS
] = { false };
331 unsigned int num_operands
;
337 if (opc
->flags
& TIC6X_FLAG_MACRO
)
339 if (fmt
->num_bits
!= num_bits
)
341 if ((opcode
& fmt
->mask
) != fmt
->cst_bits
)
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 creg_field
= tic6x_field_from_fmt (fmt
, tic6x_field_creg
);
351 const tic6x_insn_field
*z_field
;
352 unsigned int creg_value
, z_value
;
353 static const char *const conds
[8][2] =
356 { "[b0] ", "[!b0] " },
357 { "[b1] ", "[!b1] " },
358 { "[b2] ", "[!b2] " },
359 { "[a1] ", "[!a1] " },
360 { "[a2] ", "[!a2] " },
361 { "[a0] ", "[!a0] " },
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
368 z_field
= tic6x_field_from_fmt (fmt
, tic6x_field_z
);
371 printf ("*** opcode %x: missing z field", opcode
);
375 creg_value
= tic6x_field_bits (opcode
, creg_field
);
376 z_value
= tic6x_field_bits (opcode
, z_field
);
377 cond
= conds
[creg_value
][z_value
];
382 if (opc
->flags
& TIC6X_FLAG_INSN16_SPRED
)
384 const tic6x_insn_field
*cc_field
;
385 unsigned int s_value
= 0;
386 unsigned int z_value
= 0;
387 bool cond_known
= false;
388 static const char *const conds
[2][2] =
390 { "[a0] ", "[!a0] " },
391 { "[b0] ", "[!b0] " }
394 cc_field
= tic6x_field_from_fmt (fmt
, tic6x_field_cc
);
398 unsigned int cc_value
;
400 cc_value
= tic6x_field_bits (opcode
, cc_field
);
401 s_value
= (cc_value
& 0x2) >> 1;
402 z_value
= (cc_value
& 0x1);
407 const tic6x_insn_field
*z_field
;
408 const tic6x_insn_field
*s_field
;
410 s_field
= tic6x_field_from_fmt (fmt
, tic6x_field_s
);
414 printf ("opcode %x: missing compact insn predicate register field (s field)\n",
418 s_value
= tic6x_field_bits (opcode
, s_field
);
419 z_field
= tic6x_field_from_fmt (fmt
, tic6x_field_z
);
422 printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode
);
426 z_value
= tic6x_field_bits (opcode
, z_field
);
432 printf ("opcode %x: unspecified ompact insn predicate\n", opcode
);
435 cond
= conds
[s_value
][z_value
];
438 /* All fixed fields must have matching values; all fields with
439 restricted ranges must have values within those ranges. */
441 for (fix
= 0; fix
< opc
->num_fixed_fields
; fix
++)
443 unsigned int field_bits
;
444 const tic6x_insn_field
*const field
445 = tic6x_field_from_fmt (fmt
, opc
->fixed_fields
[fix
].field_id
);
449 printf ("opcode %x: missing field #%d for FIX #%d\n",
450 opcode
, opc
->fixed_fields
[fix
].field_id
, fix
);
454 field_bits
= tic6x_field_bits (opcode
, field
);
455 if (field_bits
< opc
->fixed_fields
[fix
].min_val
456 || field_bits
> opc
->fixed_fields
[fix
].max_val
)
465 /* The instruction matches. */
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
472 if (num_bits
== 16 && (fp_offset
& 0x2) == 2)
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 p_bit
= header
.p_bits
[(fp_offset
>> 2) << 1];
480 else if (fp_offset
>= 4)
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 if (fetch_packet_header_based
486 && header
.word_compact
[(fp_offset
>> 2) - 1])
487 p_bit
= header
.p_bits
[(fp_offset
>> 1) - 1];
490 unsigned int prev_opcode
491 = tic6x_extract_32 (fp
+ (fp_offset
& 0x1c) - 4, info
);
492 p_bit
= (prev_opcode
& 0x1) != 0;
497 /* Find the last instruction of the previous fetch
499 unsigned char fp_prev
[32];
501 status
= info
->read_memory_func (fp_addr
- 32, fp_prev
, 32, info
);
503 /* No previous instruction to be parallel with. */
507 bool prev_header_based
;
508 tic6x_fetch_packet_header prev_header
;
511 = tic6x_check_fetch_packet_header (fp_prev
, &prev_header
, info
);
512 if (prev_header_based
)
514 if (prev_header
.word_compact
[6])
515 p_bit
= prev_header
.p_bits
[13];
518 unsigned int prev_opcode
= tic6x_extract_32 (fp_prev
+ 24,
520 p_bit
= (prev_opcode
& 0x1) != 0;
525 unsigned int prev_opcode
= tic6x_extract_32 (fp_prev
+ 28,
527 p_bit
= (prev_opcode
& 0x1) != 0;
531 parallel
= p_bit
? "|| " : "";
533 if (opc
->func_unit
== tic6x_func_unit_nfu
)
537 unsigned int fld_num
;
539 const char *data_str
;
540 bool have_areg
= false;
541 bool have_cross
= false;
543 func_unit_side
= (opc
->flags
& TIC6X_FLAG_SIDE_B_ONLY
) ? 2 : 0;
545 func_unit_data_side
= (opc
->flags
& TIC6X_FLAG_SIDE_T2_ONLY
) ? 2 : 0;
547 for (fld_num
= 0; fld_num
< opc
->num_variable_fields
; fld_num
++)
549 const tic6x_coding_field
*const enc
= &opc
->variable_fields
[fld_num
];
550 const tic6x_insn_field
*field
;
551 unsigned int fld_val
;
553 field
= tic6x_field_from_fmt (fmt
, enc
->field_id
);
557 printf ("opcode %x: could not retrieve field (field_id:%d)\n",
562 fld_val
= tic6x_field_bits (opcode
, field
);
564 switch (enc
->coding_method
)
566 case tic6x_coding_fu
:
567 /* The side must be specified exactly once. */
570 printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
574 func_unit_side
= (fld_val
? 2 : 1);
577 case tic6x_coding_data_fu
:
578 /* The data side must be specified exactly once. */
579 if (func_unit_data_side
)
581 printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
585 func_unit_data_side
= (fld_val
? 2 : 1);
588 case tic6x_coding_xpath
:
589 /* Cross path use must be specified exactly
593 printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n",
598 func_unit_cross
= fld_val
;
601 case tic6x_coding_rside
:
602 /* If the format has a t field, use it for src/dst register side. */
605 func_unit_data_side
= (t_val
? 2 : 1);
608 case tic6x_coding_areg
:
613 /* Don't relate to functional units. */
618 /* The side of the functional unit used must now have been
619 determined either from the flags or from an instruction
621 if (func_unit_side
!= 1 && func_unit_side
!= 2)
623 printf ("opcode %x: func_unit_side is not encoded!\n", opcode
);
627 /* Cross paths are not applicable when sides are specified
628 for both address and data paths. */
629 if (func_unit_data_side
&& have_cross
)
631 printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n",
636 /* Separate address and data paths are only applicable for
638 if (func_unit_data_side
&& opc
->func_unit
!= tic6x_func_unit_d
)
640 printf ("opcode %x: separate address and data paths only applicable for D unit!\n",
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 if (have_areg
&& !func_unit_data_side
)
653 printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode
);
656 func_unit_cross
= func_unit_side
== 1;
659 switch (opc
->func_unit
)
661 case tic6x_func_unit_d
:
662 func_unit_char
= 'D';
665 case tic6x_func_unit_l
:
666 func_unit_char
= 'L';
669 case tic6x_func_unit_m
:
670 func_unit_char
= 'M';
673 case tic6x_func_unit_s
:
674 func_unit_char
= 'S';
678 printf ("opcode %x: illegal func_unit specifier %d\n", opcode
, opc
->func_unit
);
682 switch (func_unit_data_side
)
697 printf ("opcode %x: illegal data func_unit specifier %d\n",
698 opcode
, func_unit_data_side
);
702 if (opc
->flags
& TIC6X_FLAG_INSN16_BSIDE
&& func_unit_side
== 1)
705 snprintf (func_unit_buf
, sizeof func_unit_buf
, " .%c%u%s%s",
706 func_unit_char
, func_unit_side
,
707 (func_unit_cross
? "X" : ""), data_str
);
708 func_unit
= func_unit_buf
;
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
715 num_operands
= opc
->num_operands
;
716 for (op_num
= 0; op_num
< num_operands
; op_num
++)
718 unsigned int fld_num
;
719 unsigned int mem_base_reg
= 0;
720 bool mem_base_reg_known
= false;
721 bool mem_base_reg_known_long
= false;
722 unsigned int mem_offset
= 0;
723 bool mem_offset_known
= false;
724 bool mem_offset_known_long
= false;
725 unsigned int mem_mode
= 0;
726 bool mem_mode_known
= false;
727 unsigned int mem_scaled
= 0;
728 bool mem_scaled_known
= false;
729 unsigned int crlo
= 0;
730 bool crlo_known
= false;
731 unsigned int crhi
= 0;
732 bool crhi_known
= false;
733 bool spmask_skip_operand
= false;
734 unsigned int fcyc_bits
= 0;
735 bool prev_sploop_found
= false;
737 switch (opc
->operand_info
[op_num
].form
)
739 case tic6x_operand_b15reg
:
740 /* Fully determined by the functional unit. */
741 operands_text
[op_num
] = true;
742 snprintf (operands
[op_num
], 24, "b15");
745 case tic6x_operand_zreg
:
746 /* Fully determined by the functional unit. */
747 operands_text
[op_num
] = true;
748 snprintf (operands
[op_num
], 24, "%c0",
749 (func_unit_side
== 2 ? 'b' : 'a'));
752 case tic6x_operand_retreg
:
753 /* Fully determined by the functional unit. */
754 operands_text
[op_num
] = true;
755 snprintf (operands
[op_num
], 24, "%c3",
756 (func_unit_side
== 2 ? 'b' : 'a'));
759 case tic6x_operand_irp
:
760 operands_text
[op_num
] = true;
761 snprintf (operands
[op_num
], 24, "irp");
764 case tic6x_operand_nrp
:
765 operands_text
[op_num
] = true;
766 snprintf (operands
[op_num
], 24, "nrp");
769 case tic6x_operand_ilc
:
770 operands_text
[op_num
] = true;
771 snprintf (operands
[op_num
], 24, "ilc");
774 case tic6x_operand_hw_const_minus_1
:
775 operands_text
[op_num
] = true;
776 snprintf (operands
[op_num
], 24, "-1");
779 case tic6x_operand_hw_const_0
:
780 operands_text
[op_num
] = true;
781 snprintf (operands
[op_num
], 24, "0");
784 case tic6x_operand_hw_const_1
:
785 operands_text
[op_num
] = true;
786 snprintf (operands
[op_num
], 24, "1");
789 case tic6x_operand_hw_const_5
:
790 operands_text
[op_num
] = true;
791 snprintf (operands
[op_num
], 24, "5");
794 case tic6x_operand_hw_const_16
:
795 operands_text
[op_num
] = true;
796 snprintf (operands
[op_num
], 24, "16");
799 case tic6x_operand_hw_const_24
:
800 operands_text
[op_num
] = true;
801 snprintf (operands
[op_num
], 24, "24");
804 case tic6x_operand_hw_const_31
:
805 operands_text
[op_num
] = true;
806 snprintf (operands
[op_num
], 24, "31");
813 for (fld_num
= 0; fld_num
< opc
->num_variable_fields
; fld_num
++)
815 const tic6x_coding_field
*const enc
816 = &opc
->variable_fields
[fld_num
];
817 const tic6x_insn_field
*field
;
818 unsigned int fld_val
;
819 unsigned int reg_base
= 0;
820 signed int signed_fld_val
;
823 if (enc
->operand_num
!= op_num
)
825 field
= tic6x_field_from_fmt (fmt
, enc
->field_id
);
828 printf ("opcode %x: missing field (field_id:%d) in format\n", opcode
, enc
->field_id
);
831 fld_val
= tic6x_field_bits (opcode
, field
);
832 switch (enc
->coding_method
)
834 case tic6x_coding_cst_s3i
:
835 (fld_val
== 0x00) && (fld_val
= 0x10);
836 (fld_val
== 0x07) && (fld_val
= 0x08);
838 case tic6x_coding_ucst
:
839 case tic6x_coding_ulcst_dpr_byte
:
840 case tic6x_coding_ulcst_dpr_half
:
841 case tic6x_coding_ulcst_dpr_word
:
842 case tic6x_coding_lcst_low16
:
843 switch (opc
->operand_info
[op_num
].form
)
845 case tic6x_operand_asm_const
:
846 case tic6x_operand_link_const
:
847 operands_text
[op_num
] = true;
848 snprintf (operands
[op_num
], 24, "%u", fld_val
);
851 case tic6x_operand_mem_long
:
852 mem_offset
= fld_val
;
853 mem_offset_known_long
= true;
857 printf ("opcode %x: illegal operand form for operand#%d\n", opcode
, op_num
);
862 case tic6x_coding_lcst_high16
:
863 operands_text
[op_num
] = true;
864 snprintf (operands
[op_num
], 24, "%u", fld_val
<< 16);
867 case tic6x_coding_scst_l3i
:
868 operands_text
[op_num
] = true;
875 signed_fld_val
= (signed int) fld_val
;
876 signed_fld_val
^= (1 << (tic6x_field_width (field
) - 1));
877 signed_fld_val
-= (1 << (tic6x_field_width (field
) - 1));
879 snprintf (operands
[op_num
], 24, "%d", signed_fld_val
);
882 case tic6x_coding_scst
:
883 operands_text
[op_num
] = true;
884 signed_fld_val
= (signed int) fld_val
;
885 signed_fld_val
^= (1 << (tic6x_field_width (field
) - 1));
886 signed_fld_val
-= (1 << (tic6x_field_width (field
) - 1));
887 snprintf (operands
[op_num
], 24, "%d", signed_fld_val
);
890 case tic6x_coding_ucst_minus_one
:
891 operands_text
[op_num
] = true;
892 snprintf (operands
[op_num
], 24, "%u", fld_val
+ 1);
895 case tic6x_coding_pcrel
:
896 case tic6x_coding_pcrel_half
:
897 signed_fld_val
= (signed int) fld_val
;
898 signed_fld_val
^= (1 << (tic6x_field_width (field
) - 1));
899 signed_fld_val
-= (1 << (tic6x_field_width (field
) - 1));
900 if (fetch_packet_header_based
901 && enc
->coding_method
== tic6x_coding_pcrel_half
)
905 operands_pcrel
[op_num
] = true;
906 operands_addresses
[op_num
] = fp_addr
+ signed_fld_val
;
909 case tic6x_coding_regpair_msb
:
910 if (opc
->operand_info
[op_num
].form
!= tic6x_operand_regpair
)
912 operands_text
[op_num
] = true;
913 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
914 (func_unit_side
== 2 ? 'b' : 'a'), (fld_val
| 0x1),
915 (func_unit_side
== 2 ? 'b' : 'a'), (fld_val
| 0x1) - 1);
918 case tic6x_coding_pcrel_half_unsigned
:
919 operands_pcrel
[op_num
] = true;
920 operands_addresses
[op_num
] = fp_addr
+ 2 * fld_val
;
923 case tic6x_coding_reg_shift
:
926 case tic6x_coding_reg
:
927 if (num_bits
== 16 && header
.rs
&& !(opc
->flags
& TIC6X_FLAG_INSN16_NORS
))
931 switch (opc
->operand_info
[op_num
].form
)
933 case tic6x_operand_treg
:
936 printf ("opcode %x: operand treg but missing t field\n", opcode
);
939 operands_text
[op_num
] = true;
940 reg_side
= t_val
? 'b' : 'a';
941 snprintf (operands
[op_num
], 24, "%c%u", reg_side
, reg_base
+ fld_val
);
944 case tic6x_operand_reg
:
945 operands_text
[op_num
] = true;
946 reg_side
= (func_unit_side
== 2) ? 'b' : 'a';
947 snprintf (operands
[op_num
], 24, "%c%u", reg_side
, reg_base
+ fld_val
);
950 case tic6x_operand_reg_nors
:
951 operands_text
[op_num
] = true;
952 reg_side
= (func_unit_side
== 2) ? 'b' : 'a';
953 snprintf (operands
[op_num
], 24, "%c%u", reg_side
, fld_val
);
956 case tic6x_operand_reg_bside
:
957 operands_text
[op_num
] = true;
958 snprintf (operands
[op_num
], 24, "b%u", reg_base
+ fld_val
);
961 case tic6x_operand_reg_bside_nors
:
962 operands_text
[op_num
] = true;
963 snprintf (operands
[op_num
], 24, "b%u", fld_val
);
966 case tic6x_operand_xreg
:
967 operands_text
[op_num
] = true;
968 reg_side
= ((func_unit_side
== 2) ^ func_unit_cross
) ? 'b' : 'a';
969 snprintf (operands
[op_num
], 24, "%c%u", reg_side
, reg_base
+ fld_val
);
972 case tic6x_operand_dreg
:
973 operands_text
[op_num
] = true;
974 reg_side
= (func_unit_data_side
== 2) ? 'b' : 'a';
975 snprintf (operands
[op_num
], 24, "%c%u", reg_side
, reg_base
+ fld_val
);
978 case tic6x_operand_regpair
:
979 operands_text
[op_num
] = true;
982 reg_side
= (func_unit_side
== 2) ? 'b' : 'a';
983 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
984 reg_side
, reg_base
+ fld_val
+ 1,
985 reg_side
, reg_base
+ fld_val
);
988 case tic6x_operand_xregpair
:
989 operands_text
[op_num
] = true;
992 reg_side
= ((func_unit_side
== 2) ^ func_unit_cross
) ? 'b' : 'a';
993 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
994 reg_side
, reg_base
+ fld_val
+ 1,
995 reg_side
, reg_base
+ fld_val
);
998 case tic6x_operand_tregpair
:
1001 printf ("opcode %x: operand tregpair but missing t field\n", opcode
);
1004 operands_text
[op_num
] = true;
1006 operands_ok
= false;
1007 reg_side
= t_val
? 'b' : 'a';
1008 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
1009 reg_side
, reg_base
+ fld_val
+ 1,
1010 reg_side
, reg_base
+ fld_val
);
1013 case tic6x_operand_dregpair
:
1014 operands_text
[op_num
] = true;
1016 operands_ok
= false;
1017 reg_side
= (func_unit_data_side
) == 2 ? 'b' : 'a';
1018 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
1019 reg_side
, reg_base
+ fld_val
+ 1,
1020 reg_side
, reg_base
+ fld_val
);
1023 case tic6x_operand_mem_deref
:
1024 operands_text
[op_num
] = true;
1025 reg_side
= func_unit_side
== 2 ? 'b' : 'a';
1026 snprintf (operands
[op_num
], 24, "*%c%u", reg_side
, reg_base
+ fld_val
);
1029 case tic6x_operand_mem_short
:
1030 case tic6x_operand_mem_ndw
:
1031 mem_base_reg
= fld_val
;
1032 mem_base_reg_known
= true;
1036 printf ("opcode %x: unexpected operand form %d for operand #%d",
1037 opcode
, opc
->operand_info
[op_num
].form
, op_num
);
1042 case tic6x_coding_reg_ptr
:
1043 switch (opc
->operand_info
[op_num
].form
)
1045 case tic6x_operand_mem_short
:
1046 case tic6x_operand_mem_ndw
:
1049 printf("opcode %x: illegal field value for ptr register of operand #%d (%d)",
1050 opcode
, op_num
, fld_val
);
1053 mem_base_reg
= 0x4 | fld_val
;
1054 mem_base_reg_known
= true;
1058 printf ("opcode %x: unexpected operand form %d for operand #%d",
1059 opcode
, opc
->operand_info
[op_num
].form
, op_num
);
1064 case tic6x_coding_areg
:
1065 switch (opc
->operand_info
[op_num
].form
)
1067 case tic6x_operand_areg
:
1068 operands_text
[op_num
] = true;
1069 snprintf (operands
[op_num
], 24, "b%u",
1070 fld_val
? 15u : 14u);
1073 case tic6x_operand_mem_long
:
1074 mem_base_reg
= fld_val
? 15u : 14u;
1075 mem_base_reg_known_long
= true;
1079 printf ("opcode %x: bad operand form\n", opcode
);
1084 case tic6x_coding_mem_offset_minus_one_noscale
:
1085 case tic6x_coding_mem_offset_minus_one
:
1088 case tic6x_coding_mem_offset_noscale
:
1089 case tic6x_coding_mem_offset
:
1090 mem_offset
= fld_val
;
1091 mem_offset_known
= true;
1094 mem_mode_known
= true;
1095 mem_mode
= TIC6X_INSN16_MEM_MODE_VAL (opc
->flags
);
1096 mem_scaled_known
= true;
1098 if (opc
->flags
& TIC6X_FLAG_INSN16_B15PTR
)
1100 mem_base_reg_known
= true;
1103 if ( enc
->coding_method
== tic6x_coding_mem_offset_noscale
1104 || enc
->coding_method
== tic6x_coding_mem_offset_noscale
)
1109 case tic6x_coding_mem_mode
:
1111 mem_mode_known
= true;
1114 case tic6x_coding_scaled
:
1115 mem_scaled
= fld_val
;
1116 mem_scaled_known
= true;
1119 case tic6x_coding_crlo
:
1124 case tic6x_coding_crhi
:
1129 case tic6x_coding_fstg
:
1130 case tic6x_coding_fcyc
:
1131 if (!prev_sploop_found
)
1133 bfd_vma search_fp_addr
= fp_addr
;
1134 bfd_vma search_fp_offset
= fp_offset
;
1135 bool search_fp_header_based
1136 = fetch_packet_header_based
;
1137 tic6x_fetch_packet_header search_fp_header
= header
;
1138 unsigned char search_fp
[32];
1139 unsigned int search_num_bits
;
1140 unsigned int search_opcode
;
1141 unsigned int sploop_ii
= 0;
1144 memcpy (search_fp
, fp
, 32);
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 for (i
= 0; i
< 48 * 8; i
++)
1152 /* Find the previous instruction. */
1153 if (search_fp_offset
& 2)
1154 search_fp_offset
-= 2;
1155 else if (search_fp_offset
>= 4)
1157 if (search_fp_header_based
1158 && (search_fp_header
.word_compact
1159 [(search_fp_offset
>> 2) - 1]))
1160 search_fp_offset
-= 2;
1162 search_fp_offset
-= 4;
1166 search_fp_addr
-= 32;
1167 status
= info
->read_memory_func (search_fp_addr
,
1171 /* No previous SPLOOP instruction. */
1173 search_fp_header_based
1174 = (tic6x_check_fetch_packet_header
1175 (search_fp
, &search_fp_header
, info
));
1176 if (search_fp_header_based
)
1178 = search_fp_header
.word_compact
[6] ? 26 : 24;
1180 search_fp_offset
= 28;
1183 /* Extract the previous instruction. */
1184 if (search_fp_header_based
)
1186 = (search_fp_header
.word_compact
[search_fp_offset
1191 search_num_bits
= 32;
1192 if (search_num_bits
== 16)
1194 if (info
->endian
== BFD_ENDIAN_LITTLE
)
1197 (search_fp
+ search_fp_offset
, &header
, info
));
1201 (search_fp
+ (search_fp_offset
^ 2), &header
,
1206 = tic6x_extract_32 (search_fp
+ search_fp_offset
,
1209 /* Check whether it is an SPLOOP-family
1211 if (search_num_bits
== 32
1212 && ((search_opcode
& 0x003ffffe) == 0x00038000
1213 || (search_opcode
& 0x003ffffe) == 0x0003a000
1214 || ((search_opcode
& 0x003ffffe)
1217 prev_sploop_found
= true;
1218 sploop_ii
= ((search_opcode
>> 23) & 0x1f) + 1;
1220 else if (search_num_bits
== 16
1221 && (search_opcode
& 0x3c7e) == 0x0c66)
1223 prev_sploop_found
= true;
1225 = (((search_opcode
>> 7) & 0x7)
1226 | ((search_opcode
>> 11) & 0x8)) + 1;
1228 if (prev_sploop_found
)
1232 printf ("opcode %x: sloop index not found (%d)\n", opcode
, sploop_ii
);
1235 else if (sploop_ii
<= 1)
1237 else if (sploop_ii
<= 2)
1239 else if (sploop_ii
<= 4)
1241 else if (sploop_ii
<= 8)
1243 else if (sploop_ii
<= 14)
1246 prev_sploop_found
= false;
1248 if (prev_sploop_found
)
1252 if (!prev_sploop_found
)
1254 operands_ok
= false;
1255 operands_text
[op_num
] = true;
1258 if (fcyc_bits
> tic6x_field_width(field
))
1260 printf ("opcode %x: illegal fcyc value (%d)\n", opcode
, fcyc_bits
);
1263 if (enc
->coding_method
== tic6x_coding_fstg
)
1266 for (t
= 0, i
= fcyc_bits
; i
< 6; i
++)
1267 t
= (t
<< 1) | ((fld_val
>> i
) & 1);
1268 operands_text
[op_num
] = true;
1269 snprintf (operands
[op_num
], 24, "%u", t
);
1273 operands_text
[op_num
] = true;
1274 snprintf (operands
[op_num
], 24, "%u",
1275 fld_val
& ((1 << fcyc_bits
) - 1));
1279 case tic6x_coding_spmask
:
1281 spmask_skip_operand
= true;
1287 operands_text
[op_num
] = true;
1288 p
= operands
[op_num
];
1289 for (i
= 0; i
< 8; i
++)
1290 if (fld_val
& (1 << i
))
1293 *p
++ = '1' + (i
& 1);
1300 case tic6x_coding_fu
:
1301 case tic6x_coding_data_fu
:
1302 case tic6x_coding_xpath
:
1303 case tic6x_coding_rside
:
1304 /* Don't relate to operands, so operand number is
1309 printf ("opcode %x: illegal field encoding (%d)\n", opcode
, enc
->coding_method
);
1313 if (mem_base_reg_known_long
&& mem_offset_known_long
)
1315 if (operands_text
[op_num
] || operands_pcrel
[op_num
])
1317 printf ("opcode %x: long access but operands already known ?\n", opcode
);
1320 operands_text
[op_num
] = true;
1321 snprintf (operands
[op_num
], 24, "*+b%u(%u)", mem_base_reg
,
1322 mem_offset
* opc
->operand_info
[op_num
].size
);
1325 if (mem_base_reg_known
&& mem_offset_known
&& mem_mode_known
1326 && (mem_scaled_known
1327 || (opc
->operand_info
[op_num
].form
1328 != tic6x_operand_mem_ndw
)))
1337 if (operands_text
[op_num
] || operands_pcrel
[op_num
])
1339 printf ("opcode %x: mem access operands already known ?\n", opcode
);
1343 side
= func_unit_side
== 2 ? 'b' : 'a';
1344 snprintf (base
, 4, "%c%u", side
, mem_base_reg
);
1346 offset_is_reg
= (mem_mode
& 4) != 0;
1350 if (num_bits
== 16 && header
.rs
&& !(opc
->flags
& TIC6X_FLAG_INSN16_NORS
))
1354 snprintf (offset
, 4, "%c%u", side
, reg_base
+ mem_offset
);
1355 if (opc
->operand_info
[op_num
].form
1356 == tic6x_operand_mem_ndw
)
1357 offset_scaled
= mem_scaled
!= 0;
1359 offset_scaled
= true;
1363 if (opc
->operand_info
[op_num
].form
1364 == tic6x_operand_mem_ndw
)
1366 offset_scaled
= mem_scaled
!= 0;
1367 snprintf (offset
, 4, "%u", mem_offset
);
1371 offset_scaled
= false;
1372 snprintf (offset
, 4, "%u",
1374 * opc
->operand_info
[op_num
].size
));
1379 snprintf (offsetp
, 6, "[%s]", offset
);
1381 snprintf (offsetp
, 6, "(%s)", offset
);
1383 operands_text
[op_num
] = true;
1384 switch (mem_mode
& ~4u)
1387 snprintf (operands
[op_num
], 24, "*-%s%s", base
, offsetp
);
1391 snprintf (operands
[op_num
], 24, "*+%s%s", base
, offsetp
);
1396 operands_ok
= false;
1400 snprintf (operands
[op_num
], 24, "*--%s%s", base
,
1405 snprintf (operands
[op_num
], 24, "*++%s%s", base
,
1410 snprintf (operands
[op_num
], 24, "*%s--%s", base
,
1415 snprintf (operands
[op_num
], 24, "*%s++%s", base
,
1420 printf ("*** unknown mem_mode : %d \n", mem_mode
);
1425 if (crlo_known
&& crhi_known
)
1430 if (operands_text
[op_num
] || operands_pcrel
[op_num
])
1432 printf ("*** abort crlo crli\n");
1436 rw
= opc
->operand_info
[op_num
].rw
;
1437 if (rw
!= tic6x_rw_read
1438 && rw
!= tic6x_rw_write
)
1440 printf ("*** abort rw : %d\n", rw
);
1444 for (crid
= 0; crid
< tic6x_ctrl_max
; crid
++)
1446 if (crlo
== tic6x_ctrl_table
[crid
].crlo
1447 && (crhi
& tic6x_ctrl_table
[crid
].crhi_mask
) == 0
1448 && (rw
== tic6x_rw_read
1449 ? (tic6x_ctrl_table
[crid
].rw
== tic6x_rw_read
1450 || (tic6x_ctrl_table
[crid
].rw
1451 == tic6x_rw_read_write
))
1452 : (tic6x_ctrl_table
[crid
].rw
== tic6x_rw_write
1453 || (tic6x_ctrl_table
[crid
].rw
1454 == tic6x_rw_read_write
))))
1457 if (crid
== tic6x_ctrl_max
)
1459 operands_text
[op_num
] = true;
1460 operands_ok
= false;
1464 operands_text
[op_num
] = true;
1465 snprintf (operands
[op_num
], 24, "%s",
1466 tic6x_ctrl_table
[crid
].name
);
1470 if (operands_text
[op_num
] || operands_pcrel
[op_num
]
1471 || spmask_skip_operand
)
1474 /* end for fld_num */
1476 if (spmask_skip_operand
)
1478 /* SPMASK operands are only valid as the single operand
1479 in the opcode table. */
1480 if (num_operands
!= 1)
1482 printf ("opcode: %x, num_operands != 1 : %d\n", opcode
, num_operands
);
1489 /* The operand must by now have been decoded. */
1490 if (!operands_text
[op_num
] && !operands_pcrel
[op_num
])
1492 printf ("opcode: %x, operand #%d not decoded\n", opcode
, op_num
);
1496 /* end for op_num */
1501 info
->bytes_per_chunk
= num_bits
/ 8;
1502 info
->fprintf_func (info
->stream
, "%s", parallel
);
1503 info
->fprintf_func (info
->stream
, "%s%s%s", cond
, opc
->name
,
1505 for (op_num
= 0; op_num
< num_operands
; op_num
++)
1507 info
->fprintf_func (info
->stream
, "%c", (op_num
== 0 ? ' ' : ','));
1508 if (operands_pcrel
[op_num
])
1509 info
->print_address_func (operands_addresses
[op_num
], info
);
1511 info
->fprintf_func (info
->stream
, "%s", operands
[op_num
]);
1513 if (fetch_packet_header_based
&& header
.prot
)
1514 info
->fprintf_func (info
->stream
, " || nop 5");
1516 return num_bits
/ 8;
1519 info
->bytes_per_chunk
= num_bits
/ 8;
1520 info
->fprintf_func (info
->stream
, "<undefined instruction 0x%.*x>",
1521 (int) num_bits
/ 4, opcode
);
1522 return num_bits
/ 8;