1 /* TI C6X disassembler.
2 Copyright 2010-2013 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. */
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 INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
58 CONCAT2(tic6x_func_unit_,func_unit), \
59 CONCAT4(tic6x_insn_format_,func_unit,_,format), \
60 CONCAT2(tic6x_pipeline_,type), \
61 CONCAT2(TIC6X_INSN_,isa), \
67 #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
70 CONCAT2(tic6x_func_unit_,func_unit), \
71 CONCAT4(tic6x_insn_format_,func_unit,_,format), \
72 CONCAT2(tic6x_pipeline_,type), \
73 CONCAT2(TIC6X_INSN_,isa), \
79 #include "opcode/tic6x-opcode-table.h"
84 /* If instruction format FMT has a field FIELD, return a pointer to
85 the description of that field; otherwise return NULL. */
87 const tic6x_insn_field
*
88 tic6x_field_from_fmt (const tic6x_insn_format
*fmt
, tic6x_insn_field_id field
)
92 for (f
= 0; f
< fmt
->num_fields
; f
++)
93 if (fmt
->fields
[f
].field_id
== field
)
94 return &fmt
->fields
[f
];
99 /* Extract the bits corresponding to FIELD from OPCODE. */
102 tic6x_field_bits (unsigned int opcode
, const tic6x_insn_field
*field
)
104 return (opcode
>> field
->low_pos
) & ((1u << field
->width
) - 1);
107 /* Extract a 32-bit value read from the instruction stream. */
110 tic6x_extract_32 (unsigned char *p
, struct disassemble_info
*info
)
112 if (info
->endian
== BFD_ENDIAN_LITTLE
)
113 return (p
[0]) | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
115 return (p
[3]) | (p
[2] << 8) | (p
[1] << 16) | (p
[0] << 24);
118 /* Extract a 16-bit value read from the instruction stream. */
121 tic6x_extract_16 (unsigned char *p
, struct disassemble_info
*info
)
123 if (info
->endian
== BFD_ENDIAN_LITTLE
)
124 return (p
[0]) | (p
[1] << 8);
126 return (p
[1]) | (p
[0] << 8);
129 /* FP points to a fetch packet. Return whether it is header-based; if
130 it is, fill in HEADER. */
133 tic6x_check_fetch_packet_header (unsigned char *fp
,
134 tic6x_fetch_packet_header
*header
,
135 struct disassemble_info
*info
)
139 header
->header
= tic6x_extract_32 (fp
+ 28, info
);
140 if ((header
->header
& 0xf0000000) != 0xe0000000)
143 for (i
= 0; i
< 7; i
++)
144 header
->word_compact
[i
]
145 = (header
->header
& (1u << (21 + i
))) ? TRUE
: FALSE
;
147 header
->prot
= (header
->header
& (1u << 20)) ? TRUE
: FALSE
;
148 header
->rs
= (header
->header
& (1u << 19)) ? TRUE
: FALSE
;
149 header
->dsz
= (header
->header
>> 16) & 0x7;
150 header
->br
= (header
->header
& (1u << 15)) ? TRUE
: FALSE
;
151 header
->sat
= (header
->header
& (1u << 14)) ? TRUE
: FALSE
;
153 for (i
= 0; i
< 14; i
++)
155 = (header
->header
& (1u << i
)) ? TRUE
: FALSE
;
160 /* Disassemble the instruction at ADDR and print it using
161 INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
165 print_insn_tic6x (bfd_vma addr
, struct disassemble_info
*info
)
170 unsigned char fp
[32];
172 tic6x_opcode_id opcode_id
;
173 bfd_boolean fetch_packet_header_based
;
174 tic6x_fetch_packet_header header
;
175 unsigned int num_bits
;
176 bfd_boolean bad_offset
= FALSE
;
178 fp_offset
= addr
& 0x1f;
179 fp_addr
= addr
- fp_offset
;
180 status
= info
->read_memory_func (fp_addr
, fp
, 32, info
);
183 info
->memory_error_func (status
, addr
, info
);
187 fetch_packet_header_based
188 = tic6x_check_fetch_packet_header (fp
, &header
, info
);
189 if (fetch_packet_header_based
)
193 if ((fp_offset
& 0x3) && (fp_offset
>= 28
194 || !header
.word_compact
[fp_offset
>> 2]))
198 info
->bytes_per_chunk
= 4;
199 info
->fprintf_func (info
->stream
, "<fetch packet header 0x%.8x>",
203 num_bits
= (header
.word_compact
[fp_offset
>> 2] ? 16 : 32);
214 info
->bytes_per_chunk
= 1;
215 info
->fprintf_func (info
->stream
, ".byte 0x%.2x", fp
[fp_offset
]);
221 /* The least-significant part of a 32-bit word comes logically
222 before the most-significant part. For big-endian, follow the
223 TI assembler in showing instructions in logical order by
224 pretending that the two halves of the word are in opposite
225 locations to where they actually are. */
226 if (info
->endian
== BFD_ENDIAN_LITTLE
)
227 opcode
= tic6x_extract_16 (fp
+ fp_offset
, info
);
229 opcode
= tic6x_extract_16 (fp
+ (fp_offset
^ 2), info
);
232 opcode
= tic6x_extract_32 (fp
+ fp_offset
, info
);
234 for (opcode_id
= 0; opcode_id
< tic6x_opcode_max
; opcode_id
++)
236 const tic6x_opcode
*const opc
= &tic6x_opcode_table
[opcode_id
];
237 const tic6x_insn_format
*const fmt
238 = &tic6x_insn_format_table
[opc
->format
];
239 const tic6x_insn_field
*creg_field
;
241 const char *parallel
;
242 const char *cond
= "";
243 const char *func_unit
;
244 char func_unit_buf
[7];
245 unsigned int func_unit_side
= 0;
246 unsigned int func_unit_data_side
= 0;
247 unsigned int func_unit_cross
= 0;
248 /* The maximum length of the text of a non-PC-relative operand
249 is 24 bytes (SPMASK masking all eight functional units, with
250 separating commas and trailing NUL). */
251 char operands
[TIC6X_MAX_OPERANDS
][24] = { { 0 } };
252 bfd_vma operands_addresses
[TIC6X_MAX_OPERANDS
] = { 0 };
253 bfd_boolean operands_text
[TIC6X_MAX_OPERANDS
] = { FALSE
};
254 bfd_boolean operands_pcrel
[TIC6X_MAX_OPERANDS
] = { FALSE
};
256 unsigned int num_operands
;
258 bfd_boolean fixed_ok
;
259 bfd_boolean operands_ok
;
261 if (opc
->flags
& TIC6X_FLAG_MACRO
)
263 if (fmt
->num_bits
!= num_bits
)
265 if ((opcode
& fmt
->mask
) != fmt
->cst_bits
)
268 /* If the format has a creg field, it is only a candidate for a
269 match if the creg and z fields have values indicating a valid
270 condition; reserved values indicate either an instruction
271 format without a creg field, or an invalid instruction. */
272 creg_field
= tic6x_field_from_fmt (fmt
, tic6x_field_creg
);
275 const tic6x_insn_field
*z_field
;
276 unsigned int creg_value
, z_value
;
277 static const char *const conds
[8][2] =
280 { "[b0] ", "[!b0] " },
281 { "[b1] ", "[!b1] " },
282 { "[b2] ", "[!b2] " },
283 { "[a1] ", "[!a1] " },
284 { "[a2] ", "[!a2] " },
285 { "[a0] ", "[!a0] " },
289 /* A creg field is not meaningful without a z field, so if
290 the z field is not present this is an error in the format
292 z_field
= tic6x_field_from_fmt (fmt
, tic6x_field_z
);
296 creg_value
= tic6x_field_bits (opcode
, creg_field
);
297 z_value
= tic6x_field_bits (opcode
, z_field
);
298 cond
= conds
[creg_value
][z_value
];
303 /* All fixed fields must have matching values; all fields with
304 restricted ranges must have values within those ranges. */
306 for (fix
= 0; fix
< opc
->num_fixed_fields
; fix
++)
308 unsigned int field_bits
;
309 const tic6x_insn_field
*const field
310 = tic6x_field_from_fmt (fmt
, opc
->fixed_fields
[fix
].field_id
);
314 field_bits
= tic6x_field_bits (opcode
, field
);
315 if (field_bits
< opc
->fixed_fields
[fix
].min_val
316 || field_bits
> opc
->fixed_fields
[fix
].max_val
)
325 /* The instruction matches. */
327 /* The p-bit indicates whether this instruction is in parallel
328 with the *next* instruction, whereas the parallel bars
329 indicate the instruction is in parallel with the *previous*
330 instruction. Thus, we must find the p-bit for the previous
332 if (num_bits
== 16 && (fp_offset
& 0x2) == 2)
334 /* This is the logically second (most significant; second in
335 fp_offset terms because fp_offset relates to logical not
336 physical addresses) instruction of a compact pair; find
337 the p-bit for the first (least significant). */
338 p_bit
= header
.p_bits
[(fp_offset
>> 2) << 1];
340 else if (fp_offset
>= 4)
342 /* Find the last instruction of the previous word in this
343 fetch packet. For compact instructions, this is the most
344 significant 16 bits. */
345 if (fetch_packet_header_based
346 && header
.word_compact
[(fp_offset
>> 2) - 1])
347 p_bit
= header
.p_bits
[(fp_offset
>> 1) - 1];
350 unsigned int prev_opcode
351 = tic6x_extract_32 (fp
+ (fp_offset
& 0x1c) - 4, info
);
352 p_bit
= (prev_opcode
& 0x1) ? TRUE
: FALSE
;
357 /* Find the last instruction of the previous fetch
359 unsigned char fp_prev
[32];
360 status
= info
->read_memory_func (fp_addr
- 32, fp_prev
, 32, info
);
362 /* No previous instruction to be parallel with. */
366 bfd_boolean prev_header_based
;
367 tic6x_fetch_packet_header prev_header
;
370 = tic6x_check_fetch_packet_header (fp_prev
, &prev_header
, info
);
371 if (prev_header_based
&& prev_header
.word_compact
[6])
372 p_bit
= prev_header
.p_bits
[13];
375 unsigned int prev_opcode
= tic6x_extract_32 (fp_prev
+ 28,
377 p_bit
= (prev_opcode
& 0x1) ? TRUE
: FALSE
;
381 parallel
= p_bit
? "|| " : "";
383 if (opc
->func_unit
== tic6x_func_unit_nfu
)
387 unsigned int fld_num
;
389 const char *data_str
;
390 bfd_boolean have_areg
= FALSE
;
391 bfd_boolean have_cross
= FALSE
;
393 func_unit_side
= (opc
->flags
& TIC6X_FLAG_SIDE_B_ONLY
) ? 2 : 0;
395 func_unit_data_side
= (opc
->flags
& TIC6X_FLAG_SIDE_T2_ONLY
) ? 2 : 0;
397 for (fld_num
= 0; fld_num
< opc
->num_variable_fields
; fld_num
++)
399 const tic6x_coding_field
*const enc
= &opc
->variable_fields
[fld_num
];
400 const tic6x_insn_field
*field
;
401 unsigned int fld_val
;
403 field
= tic6x_field_from_fmt (fmt
, enc
->field_id
);
406 fld_val
= tic6x_field_bits (opcode
, field
);
407 switch (enc
->coding_method
)
409 case tic6x_coding_fu
:
410 /* The side must be specified exactly once. */
413 func_unit_side
= (fld_val
? 2 : 1);
416 case tic6x_coding_data_fu
:
417 /* The data side must be specified exactly once. */
418 if (func_unit_data_side
)
420 func_unit_data_side
= (fld_val
? 2 : 1);
423 case tic6x_coding_xpath
:
424 /* Cross path use must be specified exactly
429 func_unit_cross
= fld_val
;
432 case tic6x_coding_areg
:
437 /* Don't relate to functional units. */
442 /* The side of the functional unit used must now have been
443 determined either from the flags or from an instruction
445 if (func_unit_side
!= 1 && func_unit_side
!= 2)
448 /* Cross paths are not applicable when sides are specified
449 for both address and data paths. */
450 if (func_unit_data_side
&& have_cross
)
453 /* Separate address and data paths are only applicable for
455 if (func_unit_data_side
&& opc
->func_unit
!= tic6x_func_unit_d
)
458 /* If an address register is being used but in ADDA rather
459 than a load or store, it uses a cross path for side-A
460 instructions, and the cross path use is not specified by
461 an instruction field. */
462 if (have_areg
&& !func_unit_data_side
)
466 func_unit_cross
= (func_unit_side
== 1 ? TRUE
: FALSE
);
469 switch (opc
->func_unit
)
471 case tic6x_func_unit_d
:
472 func_unit_char
= 'D';
475 case tic6x_func_unit_l
:
476 func_unit_char
= 'L';
479 case tic6x_func_unit_m
:
480 func_unit_char
= 'M';
483 case tic6x_func_unit_s
:
484 func_unit_char
= 'S';
491 switch (func_unit_data_side
)
509 snprintf (func_unit_buf
, 7, " .%c%u%s%s", func_unit_char
,
510 func_unit_side
, (func_unit_cross
? "X" : ""), data_str
);
511 func_unit
= func_unit_buf
;
514 /* For each operand there must be one or more fields set based
515 on that operand, that can together be used to derive the
518 num_operands
= opc
->num_operands
;
519 for (op_num
= 0; op_num
< num_operands
; op_num
++)
521 unsigned int fld_num
;
522 unsigned int mem_base_reg
= 0;
523 bfd_boolean mem_base_reg_known
= FALSE
;
524 bfd_boolean mem_base_reg_known_long
= FALSE
;
525 unsigned int mem_offset
= 0;
526 bfd_boolean mem_offset_known
= FALSE
;
527 bfd_boolean mem_offset_known_long
= FALSE
;
528 unsigned int mem_mode
= 0;
529 bfd_boolean mem_mode_known
= FALSE
;
530 unsigned int mem_scaled
= 0;
531 bfd_boolean mem_scaled_known
= FALSE
;
532 unsigned int crlo
= 0;
533 bfd_boolean crlo_known
= FALSE
;
534 unsigned int crhi
= 0;
535 bfd_boolean crhi_known
= FALSE
;
536 bfd_boolean spmask_skip_operand
= FALSE
;
537 unsigned int fcyc_bits
= 0;
538 bfd_boolean prev_sploop_found
= FALSE
;
540 switch (opc
->operand_info
[op_num
].form
)
542 case tic6x_operand_retreg
:
543 /* Fully determined by the functional unit. */
544 operands_text
[op_num
] = TRUE
;
545 snprintf (operands
[op_num
], 24, "%c3",
546 (func_unit_side
== 2 ? 'b' : 'a'));
549 case tic6x_operand_irp
:
550 operands_text
[op_num
] = TRUE
;
551 snprintf (operands
[op_num
], 24, "irp");
554 case tic6x_operand_nrp
:
555 operands_text
[op_num
] = TRUE
;
556 snprintf (operands
[op_num
], 24, "nrp");
563 for (fld_num
= 0; fld_num
< opc
->num_variable_fields
; fld_num
++)
565 const tic6x_coding_field
*const enc
566 = &opc
->variable_fields
[fld_num
];
567 const tic6x_insn_field
*field
;
568 unsigned int fld_val
;
569 signed int signed_fld_val
;
571 if (enc
->operand_num
!= op_num
)
573 field
= tic6x_field_from_fmt (fmt
, enc
->field_id
);
576 fld_val
= tic6x_field_bits (opcode
, field
);
577 switch (enc
->coding_method
)
579 case tic6x_coding_ucst
:
580 case tic6x_coding_ulcst_dpr_byte
:
581 case tic6x_coding_ulcst_dpr_half
:
582 case tic6x_coding_ulcst_dpr_word
:
583 case tic6x_coding_lcst_low16
:
584 switch (opc
->operand_info
[op_num
].form
)
586 case tic6x_operand_asm_const
:
587 case tic6x_operand_link_const
:
588 operands_text
[op_num
] = TRUE
;
589 snprintf (operands
[op_num
], 24, "%u", fld_val
);
592 case tic6x_operand_mem_long
:
593 mem_offset
= fld_val
;
594 mem_offset_known_long
= TRUE
;
602 case tic6x_coding_lcst_high16
:
603 operands_text
[op_num
] = TRUE
;
604 snprintf (operands
[op_num
], 24, "%u", fld_val
<< 16);
607 case tic6x_coding_scst
:
608 operands_text
[op_num
] = TRUE
;
609 signed_fld_val
= (signed int) fld_val
;
610 signed_fld_val
^= (1 << (field
->width
- 1));
611 signed_fld_val
-= (1 << (field
->width
- 1));
612 snprintf (operands
[op_num
], 24, "%d", signed_fld_val
);
615 case tic6x_coding_ucst_minus_one
:
616 operands_text
[op_num
] = TRUE
;
617 snprintf (operands
[op_num
], 24, "%u", fld_val
+ 1);
620 case tic6x_coding_pcrel
:
621 case tic6x_coding_pcrel_half
:
622 signed_fld_val
= (signed int) fld_val
;
623 signed_fld_val
^= (1 << (field
->width
- 1));
624 signed_fld_val
-= (1 << (field
->width
- 1));
625 if (fetch_packet_header_based
626 && enc
->coding_method
== tic6x_coding_pcrel_half
)
630 operands_pcrel
[op_num
] = TRUE
;
631 operands_addresses
[op_num
] = fp_addr
+ signed_fld_val
;
634 case tic6x_coding_regpair_msb
:
635 if (opc
->operand_info
[op_num
].form
!= tic6x_operand_regpair
)
637 operands_text
[op_num
] = TRUE
;
638 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
639 (func_unit_side
== 2 ? 'b' : 'a'), (fld_val
| 0x1),
640 (func_unit_side
== 2 ? 'b' : 'a'), (fld_val
| 0x1) - 1);
643 case tic6x_coding_reg_shift
:
646 case tic6x_coding_reg
:
647 switch (opc
->operand_info
[op_num
].form
)
649 case tic6x_operand_reg
:
650 operands_text
[op_num
] = TRUE
;
651 snprintf (operands
[op_num
], 24, "%c%u",
652 (func_unit_side
== 2 ? 'b' : 'a'), fld_val
);
655 case tic6x_operand_xreg
:
656 operands_text
[op_num
] = TRUE
;
657 snprintf (operands
[op_num
], 24, "%c%u",
658 (((func_unit_side
== 2) ^ func_unit_cross
)
663 case tic6x_operand_dreg
:
664 operands_text
[op_num
] = TRUE
;
665 snprintf (operands
[op_num
], 24, "%c%u",
666 (func_unit_data_side
== 2 ? 'b' : 'a'),
670 case tic6x_operand_regpair
:
671 operands_text
[op_num
] = TRUE
;
674 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
675 (func_unit_side
== 2 ? 'b' : 'a'), fld_val
+ 1,
676 (func_unit_side
== 2 ? 'b' : 'a'), fld_val
);
679 case tic6x_operand_xregpair
:
680 operands_text
[op_num
] = TRUE
;
683 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
684 (((func_unit_side
== 2) ^ func_unit_cross
)
687 (((func_unit_side
== 2) ^ func_unit_cross
)
692 case tic6x_operand_dregpair
:
693 operands_text
[op_num
] = TRUE
;
696 snprintf (operands
[op_num
], 24, "%c%u:%c%u",
697 (func_unit_data_side
== 2 ? 'b' : 'a'),
699 (func_unit_data_side
== 2 ? 'b' : 'a'),
703 case tic6x_operand_mem_deref
:
704 operands_text
[op_num
] = TRUE
;
705 snprintf (operands
[op_num
], 24, "*%c%u",
706 (func_unit_side
== 2 ? 'b' : 'a'), fld_val
);
709 case tic6x_operand_mem_short
:
710 case tic6x_operand_mem_ndw
:
711 mem_base_reg
= fld_val
;
712 mem_base_reg_known
= TRUE
;
720 case tic6x_coding_areg
:
721 switch (opc
->operand_info
[op_num
].form
)
723 case tic6x_operand_areg
:
724 operands_text
[op_num
] = TRUE
;
725 snprintf (operands
[op_num
], 24, "b%u",
726 fld_val
? 15u : 14u);
729 case tic6x_operand_mem_long
:
730 mem_base_reg
= fld_val
? 15u : 14u;
731 mem_base_reg_known_long
= TRUE
;
739 case tic6x_coding_mem_offset
:
740 case tic6x_coding_mem_offset_noscale
:
741 mem_offset
= fld_val
;
742 mem_offset_known
= TRUE
;
745 case tic6x_coding_mem_mode
:
747 mem_mode_known
= TRUE
;
750 case tic6x_coding_scaled
:
751 mem_scaled
= fld_val
;
752 mem_scaled_known
= TRUE
;
755 case tic6x_coding_crlo
:
760 case tic6x_coding_crhi
:
765 case tic6x_coding_fstg
:
766 case tic6x_coding_fcyc
:
767 if (!prev_sploop_found
)
769 bfd_vma search_fp_addr
= fp_addr
;
770 bfd_vma search_fp_offset
= fp_offset
;
771 bfd_boolean search_fp_header_based
772 = fetch_packet_header_based
;
773 tic6x_fetch_packet_header search_fp_header
= header
;
774 unsigned char search_fp
[32];
775 unsigned int search_num_bits
;
776 unsigned int search_opcode
;
777 unsigned int sploop_ii
= 0;
780 memcpy (search_fp
, fp
, 32);
782 /* To interpret these bits in an SPKERNEL
783 instruction, we must find the previous
784 SPLOOP-family instruction. It may come up to
785 48 execute packets earlier. */
786 for (i
= 0; i
< 48 * 8; i
++)
788 /* Find the previous instruction. */
789 if (search_fp_offset
& 2)
790 search_fp_offset
-= 2;
791 else if (search_fp_offset
>= 4)
793 if (search_fp_header_based
794 && (search_fp_header
.word_compact
795 [(search_fp_offset
>> 2) - 1]))
796 search_fp_offset
-= 2;
798 search_fp_offset
-= 4;
802 search_fp_addr
-= 32;
803 status
= info
->read_memory_func (search_fp_addr
,
807 /* No previous SPLOOP instruction. */
809 search_fp_header_based
810 = (tic6x_check_fetch_packet_header
811 (search_fp
, &search_fp_header
, info
));
812 if (search_fp_header_based
)
814 = search_fp_header
.word_compact
[6] ? 26 : 24;
816 search_fp_offset
= 28;
819 /* Extract the previous instruction. */
820 if (search_fp_header_based
)
822 = (search_fp_header
.word_compact
[search_fp_offset
827 search_num_bits
= 32;
828 if (search_num_bits
== 16)
830 if (info
->endian
== BFD_ENDIAN_LITTLE
)
833 (search_fp
+ search_fp_offset
, info
));
837 (search_fp
+ (search_fp_offset
^ 2),
842 = tic6x_extract_32 (search_fp
+ search_fp_offset
,
845 /* Check whether it is an SPLOOP-family
847 if (search_num_bits
== 32
848 && ((search_opcode
& 0x003ffffe) == 0x00038000
849 || (search_opcode
& 0x003ffffe) == 0x0003a000
850 || ((search_opcode
& 0x003ffffe)
853 prev_sploop_found
= TRUE
;
854 sploop_ii
= ((search_opcode
>> 23) & 0x1f) + 1;
856 else if (search_num_bits
== 16
857 && (search_opcode
& 0x3c7e) == 0x0c66)
859 prev_sploop_found
= TRUE
;
861 = (((search_opcode
>> 7) & 0x7)
862 | ((search_opcode
>> 11) & 0x8)) + 1;
864 if (prev_sploop_found
)
868 else if (sploop_ii
<= 1)
870 else if (sploop_ii
<= 2)
872 else if (sploop_ii
<= 4)
874 else if (sploop_ii
<= 8)
876 else if (sploop_ii
<= 14)
879 prev_sploop_found
= FALSE
;
881 if (prev_sploop_found
)
885 if (!prev_sploop_found
)
888 operands_text
[op_num
] = TRUE
;
891 if (fcyc_bits
> field
->width
)
893 if (enc
->coding_method
== tic6x_coding_fstg
)
896 for (t
= 0, i
= fcyc_bits
; i
< 6; i
++)
897 t
= (t
<< 1) | ((fld_val
>> i
) & 1);
898 operands_text
[op_num
] = TRUE
;
899 snprintf (operands
[op_num
], 24, "%u", t
);
903 operands_text
[op_num
] = TRUE
;
904 snprintf (operands
[op_num
], 24, "%u",
905 fld_val
& ((1 << fcyc_bits
) - 1));
909 case tic6x_coding_spmask
:
911 spmask_skip_operand
= TRUE
;
917 operands_text
[op_num
] = TRUE
;
918 p
= operands
[op_num
];
919 for (i
= 0; i
< 8; i
++)
920 if (fld_val
& (1 << i
))
923 *p
++ = '1' + (i
& 1);
930 case tic6x_coding_fu
:
931 case tic6x_coding_data_fu
:
932 case tic6x_coding_xpath
:
933 /* Don't relate to operands, so operand number is
941 if (mem_base_reg_known_long
&& mem_offset_known_long
)
943 if (operands_text
[op_num
] || operands_pcrel
[op_num
])
945 operands_text
[op_num
] = TRUE
;
946 snprintf (operands
[op_num
], 24, "*+b%u(%u)", mem_base_reg
,
947 mem_offset
* opc
->operand_info
[op_num
].size
);
950 if (mem_base_reg_known
&& mem_offset_known
&& mem_mode_known
952 || (opc
->operand_info
[op_num
].form
953 != tic6x_operand_mem_ndw
)))
957 bfd_boolean offset_is_reg
;
958 bfd_boolean offset_scaled
;
962 if (operands_text
[op_num
] || operands_pcrel
[op_num
])
965 side
= func_unit_side
== 2 ? 'b' : 'a';
966 snprintf (base
, 4, "%c%u", side
, mem_base_reg
);
968 offset_is_reg
= ((mem_mode
& 4) ? TRUE
: FALSE
);
971 snprintf (offset
, 4, "%c%u", side
, mem_offset
);
972 if (opc
->operand_info
[op_num
].form
973 == tic6x_operand_mem_ndw
)
974 offset_scaled
= mem_scaled
? TRUE
: FALSE
;
976 offset_scaled
= TRUE
;
980 if (opc
->operand_info
[op_num
].form
981 == tic6x_operand_mem_ndw
)
983 offset_scaled
= mem_scaled
? TRUE
: FALSE
;
984 snprintf (offset
, 4, "%u", mem_offset
);
988 offset_scaled
= FALSE
;
989 snprintf (offset
, 4, "%u",
991 * opc
->operand_info
[op_num
].size
));
996 snprintf (offsetp
, 6, "[%s]", offset
);
998 snprintf (offsetp
, 6, "(%s)", offset
);
1000 operands_text
[op_num
] = TRUE
;
1001 switch (mem_mode
& ~4u)
1004 snprintf (operands
[op_num
], 24, "*-%s%s", base
, offsetp
);
1008 snprintf (operands
[op_num
], 24, "*+%s%s", base
, offsetp
);
1013 operands_ok
= FALSE
;
1017 snprintf (operands
[op_num
], 24, "*--%s%s", base
,
1022 snprintf (operands
[op_num
], 24, "*++%s%s", base
,
1027 snprintf (operands
[op_num
], 24, "*%s--%s", base
,
1032 snprintf (operands
[op_num
], 24, "*%s++%s", base
,
1041 if (crlo_known
&& crhi_known
)
1046 if (operands_text
[op_num
] || operands_pcrel
[op_num
])
1049 rw
= opc
->operand_info
[op_num
].rw
;
1050 if (rw
!= tic6x_rw_read
1051 && rw
!= tic6x_rw_write
)
1054 for (crid
= 0; crid
< tic6x_ctrl_max
; crid
++)
1056 if (crlo
== tic6x_ctrl_table
[crid
].crlo
1057 && (crhi
& tic6x_ctrl_table
[crid
].crhi_mask
) == 0
1058 && (rw
== tic6x_rw_read
1059 ? (tic6x_ctrl_table
[crid
].rw
== tic6x_rw_read
1060 || (tic6x_ctrl_table
[crid
].rw
1061 == tic6x_rw_read_write
))
1062 : (tic6x_ctrl_table
[crid
].rw
== tic6x_rw_write
1063 || (tic6x_ctrl_table
[crid
].rw
1064 == tic6x_rw_read_write
))))
1067 if (crid
== tic6x_ctrl_max
)
1069 operands_text
[op_num
] = TRUE
;
1070 operands_ok
= FALSE
;
1074 operands_text
[op_num
] = TRUE
;
1075 snprintf (operands
[op_num
], 24, "%s",
1076 tic6x_ctrl_table
[crid
].name
);
1080 if (operands_text
[op_num
] || operands_pcrel
[op_num
]
1081 || spmask_skip_operand
)
1084 if (spmask_skip_operand
)
1086 /* SPMASK operands are only valid as the single operand
1087 in the opcode table. */
1088 if (num_operands
!= 1)
1093 /* The operand must by now have been decoded. */
1094 if (!operands_text
[op_num
] && !operands_pcrel
[op_num
])
1101 info
->bytes_per_chunk
= num_bits
/ 8;
1102 info
->fprintf_func (info
->stream
, "%s%s%s%s", parallel
, cond
,
1103 opc
->name
, func_unit
);
1104 for (op_num
= 0; op_num
< num_operands
; op_num
++)
1106 info
->fprintf_func (info
->stream
, "%c", (op_num
== 0 ? ' ' : ','));
1107 if (operands_pcrel
[op_num
])
1108 info
->print_address_func (operands_addresses
[op_num
], info
);
1110 info
->fprintf_func (info
->stream
, "%s", operands
[op_num
]);
1112 if (fetch_packet_header_based
&& header
.prot
)
1113 info
->fprintf_func (info
->stream
, " || nop 5");
1115 return num_bits
/ 8;
1118 info
->bytes_per_chunk
= num_bits
/ 8;
1119 info
->fprintf_func (info
->stream
, "<undefined instruction 0x%.*x>",
1120 (int) num_bits
/ 4, opcode
);
1121 return num_bits
/ 8;