1c5dff60aSchristos /* TI C6X disassembler.
2*1424dfb3Schristos Copyright (C) 2010-2020 Free Software Foundation, Inc.
3c5dff60aSchristos Contributed by Joseph Myers <joseph@codesourcery.com>
4c5dff60aSchristos Bernd Schmidt <bernds@codesourcery.com>
5c5dff60aSchristos
6c5dff60aSchristos This file is part of libopcodes.
7c5dff60aSchristos
8c5dff60aSchristos This library is free software; you can redistribute it and/or modify
9c5dff60aSchristos it under the terms of the GNU General Public License as published by
10c5dff60aSchristos the Free Software Foundation; either version 3 of the License, or
11c5dff60aSchristos (at your option) any later version.
12c5dff60aSchristos
13c5dff60aSchristos It is distributed in the hope that it will be useful, but WITHOUT
14c5dff60aSchristos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15c5dff60aSchristos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16c5dff60aSchristos License for more details.
17c5dff60aSchristos
18c5dff60aSchristos You should have received a copy of the GNU General Public License
19c5dff60aSchristos along with this program; if not, write to the Free Software
20c5dff60aSchristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21c5dff60aSchristos MA 02110-1301, USA. */
22c5dff60aSchristos
23c5dff60aSchristos #include "sysdep.h"
2407163879Schristos #include "disassemble.h"
25c5dff60aSchristos #include "opcode/tic6x.h"
26c5dff60aSchristos #include "libiberty.h"
27c5dff60aSchristos
28c5dff60aSchristos /* Define the instruction format table. */
29c5dff60aSchristos const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
30c5dff60aSchristos {
31c5dff60aSchristos #define FMT(name, num_bits, cst_bits, mask, fields) \
32c5dff60aSchristos { num_bits, cst_bits, mask, fields },
33c5dff60aSchristos #include "opcode/tic6x-insn-formats.h"
34c5dff60aSchristos #undef FMT
35c5dff60aSchristos };
36c5dff60aSchristos
37c5dff60aSchristos /* Define the control register table. */
38c5dff60aSchristos const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
39c5dff60aSchristos {
40c5dff60aSchristos #define CTRL(name, isa, rw, crlo, crhi_mask) \
41c5dff60aSchristos { \
42c5dff60aSchristos STRINGX(name), \
43c5dff60aSchristos CONCAT2(TIC6X_INSN_,isa), \
44c5dff60aSchristos CONCAT2(tic6x_rw_,rw), \
45c5dff60aSchristos crlo, \
46c5dff60aSchristos crhi_mask \
47c5dff60aSchristos },
48c5dff60aSchristos #include "opcode/tic6x-control-registers.h"
49c5dff60aSchristos #undef CTRL
50c5dff60aSchristos };
51c5dff60aSchristos
52c5dff60aSchristos /* Define the opcode table. */
53c5dff60aSchristos const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
54c5dff60aSchristos {
557af5a897Schristos #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \
567af5a897Schristos { \
577af5a897Schristos STRINGX(name), \
587af5a897Schristos CONCAT2(tic6x_func_unit_,func_unit), \
597af5a897Schristos CONCAT3(tic6x_insn_format,_,format), \
607af5a897Schristos CONCAT2(tic6x_pipeline_,type), \
617af5a897Schristos CONCAT2(TIC6X_INSN_,isa), \
627af5a897Schristos flags, \
637af5a897Schristos fixed, \
647af5a897Schristos ops, \
657af5a897Schristos var \
667af5a897Schristos },
677af5a897Schristos #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
687af5a897Schristos { \
697af5a897Schristos STRINGX(name), \
707af5a897Schristos CONCAT2(tic6x_func_unit_,func_unit), \
717af5a897Schristos CONCAT3(tic6x_insn_format,_,format), \
727af5a897Schristos CONCAT2(tic6x_pipeline_,type), \
737af5a897Schristos CONCAT2(TIC6X_INSN_,isa), \
747af5a897Schristos flags, \
757af5a897Schristos fixed, \
767af5a897Schristos ops, \
777af5a897Schristos var \
787af5a897Schristos },
79c5dff60aSchristos #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
80c5dff60aSchristos { \
81c5dff60aSchristos STRINGX(name), \
82c5dff60aSchristos CONCAT2(tic6x_func_unit_,func_unit), \
83c5dff60aSchristos CONCAT4(tic6x_insn_format_,func_unit,_,format), \
84c5dff60aSchristos CONCAT2(tic6x_pipeline_,type), \
85c5dff60aSchristos CONCAT2(TIC6X_INSN_,isa), \
86c5dff60aSchristos flags, \
87c5dff60aSchristos fixed, \
88c5dff60aSchristos ops, \
89c5dff60aSchristos var \
90c5dff60aSchristos },
91c5dff60aSchristos #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
92c5dff60aSchristos { \
93c5dff60aSchristos STRINGX(name), \
94c5dff60aSchristos CONCAT2(tic6x_func_unit_,func_unit), \
95c5dff60aSchristos CONCAT4(tic6x_insn_format_,func_unit,_,format), \
96c5dff60aSchristos CONCAT2(tic6x_pipeline_,type), \
97c5dff60aSchristos CONCAT2(TIC6X_INSN_,isa), \
98c5dff60aSchristos flags, \
99c5dff60aSchristos fixed, \
100c5dff60aSchristos ops, \
101c5dff60aSchristos var \
102c5dff60aSchristos },
103c5dff60aSchristos #include "opcode/tic6x-opcode-table.h"
104c5dff60aSchristos #undef INSN
105c5dff60aSchristos #undef INSNE
1067af5a897Schristos #undef INSNU
1077af5a897Schristos #undef INSNUE
108c5dff60aSchristos };
109c5dff60aSchristos
110c5dff60aSchristos /* If instruction format FMT has a field FIELD, return a pointer to
111c5dff60aSchristos the description of that field; otherwise return NULL. */
112c5dff60aSchristos
113c5dff60aSchristos const tic6x_insn_field *
tic6x_field_from_fmt(const tic6x_insn_format * fmt,tic6x_insn_field_id field)114c5dff60aSchristos tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
115c5dff60aSchristos {
116c5dff60aSchristos unsigned int f;
117c5dff60aSchristos
118c5dff60aSchristos for (f = 0; f < fmt->num_fields; f++)
119c5dff60aSchristos if (fmt->fields[f].field_id == field)
120c5dff60aSchristos return &fmt->fields[f];
121c5dff60aSchristos
122c5dff60aSchristos return NULL;
123c5dff60aSchristos }
124c5dff60aSchristos
1257af5a897Schristos /* Extract the field width. */
1267af5a897Schristos
1277af5a897Schristos static unsigned int
tic6x_field_width(const tic6x_insn_field * field)1287af5a897Schristos tic6x_field_width (const tic6x_insn_field *field)
1297af5a897Schristos {
1307af5a897Schristos unsigned int i;
1317af5a897Schristos unsigned int width = 0;
1327af5a897Schristos
1337af5a897Schristos if (!field->num_bitfields)
1347af5a897Schristos return field->bitfields[0].width;
1357af5a897Schristos
1367af5a897Schristos for (i = 0 ; i < field->num_bitfields ; i++)
1377af5a897Schristos width += field->bitfields[i].width;
1387af5a897Schristos
1397af5a897Schristos return width;
1407af5a897Schristos }
1417af5a897Schristos
142c5dff60aSchristos /* Extract the bits corresponding to FIELD from OPCODE. */
143c5dff60aSchristos
144c5dff60aSchristos static unsigned int
tic6x_field_bits(unsigned int opcode,const tic6x_insn_field * field)145c5dff60aSchristos tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
146c5dff60aSchristos {
1477af5a897Schristos unsigned int i;
1487af5a897Schristos unsigned int val = 0;
1497af5a897Schristos
1507af5a897Schristos if (!field->num_bitfields)
1517af5a897Schristos return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1);
1527af5a897Schristos
1537af5a897Schristos for (i = 0 ; i < field->num_bitfields ; i++)
1547af5a897Schristos val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1))
1557af5a897Schristos << field->bitfields[i].pos;
1567af5a897Schristos
1577af5a897Schristos return val;
158c5dff60aSchristos }
159c5dff60aSchristos
160c5dff60aSchristos /* Extract a 32-bit value read from the instruction stream. */
161c5dff60aSchristos
162c5dff60aSchristos static unsigned int
tic6x_extract_32(unsigned char * p,struct disassemble_info * info)163c5dff60aSchristos tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
164c5dff60aSchristos {
165c5dff60aSchristos if (info->endian == BFD_ENDIAN_LITTLE)
166*1424dfb3Schristos return p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned) p[3] << 24);
167c5dff60aSchristos else
168*1424dfb3Schristos return p[3] | (p[2] << 8) | (p[1] << 16) | ((unsigned) p[0] << 24);
169c5dff60aSchristos }
170c5dff60aSchristos
171c5dff60aSchristos /* Extract a 16-bit value read from the instruction stream. */
172c5dff60aSchristos
173c5dff60aSchristos static unsigned int
tic6x_extract_16(unsigned char * p,tic6x_fetch_packet_header * header,struct disassemble_info * info)1747af5a897Schristos tic6x_extract_16 (unsigned char *p, tic6x_fetch_packet_header *header,
1757af5a897Schristos struct disassemble_info *info)
176c5dff60aSchristos {
1777af5a897Schristos unsigned int op16;
1787af5a897Schristos
179c5dff60aSchristos if (info->endian == BFD_ENDIAN_LITTLE)
1807af5a897Schristos op16 = (p[0]) | (p[1] << 8);
181c5dff60aSchristos else
1827af5a897Schristos op16 = (p[1]) | (p[0] << 8);
1837af5a897Schristos op16 |= (header->sat << TIC6X_COMPACT_SAT_POS);
1847af5a897Schristos op16 |= (header->br << TIC6X_COMPACT_BR_POS);
1857af5a897Schristos op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS);
1867af5a897Schristos return op16;
187c5dff60aSchristos }
188c5dff60aSchristos
189c5dff60aSchristos /* FP points to a fetch packet. Return whether it is header-based; if
190c5dff60aSchristos it is, fill in HEADER. */
191c5dff60aSchristos
192c5dff60aSchristos static bfd_boolean
tic6x_check_fetch_packet_header(unsigned char * fp,tic6x_fetch_packet_header * header,struct disassemble_info * info)193c5dff60aSchristos tic6x_check_fetch_packet_header (unsigned char *fp,
194c5dff60aSchristos tic6x_fetch_packet_header *header,
195c5dff60aSchristos struct disassemble_info *info)
196c5dff60aSchristos {
197c5dff60aSchristos int i;
198c5dff60aSchristos
199c5dff60aSchristos header->header = tic6x_extract_32 (fp + 28, info);
2007af5a897Schristos
201c5dff60aSchristos if ((header->header & 0xf0000000) != 0xe0000000)
2027af5a897Schristos {
2037af5a897Schristos header->prot = 0;
2047af5a897Schristos header->rs = 0;
2057af5a897Schristos header->dsz = 0;
2067af5a897Schristos header->br = 0;
2077af5a897Schristos header->sat = 0;
2087af5a897Schristos for (i = 0; i < 7; i++)
2097af5a897Schristos header->word_compact[i] = FALSE;
2107af5a897Schristos for (i = 0; i < 14; i++)
2117af5a897Schristos header->p_bits[i] = FALSE;
212c5dff60aSchristos return FALSE;
2137af5a897Schristos }
214c5dff60aSchristos
215c5dff60aSchristos for (i = 0; i < 7; i++)
216c5dff60aSchristos header->word_compact[i]
217c5dff60aSchristos = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
218c5dff60aSchristos
219c5dff60aSchristos header->prot = (header->header & (1u << 20)) ? TRUE : FALSE;
220c5dff60aSchristos header->rs = (header->header & (1u << 19)) ? TRUE : FALSE;
221c5dff60aSchristos header->dsz = (header->header >> 16) & 0x7;
222c5dff60aSchristos header->br = (header->header & (1u << 15)) ? TRUE : FALSE;
223c5dff60aSchristos header->sat = (header->header & (1u << 14)) ? TRUE : FALSE;
224c5dff60aSchristos
225c5dff60aSchristos for (i = 0; i < 14; i++)
226c5dff60aSchristos header->p_bits[i]
227c5dff60aSchristos = (header->header & (1u << i)) ? TRUE : FALSE;
228c5dff60aSchristos
229c5dff60aSchristos return TRUE;
230c5dff60aSchristos }
231c5dff60aSchristos
232c5dff60aSchristos /* Disassemble the instruction at ADDR and print it using
233c5dff60aSchristos INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
234c5dff60aSchristos consumed. */
235c5dff60aSchristos
236c5dff60aSchristos int
print_insn_tic6x(bfd_vma addr,struct disassemble_info * info)237c5dff60aSchristos print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
238c5dff60aSchristos {
239c5dff60aSchristos int status;
240c5dff60aSchristos bfd_vma fp_addr;
241c5dff60aSchristos bfd_vma fp_offset;
242c5dff60aSchristos unsigned char fp[32];
243c5dff60aSchristos unsigned int opcode;
244c5dff60aSchristos tic6x_opcode_id opcode_id;
245c5dff60aSchristos bfd_boolean fetch_packet_header_based;
246c5dff60aSchristos tic6x_fetch_packet_header header;
247c5dff60aSchristos unsigned int num_bits;
248c5dff60aSchristos bfd_boolean bad_offset = FALSE;
249c5dff60aSchristos
250c5dff60aSchristos fp_offset = addr & 0x1f;
251c5dff60aSchristos fp_addr = addr - fp_offset;
252ed6a76a9Schristos /* Read in a block of instructions. Since there might be a
253ed6a76a9Schristos symbol in the middle of this block, disable stop_vma. */
254ed6a76a9Schristos info->stop_vma = 0;
255c5dff60aSchristos status = info->read_memory_func (fp_addr, fp, 32, info);
256c5dff60aSchristos if (status)
257c5dff60aSchristos {
258c5dff60aSchristos info->memory_error_func (status, addr, info);
259c5dff60aSchristos return -1;
260c5dff60aSchristos }
261c5dff60aSchristos
262c5dff60aSchristos fetch_packet_header_based
263c5dff60aSchristos = tic6x_check_fetch_packet_header (fp, &header, info);
264c5dff60aSchristos if (fetch_packet_header_based)
265c5dff60aSchristos {
266c5dff60aSchristos if (fp_offset & 0x1)
267c5dff60aSchristos bad_offset = TRUE;
268c5dff60aSchristos if ((fp_offset & 0x3) && (fp_offset >= 28
269c5dff60aSchristos || !header.word_compact[fp_offset >> 2]))
270c5dff60aSchristos bad_offset = TRUE;
271c5dff60aSchristos if (fp_offset == 28)
272c5dff60aSchristos {
273c5dff60aSchristos info->bytes_per_chunk = 4;
274c5dff60aSchristos info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
275c5dff60aSchristos header.header);
276c5dff60aSchristos return 4;
277c5dff60aSchristos }
278c5dff60aSchristos num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
279c5dff60aSchristos }
280c5dff60aSchristos else
281c5dff60aSchristos {
282c5dff60aSchristos num_bits = 32;
283c5dff60aSchristos if (fp_offset & 0x3)
284c5dff60aSchristos bad_offset = TRUE;
285c5dff60aSchristos }
286c5dff60aSchristos
287c5dff60aSchristos if (bad_offset)
288c5dff60aSchristos {
289c5dff60aSchristos info->bytes_per_chunk = 1;
290c5dff60aSchristos info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
291c5dff60aSchristos return 1;
292c5dff60aSchristos }
293c5dff60aSchristos
294c5dff60aSchristos if (num_bits == 16)
295c5dff60aSchristos {
296c5dff60aSchristos /* The least-significant part of a 32-bit word comes logically
297c5dff60aSchristos before the most-significant part. For big-endian, follow the
298c5dff60aSchristos TI assembler in showing instructions in logical order by
299c5dff60aSchristos pretending that the two halves of the word are in opposite
300c5dff60aSchristos locations to where they actually are. */
301c5dff60aSchristos if (info->endian == BFD_ENDIAN_LITTLE)
3027af5a897Schristos opcode = tic6x_extract_16 (fp + fp_offset, &header, info);
303c5dff60aSchristos else
3047af5a897Schristos opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info);
305c5dff60aSchristos }
306c5dff60aSchristos else
307c5dff60aSchristos opcode = tic6x_extract_32 (fp + fp_offset, info);
308c5dff60aSchristos
309c5dff60aSchristos for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
310c5dff60aSchristos {
311c5dff60aSchristos const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id];
312c5dff60aSchristos const tic6x_insn_format *const fmt
313c5dff60aSchristos = &tic6x_insn_format_table[opc->format];
314c5dff60aSchristos const tic6x_insn_field *creg_field;
315c5dff60aSchristos bfd_boolean p_bit;
316c5dff60aSchristos const char *parallel;
317c5dff60aSchristos const char *cond = "";
318c5dff60aSchristos const char *func_unit;
3191c468f90Schristos char func_unit_buf[8];
320c5dff60aSchristos unsigned int func_unit_side = 0;
321c5dff60aSchristos unsigned int func_unit_data_side = 0;
322c5dff60aSchristos unsigned int func_unit_cross = 0;
3237af5a897Schristos unsigned int t_val = 0;
324c5dff60aSchristos /* The maximum length of the text of a non-PC-relative operand
325c5dff60aSchristos is 24 bytes (SPMASK masking all eight functional units, with
326c5dff60aSchristos separating commas and trailing NUL). */
327c5dff60aSchristos char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } };
328c5dff60aSchristos bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 };
329c5dff60aSchristos bfd_boolean operands_text[TIC6X_MAX_OPERANDS] = { FALSE };
330c5dff60aSchristos bfd_boolean operands_pcrel[TIC6X_MAX_OPERANDS] = { FALSE };
331c5dff60aSchristos unsigned int fix;
332c5dff60aSchristos unsigned int num_operands;
333c5dff60aSchristos unsigned int op_num;
334c5dff60aSchristos bfd_boolean fixed_ok;
335c5dff60aSchristos bfd_boolean operands_ok;
3367af5a897Schristos bfd_boolean have_t = FALSE;
337c5dff60aSchristos
338c5dff60aSchristos if (opc->flags & TIC6X_FLAG_MACRO)
339c5dff60aSchristos continue;
340c5dff60aSchristos if (fmt->num_bits != num_bits)
341c5dff60aSchristos continue;
342c5dff60aSchristos if ((opcode & fmt->mask) != fmt->cst_bits)
343c5dff60aSchristos continue;
344c5dff60aSchristos
345c5dff60aSchristos /* If the format has a creg field, it is only a candidate for a
346c5dff60aSchristos match if the creg and z fields have values indicating a valid
347c5dff60aSchristos condition; reserved values indicate either an instruction
348c5dff60aSchristos format without a creg field, or an invalid instruction. */
349c5dff60aSchristos creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg);
350c5dff60aSchristos if (creg_field)
351c5dff60aSchristos {
352c5dff60aSchristos const tic6x_insn_field *z_field;
353c5dff60aSchristos unsigned int creg_value, z_value;
354c5dff60aSchristos static const char *const conds[8][2] =
355c5dff60aSchristos {
356c5dff60aSchristos { "", NULL },
357c5dff60aSchristos { "[b0] ", "[!b0] " },
358c5dff60aSchristos { "[b1] ", "[!b1] " },
359c5dff60aSchristos { "[b2] ", "[!b2] " },
360c5dff60aSchristos { "[a1] ", "[!a1] " },
361c5dff60aSchristos { "[a2] ", "[!a2] " },
362c5dff60aSchristos { "[a0] ", "[!a0] " },
363c5dff60aSchristos { NULL, NULL }
364c5dff60aSchristos };
365c5dff60aSchristos
366c5dff60aSchristos /* A creg field is not meaningful without a z field, so if
367c5dff60aSchristos the z field is not present this is an error in the format
368c5dff60aSchristos table. */
369c5dff60aSchristos z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
370c5dff60aSchristos if (!z_field)
3717af5a897Schristos {
3727af5a897Schristos printf ("*** opcode %x: missing z field", opcode);
373c5dff60aSchristos abort ();
3747af5a897Schristos }
375c5dff60aSchristos
376c5dff60aSchristos creg_value = tic6x_field_bits (opcode, creg_field);
377c5dff60aSchristos z_value = tic6x_field_bits (opcode, z_field);
378c5dff60aSchristos cond = conds[creg_value][z_value];
379c5dff60aSchristos if (cond == NULL)
380c5dff60aSchristos continue;
381c5dff60aSchristos }
382c5dff60aSchristos
3837af5a897Schristos if (opc->flags & TIC6X_FLAG_INSN16_SPRED)
3847af5a897Schristos {
3857af5a897Schristos const tic6x_insn_field *cc_field;
3867af5a897Schristos unsigned int s_value = 0;
3877af5a897Schristos unsigned int z_value = 0;
3887af5a897Schristos bfd_boolean cond_known = FALSE;
3897af5a897Schristos static const char *const conds[2][2] =
3907af5a897Schristos {
3917af5a897Schristos { "[a0] ", "[!a0] " },
3927af5a897Schristos { "[b0] ", "[!b0] " }
3937af5a897Schristos };
3947af5a897Schristos
3957af5a897Schristos cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc);
3967af5a897Schristos
3977af5a897Schristos if (cc_field)
3987af5a897Schristos {
3997af5a897Schristos unsigned int cc_value;
4007af5a897Schristos
4017af5a897Schristos cc_value = tic6x_field_bits (opcode, cc_field);
4027af5a897Schristos s_value = (cc_value & 0x2) >> 1;
4037af5a897Schristos z_value = (cc_value & 0x1);
4047af5a897Schristos cond_known = TRUE;
4057af5a897Schristos }
4067af5a897Schristos else
4077af5a897Schristos {
4087af5a897Schristos const tic6x_insn_field *z_field;
4097af5a897Schristos const tic6x_insn_field *s_field;
4107af5a897Schristos
4117af5a897Schristos s_field = tic6x_field_from_fmt (fmt, tic6x_field_s);
4127af5a897Schristos
4137af5a897Schristos if (!s_field)
4147af5a897Schristos {
4157af5a897Schristos printf ("opcode %x: missing compact insn predicate register field (s field)\n",
4167af5a897Schristos opcode);
4177af5a897Schristos abort ();
4187af5a897Schristos }
4197af5a897Schristos s_value = tic6x_field_bits (opcode, s_field);
4207af5a897Schristos z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
4217af5a897Schristos if (!z_field)
4227af5a897Schristos {
4237af5a897Schristos printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode);
4247af5a897Schristos abort ();
4257af5a897Schristos }
4267af5a897Schristos
4277af5a897Schristos z_value = tic6x_field_bits (opcode, z_field);
4287af5a897Schristos cond_known = TRUE;
4297af5a897Schristos }
4307af5a897Schristos
4317af5a897Schristos if (!cond_known)
4327af5a897Schristos {
4337af5a897Schristos printf ("opcode %x: unspecified ompact insn predicate\n", opcode);
4347af5a897Schristos abort ();
4357af5a897Schristos }
4367af5a897Schristos cond = conds[s_value][z_value];
4377af5a897Schristos }
4387af5a897Schristos
439c5dff60aSchristos /* All fixed fields must have matching values; all fields with
440c5dff60aSchristos restricted ranges must have values within those ranges. */
441c5dff60aSchristos fixed_ok = TRUE;
442c5dff60aSchristos for (fix = 0; fix < opc->num_fixed_fields; fix++)
443c5dff60aSchristos {
444c5dff60aSchristos unsigned int field_bits;
445c5dff60aSchristos const tic6x_insn_field *const field
446c5dff60aSchristos = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
447c5dff60aSchristos
448c5dff60aSchristos if (!field)
4497af5a897Schristos {
4507af5a897Schristos printf ("opcode %x: missing field #%d for FIX #%d\n",
4517af5a897Schristos opcode, opc->fixed_fields[fix].field_id, fix);
452c5dff60aSchristos abort ();
4537af5a897Schristos }
4547af5a897Schristos
455c5dff60aSchristos field_bits = tic6x_field_bits (opcode, field);
456c5dff60aSchristos if (field_bits < opc->fixed_fields[fix].min_val
457c5dff60aSchristos || field_bits > opc->fixed_fields[fix].max_val)
458c5dff60aSchristos {
459c5dff60aSchristos fixed_ok = FALSE;
460c5dff60aSchristos break;
461c5dff60aSchristos }
462c5dff60aSchristos }
463c5dff60aSchristos if (!fixed_ok)
464c5dff60aSchristos continue;
465c5dff60aSchristos
466c5dff60aSchristos /* The instruction matches. */
467c5dff60aSchristos
468c5dff60aSchristos /* The p-bit indicates whether this instruction is in parallel
469c5dff60aSchristos with the *next* instruction, whereas the parallel bars
470c5dff60aSchristos indicate the instruction is in parallel with the *previous*
471c5dff60aSchristos instruction. Thus, we must find the p-bit for the previous
472c5dff60aSchristos instruction. */
473c5dff60aSchristos if (num_bits == 16 && (fp_offset & 0x2) == 2)
474c5dff60aSchristos {
475c5dff60aSchristos /* This is the logically second (most significant; second in
476c5dff60aSchristos fp_offset terms because fp_offset relates to logical not
477c5dff60aSchristos physical addresses) instruction of a compact pair; find
478c5dff60aSchristos the p-bit for the first (least significant). */
479c5dff60aSchristos p_bit = header.p_bits[(fp_offset >> 2) << 1];
480c5dff60aSchristos }
481c5dff60aSchristos else if (fp_offset >= 4)
482c5dff60aSchristos {
483c5dff60aSchristos /* Find the last instruction of the previous word in this
484c5dff60aSchristos fetch packet. For compact instructions, this is the most
485c5dff60aSchristos significant 16 bits. */
486c5dff60aSchristos if (fetch_packet_header_based
487c5dff60aSchristos && header.word_compact[(fp_offset >> 2) - 1])
488c5dff60aSchristos p_bit = header.p_bits[(fp_offset >> 1) - 1];
489c5dff60aSchristos else
490c5dff60aSchristos {
491c5dff60aSchristos unsigned int prev_opcode
492c5dff60aSchristos = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
493c5dff60aSchristos p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
494c5dff60aSchristos }
495c5dff60aSchristos }
496c5dff60aSchristos else
497c5dff60aSchristos {
498c5dff60aSchristos /* Find the last instruction of the previous fetch
499c5dff60aSchristos packet. */
500c5dff60aSchristos unsigned char fp_prev[32];
5017af5a897Schristos
502c5dff60aSchristos status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info);
503c5dff60aSchristos if (status)
504c5dff60aSchristos /* No previous instruction to be parallel with. */
505c5dff60aSchristos p_bit = FALSE;
506c5dff60aSchristos else
507c5dff60aSchristos {
508c5dff60aSchristos bfd_boolean prev_header_based;
509c5dff60aSchristos tic6x_fetch_packet_header prev_header;
510c5dff60aSchristos
511c5dff60aSchristos prev_header_based
512c5dff60aSchristos = tic6x_check_fetch_packet_header (fp_prev, &prev_header, info);
5131c468f90Schristos if (prev_header_based)
5141c468f90Schristos {
5151c468f90Schristos if (prev_header.word_compact[6])
516c5dff60aSchristos p_bit = prev_header.p_bits[13];
517c5dff60aSchristos else
518c5dff60aSchristos {
5191c468f90Schristos unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 24,
5201c468f90Schristos info);
5211c468f90Schristos p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
5221c468f90Schristos }
5231c468f90Schristos }
5241c468f90Schristos else
5251c468f90Schristos {
526c5dff60aSchristos unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
527c5dff60aSchristos info);
528c5dff60aSchristos p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
529c5dff60aSchristos }
530c5dff60aSchristos }
531c5dff60aSchristos }
532c5dff60aSchristos parallel = p_bit ? "|| " : "";
533c5dff60aSchristos
534c5dff60aSchristos if (opc->func_unit == tic6x_func_unit_nfu)
535c5dff60aSchristos func_unit = "";
536c5dff60aSchristos else
537c5dff60aSchristos {
538c5dff60aSchristos unsigned int fld_num;
539c5dff60aSchristos char func_unit_char;
540c5dff60aSchristos const char *data_str;
541c5dff60aSchristos bfd_boolean have_areg = FALSE;
542c5dff60aSchristos bfd_boolean have_cross = FALSE;
543c5dff60aSchristos
544c5dff60aSchristos func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0;
545c5dff60aSchristos func_unit_cross = 0;
546c5dff60aSchristos func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0;
547c5dff60aSchristos
548c5dff60aSchristos for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
549c5dff60aSchristos {
550c5dff60aSchristos const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
551c5dff60aSchristos const tic6x_insn_field *field;
552c5dff60aSchristos unsigned int fld_val;
553c5dff60aSchristos
554c5dff60aSchristos field = tic6x_field_from_fmt (fmt, enc->field_id);
5557af5a897Schristos
556c5dff60aSchristos if (!field)
5577af5a897Schristos {
5587af5a897Schristos printf ("opcode %x: could not retrieve field (field_id:%d)\n",
5597af5a897Schristos opcode, fld_num);
560c5dff60aSchristos abort ();
5617af5a897Schristos }
5627af5a897Schristos
563c5dff60aSchristos fld_val = tic6x_field_bits (opcode, field);
5647af5a897Schristos
565c5dff60aSchristos switch (enc->coding_method)
566c5dff60aSchristos {
567c5dff60aSchristos case tic6x_coding_fu:
568c5dff60aSchristos /* The side must be specified exactly once. */
569c5dff60aSchristos if (func_unit_side)
5707af5a897Schristos {
5717af5a897Schristos printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
5727af5a897Schristos opcode, fld_num);
573c5dff60aSchristos abort ();
5747af5a897Schristos }
575c5dff60aSchristos func_unit_side = (fld_val ? 2 : 1);
576c5dff60aSchristos break;
577c5dff60aSchristos
578c5dff60aSchristos case tic6x_coding_data_fu:
579c5dff60aSchristos /* The data side must be specified exactly once. */
580c5dff60aSchristos if (func_unit_data_side)
5817af5a897Schristos {
5827af5a897Schristos printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
5837af5a897Schristos opcode, fld_num);
584c5dff60aSchristos abort ();
5857af5a897Schristos }
586c5dff60aSchristos func_unit_data_side = (fld_val ? 2 : 1);
587c5dff60aSchristos break;
588c5dff60aSchristos
589c5dff60aSchristos case tic6x_coding_xpath:
590c5dff60aSchristos /* Cross path use must be specified exactly
591c5dff60aSchristos once. */
592c5dff60aSchristos if (have_cross)
5937af5a897Schristos {
5947af5a897Schristos printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n",
5957af5a897Schristos opcode, fld_num);
596c5dff60aSchristos abort ();
5977af5a897Schristos }
598c5dff60aSchristos have_cross = TRUE;
599c5dff60aSchristos func_unit_cross = fld_val;
600c5dff60aSchristos break;
601c5dff60aSchristos
6027af5a897Schristos case tic6x_coding_rside:
6037af5a897Schristos /* If the format has a t field, use it for src/dst register side. */
6047af5a897Schristos have_t = TRUE;
6057af5a897Schristos t_val = fld_val;
6067af5a897Schristos func_unit_data_side = (t_val ? 2 : 1);
6077af5a897Schristos break;
6087af5a897Schristos
609c5dff60aSchristos case tic6x_coding_areg:
610c5dff60aSchristos have_areg = TRUE;
611c5dff60aSchristos break;
612c5dff60aSchristos
613c5dff60aSchristos default:
614c5dff60aSchristos /* Don't relate to functional units. */
615c5dff60aSchristos break;
616c5dff60aSchristos }
617c5dff60aSchristos }
618c5dff60aSchristos
619c5dff60aSchristos /* The side of the functional unit used must now have been
620c5dff60aSchristos determined either from the flags or from an instruction
621c5dff60aSchristos field. */
622c5dff60aSchristos if (func_unit_side != 1 && func_unit_side != 2)
6237af5a897Schristos {
6247af5a897Schristos printf ("opcode %x: func_unit_side is not encoded!\n", opcode);
625c5dff60aSchristos abort ();
6267af5a897Schristos }
627c5dff60aSchristos
628c5dff60aSchristos /* Cross paths are not applicable when sides are specified
629c5dff60aSchristos for both address and data paths. */
630c5dff60aSchristos if (func_unit_data_side && have_cross)
6317af5a897Schristos {
6327af5a897Schristos printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n",
6337af5a897Schristos opcode);
634c5dff60aSchristos abort ();
6357af5a897Schristos }
636c5dff60aSchristos
637c5dff60aSchristos /* Separate address and data paths are only applicable for
638c5dff60aSchristos the D unit. */
639c5dff60aSchristos if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d)
6407af5a897Schristos {
6417af5a897Schristos printf ("opcode %x: separate address and data paths only applicable for D unit!\n",
6427af5a897Schristos opcode);
643c5dff60aSchristos abort ();
6447af5a897Schristos }
645c5dff60aSchristos
646c5dff60aSchristos /* If an address register is being used but in ADDA rather
647c5dff60aSchristos than a load or store, it uses a cross path for side-A
648c5dff60aSchristos instructions, and the cross path use is not specified by
649c5dff60aSchristos an instruction field. */
650c5dff60aSchristos if (have_areg && !func_unit_data_side)
651c5dff60aSchristos {
652c5dff60aSchristos if (have_cross)
6537af5a897Schristos {
6547af5a897Schristos printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode);
655c5dff60aSchristos abort ();
6567af5a897Schristos }
657c5dff60aSchristos func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
658c5dff60aSchristos }
659c5dff60aSchristos
660c5dff60aSchristos switch (opc->func_unit)
661c5dff60aSchristos {
662c5dff60aSchristos case tic6x_func_unit_d:
663c5dff60aSchristos func_unit_char = 'D';
664c5dff60aSchristos break;
665c5dff60aSchristos
666c5dff60aSchristos case tic6x_func_unit_l:
667c5dff60aSchristos func_unit_char = 'L';
668c5dff60aSchristos break;
669c5dff60aSchristos
670c5dff60aSchristos case tic6x_func_unit_m:
671c5dff60aSchristos func_unit_char = 'M';
672c5dff60aSchristos break;
673c5dff60aSchristos
674c5dff60aSchristos case tic6x_func_unit_s:
675c5dff60aSchristos func_unit_char = 'S';
676c5dff60aSchristos break;
677c5dff60aSchristos
678c5dff60aSchristos default:
6797af5a897Schristos printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit);
680c5dff60aSchristos abort ();
681c5dff60aSchristos }
682c5dff60aSchristos
683c5dff60aSchristos switch (func_unit_data_side)
684c5dff60aSchristos {
685c5dff60aSchristos case 0:
686c5dff60aSchristos data_str = "";
687c5dff60aSchristos break;
688c5dff60aSchristos
689c5dff60aSchristos case 1:
690c5dff60aSchristos data_str = "T1";
691c5dff60aSchristos break;
692c5dff60aSchristos
693c5dff60aSchristos case 2:
694c5dff60aSchristos data_str = "T2";
695c5dff60aSchristos break;
696c5dff60aSchristos
697c5dff60aSchristos default:
6987af5a897Schristos printf ("opcode %x: illegal data func_unit specifier %d\n",
6997af5a897Schristos opcode, func_unit_data_side);
700c5dff60aSchristos abort ();
701c5dff60aSchristos }
702c5dff60aSchristos
7037af5a897Schristos if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1)
7047af5a897Schristos func_unit_cross = 1;
7057af5a897Schristos
7061c468f90Schristos snprintf (func_unit_buf, sizeof func_unit_buf, " .%c%u%s%s",
7071c468f90Schristos func_unit_char, func_unit_side,
7081c468f90Schristos (func_unit_cross ? "X" : ""), data_str);
709c5dff60aSchristos func_unit = func_unit_buf;
710c5dff60aSchristos }
711c5dff60aSchristos
712c5dff60aSchristos /* For each operand there must be one or more fields set based
713c5dff60aSchristos on that operand, that can together be used to derive the
714c5dff60aSchristos operand value. */
715c5dff60aSchristos operands_ok = TRUE;
716c5dff60aSchristos num_operands = opc->num_operands;
717c5dff60aSchristos for (op_num = 0; op_num < num_operands; op_num++)
718c5dff60aSchristos {
719c5dff60aSchristos unsigned int fld_num;
720c5dff60aSchristos unsigned int mem_base_reg = 0;
721c5dff60aSchristos bfd_boolean mem_base_reg_known = FALSE;
722c5dff60aSchristos bfd_boolean mem_base_reg_known_long = FALSE;
723c5dff60aSchristos unsigned int mem_offset = 0;
724c5dff60aSchristos bfd_boolean mem_offset_known = FALSE;
725c5dff60aSchristos bfd_boolean mem_offset_known_long = FALSE;
726c5dff60aSchristos unsigned int mem_mode = 0;
727c5dff60aSchristos bfd_boolean mem_mode_known = FALSE;
728c5dff60aSchristos unsigned int mem_scaled = 0;
729c5dff60aSchristos bfd_boolean mem_scaled_known = FALSE;
730c5dff60aSchristos unsigned int crlo = 0;
731c5dff60aSchristos bfd_boolean crlo_known = FALSE;
732c5dff60aSchristos unsigned int crhi = 0;
733c5dff60aSchristos bfd_boolean crhi_known = FALSE;
734c5dff60aSchristos bfd_boolean spmask_skip_operand = FALSE;
735c5dff60aSchristos unsigned int fcyc_bits = 0;
736c5dff60aSchristos bfd_boolean prev_sploop_found = FALSE;
737c5dff60aSchristos
738c5dff60aSchristos switch (opc->operand_info[op_num].form)
739c5dff60aSchristos {
7407af5a897Schristos case tic6x_operand_b15reg:
7417af5a897Schristos /* Fully determined by the functional unit. */
7427af5a897Schristos operands_text[op_num] = TRUE;
7437af5a897Schristos snprintf (operands[op_num], 24, "b15");
7447af5a897Schristos continue;
7457af5a897Schristos
7467af5a897Schristos case tic6x_operand_zreg:
7477af5a897Schristos /* Fully determined by the functional unit. */
7487af5a897Schristos operands_text[op_num] = TRUE;
7497af5a897Schristos snprintf (operands[op_num], 24, "%c0",
7507af5a897Schristos (func_unit_side == 2 ? 'b' : 'a'));
7517af5a897Schristos continue;
7527af5a897Schristos
753c5dff60aSchristos case tic6x_operand_retreg:
754c5dff60aSchristos /* Fully determined by the functional unit. */
755c5dff60aSchristos operands_text[op_num] = TRUE;
756c5dff60aSchristos snprintf (operands[op_num], 24, "%c3",
757c5dff60aSchristos (func_unit_side == 2 ? 'b' : 'a'));
758c5dff60aSchristos continue;
759c5dff60aSchristos
760c5dff60aSchristos case tic6x_operand_irp:
761c5dff60aSchristos operands_text[op_num] = TRUE;
762c5dff60aSchristos snprintf (operands[op_num], 24, "irp");
763c5dff60aSchristos continue;
764c5dff60aSchristos
765c5dff60aSchristos case tic6x_operand_nrp:
766c5dff60aSchristos operands_text[op_num] = TRUE;
767c5dff60aSchristos snprintf (operands[op_num], 24, "nrp");
768c5dff60aSchristos continue;
769c5dff60aSchristos
7707af5a897Schristos case tic6x_operand_ilc:
7717af5a897Schristos operands_text[op_num] = TRUE;
7727af5a897Schristos snprintf (operands[op_num], 24, "ilc");
7737af5a897Schristos continue;
7747af5a897Schristos
7757af5a897Schristos case tic6x_operand_hw_const_minus_1:
7767af5a897Schristos operands_text[op_num] = TRUE;
7777af5a897Schristos snprintf (operands[op_num], 24, "-1");
7787af5a897Schristos continue;
7797af5a897Schristos
7807af5a897Schristos case tic6x_operand_hw_const_0:
7817af5a897Schristos operands_text[op_num] = TRUE;
7827af5a897Schristos snprintf (operands[op_num], 24, "0");
7837af5a897Schristos continue;
7847af5a897Schristos
7857af5a897Schristos case tic6x_operand_hw_const_1:
7867af5a897Schristos operands_text[op_num] = TRUE;
7877af5a897Schristos snprintf (operands[op_num], 24, "1");
7887af5a897Schristos continue;
7897af5a897Schristos
7907af5a897Schristos case tic6x_operand_hw_const_5:
7917af5a897Schristos operands_text[op_num] = TRUE;
7927af5a897Schristos snprintf (operands[op_num], 24, "5");
7937af5a897Schristos continue;
7947af5a897Schristos
7957af5a897Schristos case tic6x_operand_hw_const_16:
7967af5a897Schristos operands_text[op_num] = TRUE;
7977af5a897Schristos snprintf (operands[op_num], 24, "16");
7987af5a897Schristos continue;
7997af5a897Schristos
8007af5a897Schristos case tic6x_operand_hw_const_24:
8017af5a897Schristos operands_text[op_num] = TRUE;
8027af5a897Schristos snprintf (operands[op_num], 24, "24");
8037af5a897Schristos continue;
8047af5a897Schristos
8057af5a897Schristos case tic6x_operand_hw_const_31:
8067af5a897Schristos operands_text[op_num] = TRUE;
8077af5a897Schristos snprintf (operands[op_num], 24, "31");
8087af5a897Schristos continue;
8097af5a897Schristos
810c5dff60aSchristos default:
811c5dff60aSchristos break;
812c5dff60aSchristos }
813c5dff60aSchristos
814c5dff60aSchristos for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
815c5dff60aSchristos {
816c5dff60aSchristos const tic6x_coding_field *const enc
817c5dff60aSchristos = &opc->variable_fields[fld_num];
818c5dff60aSchristos const tic6x_insn_field *field;
819c5dff60aSchristos unsigned int fld_val;
8207af5a897Schristos unsigned int reg_base = 0;
821c5dff60aSchristos signed int signed_fld_val;
8227af5a897Schristos char reg_side = '?';
823c5dff60aSchristos
824c5dff60aSchristos if (enc->operand_num != op_num)
825c5dff60aSchristos continue;
826c5dff60aSchristos field = tic6x_field_from_fmt (fmt, enc->field_id);
827c5dff60aSchristos if (!field)
8287af5a897Schristos {
8297af5a897Schristos printf ("opcode %x: missing field (field_id:%d) in format\n", opcode, enc->field_id);
830c5dff60aSchristos abort ();
8317af5a897Schristos }
832c5dff60aSchristos fld_val = tic6x_field_bits (opcode, field);
833c5dff60aSchristos switch (enc->coding_method)
834c5dff60aSchristos {
8357af5a897Schristos case tic6x_coding_cst_s3i:
8367af5a897Schristos (fld_val == 0x00) && (fld_val = 0x10);
8377af5a897Schristos (fld_val == 0x07) && (fld_val = 0x08);
8387af5a897Schristos /* Fall through. */
839c5dff60aSchristos case tic6x_coding_ucst:
840c5dff60aSchristos case tic6x_coding_ulcst_dpr_byte:
841c5dff60aSchristos case tic6x_coding_ulcst_dpr_half:
842c5dff60aSchristos case tic6x_coding_ulcst_dpr_word:
843c5dff60aSchristos case tic6x_coding_lcst_low16:
844c5dff60aSchristos switch (opc->operand_info[op_num].form)
845c5dff60aSchristos {
846c5dff60aSchristos case tic6x_operand_asm_const:
847c5dff60aSchristos case tic6x_operand_link_const:
848c5dff60aSchristos operands_text[op_num] = TRUE;
849c5dff60aSchristos snprintf (operands[op_num], 24, "%u", fld_val);
850c5dff60aSchristos break;
851c5dff60aSchristos
852c5dff60aSchristos case tic6x_operand_mem_long:
853c5dff60aSchristos mem_offset = fld_val;
854c5dff60aSchristos mem_offset_known_long = TRUE;
855c5dff60aSchristos break;
856c5dff60aSchristos
857c5dff60aSchristos default:
8587af5a897Schristos printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num);
859c5dff60aSchristos abort ();
860c5dff60aSchristos }
861c5dff60aSchristos break;
862c5dff60aSchristos
863c5dff60aSchristos case tic6x_coding_lcst_high16:
864c5dff60aSchristos operands_text[op_num] = TRUE;
865c5dff60aSchristos snprintf (operands[op_num], 24, "%u", fld_val << 16);
866c5dff60aSchristos break;
867c5dff60aSchristos
8687af5a897Schristos case tic6x_coding_scst_l3i:
8697af5a897Schristos operands_text[op_num] = TRUE;
8707af5a897Schristos if (fld_val == 0)
8717af5a897Schristos {
8727af5a897Schristos signed_fld_val = 8;
8737af5a897Schristos }
8747af5a897Schristos else
8757af5a897Schristos {
8767af5a897Schristos signed_fld_val = (signed int) fld_val;
8777af5a897Schristos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
8787af5a897Schristos signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
8797af5a897Schristos }
8807af5a897Schristos snprintf (operands[op_num], 24, "%d", signed_fld_val);
8817af5a897Schristos break;
8827af5a897Schristos
883c5dff60aSchristos case tic6x_coding_scst:
884c5dff60aSchristos operands_text[op_num] = TRUE;
885c5dff60aSchristos signed_fld_val = (signed int) fld_val;
8867af5a897Schristos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
8877af5a897Schristos signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
888c5dff60aSchristos snprintf (operands[op_num], 24, "%d", signed_fld_val);
889c5dff60aSchristos break;
890c5dff60aSchristos
891c5dff60aSchristos case tic6x_coding_ucst_minus_one:
892c5dff60aSchristos operands_text[op_num] = TRUE;
893c5dff60aSchristos snprintf (operands[op_num], 24, "%u", fld_val + 1);
894c5dff60aSchristos break;
895c5dff60aSchristos
896c5dff60aSchristos case tic6x_coding_pcrel:
897c5dff60aSchristos case tic6x_coding_pcrel_half:
898c5dff60aSchristos signed_fld_val = (signed int) fld_val;
8997af5a897Schristos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
9007af5a897Schristos signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
901c5dff60aSchristos if (fetch_packet_header_based
902c5dff60aSchristos && enc->coding_method == tic6x_coding_pcrel_half)
903c5dff60aSchristos signed_fld_val *= 2;
904c5dff60aSchristos else
905c5dff60aSchristos signed_fld_val *= 4;
906c5dff60aSchristos operands_pcrel[op_num] = TRUE;
907c5dff60aSchristos operands_addresses[op_num] = fp_addr + signed_fld_val;
908c5dff60aSchristos break;
909c5dff60aSchristos
9107af5a897Schristos case tic6x_coding_regpair_msb:
9117af5a897Schristos if (opc->operand_info[op_num].form != tic6x_operand_regpair)
9127af5a897Schristos abort ();
9137af5a897Schristos operands_text[op_num] = TRUE;
9147af5a897Schristos snprintf (operands[op_num], 24, "%c%u:%c%u",
9157af5a897Schristos (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1),
9167af5a897Schristos (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1);
9177af5a897Schristos break;
9187af5a897Schristos
9197af5a897Schristos case tic6x_coding_pcrel_half_unsigned:
9207af5a897Schristos operands_pcrel[op_num] = TRUE;
9217af5a897Schristos operands_addresses[op_num] = fp_addr + 2 * fld_val;
9227af5a897Schristos break;
9237af5a897Schristos
924c5dff60aSchristos case tic6x_coding_reg_shift:
925c5dff60aSchristos fld_val <<= 1;
926c5dff60aSchristos /* Fall through. */
927c5dff60aSchristos case tic6x_coding_reg:
9287af5a897Schristos if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
9297af5a897Schristos {
9307af5a897Schristos reg_base = 16;
9317af5a897Schristos }
932c5dff60aSchristos switch (opc->operand_info[op_num].form)
933c5dff60aSchristos {
9347af5a897Schristos case tic6x_operand_treg:
9357af5a897Schristos if (!have_t)
9367af5a897Schristos {
9377af5a897Schristos printf ("opcode %x: operand treg but missing t field\n", opcode);
9387af5a897Schristos abort ();
9397af5a897Schristos }
9407af5a897Schristos operands_text[op_num] = TRUE;
9417af5a897Schristos reg_side = t_val ? 'b' : 'a';
9427af5a897Schristos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
9437af5a897Schristos break;
9447af5a897Schristos
945c5dff60aSchristos case tic6x_operand_reg:
946c5dff60aSchristos operands_text[op_num] = TRUE;
9477af5a897Schristos reg_side = (func_unit_side == 2) ? 'b' : 'a';
9487af5a897Schristos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
9497af5a897Schristos break;
9507af5a897Schristos
9517af5a897Schristos case tic6x_operand_reg_nors:
9527af5a897Schristos operands_text[op_num] = TRUE;
9537af5a897Schristos reg_side = (func_unit_side == 2) ? 'b' : 'a';
9547af5a897Schristos snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val);
9557af5a897Schristos break;
9567af5a897Schristos
9577af5a897Schristos case tic6x_operand_reg_bside:
9587af5a897Schristos operands_text[op_num] = TRUE;
9597af5a897Schristos snprintf (operands[op_num], 24, "b%u", reg_base + fld_val);
9607af5a897Schristos break;
9617af5a897Schristos
9627af5a897Schristos case tic6x_operand_reg_bside_nors:
9637af5a897Schristos operands_text[op_num] = TRUE;
9647af5a897Schristos snprintf (operands[op_num], 24, "b%u", fld_val);
965c5dff60aSchristos break;
966c5dff60aSchristos
967c5dff60aSchristos case tic6x_operand_xreg:
968c5dff60aSchristos operands_text[op_num] = TRUE;
9697af5a897Schristos reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
9707af5a897Schristos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
971c5dff60aSchristos break;
972c5dff60aSchristos
973c5dff60aSchristos case tic6x_operand_dreg:
974c5dff60aSchristos operands_text[op_num] = TRUE;
9757af5a897Schristos reg_side = (func_unit_data_side == 2) ? 'b' : 'a';
9767af5a897Schristos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
977c5dff60aSchristos break;
978c5dff60aSchristos
979c5dff60aSchristos case tic6x_operand_regpair:
980c5dff60aSchristos operands_text[op_num] = TRUE;
981c5dff60aSchristos if (fld_val & 1)
982c5dff60aSchristos operands_ok = FALSE;
9837af5a897Schristos reg_side = (func_unit_side == 2) ? 'b' : 'a';
984c5dff60aSchristos snprintf (operands[op_num], 24, "%c%u:%c%u",
9857af5a897Schristos reg_side, reg_base + fld_val + 1,
9867af5a897Schristos reg_side, reg_base + fld_val);
987c5dff60aSchristos break;
988c5dff60aSchristos
989c5dff60aSchristos case tic6x_operand_xregpair:
990c5dff60aSchristos operands_text[op_num] = TRUE;
991c5dff60aSchristos if (fld_val & 1)
992c5dff60aSchristos operands_ok = FALSE;
9937af5a897Schristos reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
994c5dff60aSchristos snprintf (operands[op_num], 24, "%c%u:%c%u",
9957af5a897Schristos reg_side, reg_base + fld_val + 1,
9967af5a897Schristos reg_side, reg_base + fld_val);
9977af5a897Schristos break;
9987af5a897Schristos
9997af5a897Schristos case tic6x_operand_tregpair:
10007af5a897Schristos if (!have_t)
10017af5a897Schristos {
10027af5a897Schristos printf ("opcode %x: operand tregpair but missing t field\n", opcode);
10037af5a897Schristos abort ();
10047af5a897Schristos }
10057af5a897Schristos operands_text[op_num] = TRUE;
10067af5a897Schristos if (fld_val & 1)
10077af5a897Schristos operands_ok = FALSE;
10087af5a897Schristos reg_side = t_val ? 'b' : 'a';
10097af5a897Schristos snprintf (operands[op_num], 24, "%c%u:%c%u",
10107af5a897Schristos reg_side, reg_base + fld_val + 1,
10117af5a897Schristos reg_side, reg_base + fld_val);
1012c5dff60aSchristos break;
1013c5dff60aSchristos
1014c5dff60aSchristos case tic6x_operand_dregpair:
1015c5dff60aSchristos operands_text[op_num] = TRUE;
1016c5dff60aSchristos if (fld_val & 1)
1017c5dff60aSchristos operands_ok = FALSE;
10187af5a897Schristos reg_side = (func_unit_data_side) == 2 ? 'b' : 'a';
1019c5dff60aSchristos snprintf (operands[op_num], 24, "%c%u:%c%u",
10207af5a897Schristos reg_side, reg_base + fld_val + 1,
10217af5a897Schristos reg_side, reg_base + fld_val);
1022c5dff60aSchristos break;
1023c5dff60aSchristos
1024c5dff60aSchristos case tic6x_operand_mem_deref:
1025c5dff60aSchristos operands_text[op_num] = TRUE;
10267af5a897Schristos reg_side = func_unit_side == 2 ? 'b' : 'a';
10277af5a897Schristos snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val);
1028c5dff60aSchristos break;
1029c5dff60aSchristos
1030c5dff60aSchristos case tic6x_operand_mem_short:
1031c5dff60aSchristos case tic6x_operand_mem_ndw:
1032c5dff60aSchristos mem_base_reg = fld_val;
1033c5dff60aSchristos mem_base_reg_known = TRUE;
1034c5dff60aSchristos break;
1035c5dff60aSchristos
1036c5dff60aSchristos default:
10377af5a897Schristos printf ("opcode %x: unexpected operand form %d for operand #%d",
10387af5a897Schristos opcode, opc->operand_info[op_num].form, op_num);
10397af5a897Schristos abort ();
10407af5a897Schristos }
10417af5a897Schristos break;
10427af5a897Schristos
10437af5a897Schristos case tic6x_coding_reg_ptr:
10447af5a897Schristos switch (opc->operand_info[op_num].form)
10457af5a897Schristos {
10467af5a897Schristos case tic6x_operand_mem_short:
10477af5a897Schristos case tic6x_operand_mem_ndw:
10487af5a897Schristos if (fld_val > 0x3u)
10497af5a897Schristos {
10507af5a897Schristos printf("opcode %x: illegal field value for ptr register of operand #%d (%d)",
10517af5a897Schristos opcode, op_num, fld_val);
10527af5a897Schristos abort ();
10537af5a897Schristos }
10547af5a897Schristos mem_base_reg = 0x4 | fld_val;
10557af5a897Schristos mem_base_reg_known = TRUE;
10567af5a897Schristos break;
10577af5a897Schristos
10587af5a897Schristos default:
10597af5a897Schristos printf ("opcode %x: unexpected operand form %d for operand #%d",
10607af5a897Schristos opcode, opc->operand_info[op_num].form, op_num);
1061c5dff60aSchristos abort ();
1062c5dff60aSchristos }
1063c5dff60aSchristos break;
1064c5dff60aSchristos
1065c5dff60aSchristos case tic6x_coding_areg:
1066c5dff60aSchristos switch (opc->operand_info[op_num].form)
1067c5dff60aSchristos {
1068c5dff60aSchristos case tic6x_operand_areg:
1069c5dff60aSchristos operands_text[op_num] = TRUE;
1070c5dff60aSchristos snprintf (operands[op_num], 24, "b%u",
1071c5dff60aSchristos fld_val ? 15u : 14u);
1072c5dff60aSchristos break;
1073c5dff60aSchristos
1074c5dff60aSchristos case tic6x_operand_mem_long:
1075c5dff60aSchristos mem_base_reg = fld_val ? 15u : 14u;
1076c5dff60aSchristos mem_base_reg_known_long = TRUE;
1077c5dff60aSchristos break;
1078c5dff60aSchristos
1079c5dff60aSchristos default:
10807af5a897Schristos printf ("opcode %x: bad operand form\n", opcode);
1081c5dff60aSchristos abort ();
1082c5dff60aSchristos }
1083c5dff60aSchristos break;
1084c5dff60aSchristos
10857af5a897Schristos case tic6x_coding_mem_offset_minus_one_noscale:
10867af5a897Schristos case tic6x_coding_mem_offset_minus_one:
10877af5a897Schristos fld_val += 1;
10881c468f90Schristos /* Fall through. */
1089c5dff60aSchristos case tic6x_coding_mem_offset_noscale:
10907af5a897Schristos case tic6x_coding_mem_offset:
1091c5dff60aSchristos mem_offset = fld_val;
1092c5dff60aSchristos mem_offset_known = TRUE;
10937af5a897Schristos if (num_bits == 16)
10947af5a897Schristos {
10957af5a897Schristos mem_mode_known = TRUE;
10967af5a897Schristos mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags);
10977af5a897Schristos mem_scaled_known = TRUE;
10987af5a897Schristos mem_scaled = TRUE;
10997af5a897Schristos if (opc->flags & TIC6X_FLAG_INSN16_B15PTR)
11007af5a897Schristos {
11017af5a897Schristos mem_base_reg_known = TRUE;
11027af5a897Schristos mem_base_reg = 15;
11037af5a897Schristos }
11047af5a897Schristos if ( enc->coding_method == tic6x_coding_mem_offset_noscale
11057af5a897Schristos || enc->coding_method == tic6x_coding_mem_offset_noscale )
11067af5a897Schristos mem_scaled = FALSE;
11077af5a897Schristos }
1108c5dff60aSchristos break;
1109c5dff60aSchristos
1110c5dff60aSchristos case tic6x_coding_mem_mode:
1111c5dff60aSchristos mem_mode = fld_val;
1112c5dff60aSchristos mem_mode_known = TRUE;
1113c5dff60aSchristos break;
1114c5dff60aSchristos
1115c5dff60aSchristos case tic6x_coding_scaled:
1116c5dff60aSchristos mem_scaled = fld_val;
1117c5dff60aSchristos mem_scaled_known = TRUE;
1118c5dff60aSchristos break;
1119c5dff60aSchristos
1120c5dff60aSchristos case tic6x_coding_crlo:
1121c5dff60aSchristos crlo = fld_val;
1122c5dff60aSchristos crlo_known = TRUE;
1123c5dff60aSchristos break;
1124c5dff60aSchristos
1125c5dff60aSchristos case tic6x_coding_crhi:
1126c5dff60aSchristos crhi = fld_val;
1127c5dff60aSchristos crhi_known = TRUE;
1128c5dff60aSchristos break;
1129c5dff60aSchristos
1130c5dff60aSchristos case tic6x_coding_fstg:
1131c5dff60aSchristos case tic6x_coding_fcyc:
1132c5dff60aSchristos if (!prev_sploop_found)
1133c5dff60aSchristos {
1134c5dff60aSchristos bfd_vma search_fp_addr = fp_addr;
1135c5dff60aSchristos bfd_vma search_fp_offset = fp_offset;
1136c5dff60aSchristos bfd_boolean search_fp_header_based
1137c5dff60aSchristos = fetch_packet_header_based;
1138c5dff60aSchristos tic6x_fetch_packet_header search_fp_header = header;
1139c5dff60aSchristos unsigned char search_fp[32];
1140c5dff60aSchristos unsigned int search_num_bits;
1141c5dff60aSchristos unsigned int search_opcode;
1142c5dff60aSchristos unsigned int sploop_ii = 0;
1143c5dff60aSchristos int i;
1144c5dff60aSchristos
1145c5dff60aSchristos memcpy (search_fp, fp, 32);
1146c5dff60aSchristos
1147c5dff60aSchristos /* To interpret these bits in an SPKERNEL
1148c5dff60aSchristos instruction, we must find the previous
1149c5dff60aSchristos SPLOOP-family instruction. It may come up to
1150c5dff60aSchristos 48 execute packets earlier. */
1151c5dff60aSchristos for (i = 0; i < 48 * 8; i++)
1152c5dff60aSchristos {
1153c5dff60aSchristos /* Find the previous instruction. */
1154c5dff60aSchristos if (search_fp_offset & 2)
1155c5dff60aSchristos search_fp_offset -= 2;
1156c5dff60aSchristos else if (search_fp_offset >= 4)
1157c5dff60aSchristos {
1158c5dff60aSchristos if (search_fp_header_based
1159c5dff60aSchristos && (search_fp_header.word_compact
1160c5dff60aSchristos [(search_fp_offset >> 2) - 1]))
1161c5dff60aSchristos search_fp_offset -= 2;
1162c5dff60aSchristos else
1163c5dff60aSchristos search_fp_offset -= 4;
1164c5dff60aSchristos }
1165c5dff60aSchristos else
1166c5dff60aSchristos {
1167c5dff60aSchristos search_fp_addr -= 32;
1168c5dff60aSchristos status = info->read_memory_func (search_fp_addr,
1169c5dff60aSchristos search_fp,
1170c5dff60aSchristos 32, info);
1171c5dff60aSchristos if (status)
1172c5dff60aSchristos /* No previous SPLOOP instruction. */
1173c5dff60aSchristos break;
1174c5dff60aSchristos search_fp_header_based
1175c5dff60aSchristos = (tic6x_check_fetch_packet_header
1176c5dff60aSchristos (search_fp, &search_fp_header, info));
1177c5dff60aSchristos if (search_fp_header_based)
1178c5dff60aSchristos search_fp_offset
1179c5dff60aSchristos = search_fp_header.word_compact[6] ? 26 : 24;
1180c5dff60aSchristos else
1181c5dff60aSchristos search_fp_offset = 28;
1182c5dff60aSchristos }
1183c5dff60aSchristos
1184c5dff60aSchristos /* Extract the previous instruction. */
1185c5dff60aSchristos if (search_fp_header_based)
1186c5dff60aSchristos search_num_bits
1187c5dff60aSchristos = (search_fp_header.word_compact[search_fp_offset
1188c5dff60aSchristos >> 2]
1189c5dff60aSchristos ? 16
1190c5dff60aSchristos : 32);
1191c5dff60aSchristos else
1192c5dff60aSchristos search_num_bits = 32;
1193c5dff60aSchristos if (search_num_bits == 16)
1194c5dff60aSchristos {
1195c5dff60aSchristos if (info->endian == BFD_ENDIAN_LITTLE)
1196c5dff60aSchristos search_opcode
1197c5dff60aSchristos = (tic6x_extract_16
11987af5a897Schristos (search_fp + search_fp_offset, &header, info));
1199c5dff60aSchristos else
1200c5dff60aSchristos search_opcode
1201c5dff60aSchristos = (tic6x_extract_16
12027af5a897Schristos (search_fp + (search_fp_offset ^ 2), &header,
1203c5dff60aSchristos info));
1204c5dff60aSchristos }
1205c5dff60aSchristos else
1206c5dff60aSchristos search_opcode
1207c5dff60aSchristos = tic6x_extract_32 (search_fp + search_fp_offset,
1208c5dff60aSchristos info);
1209c5dff60aSchristos
1210c5dff60aSchristos /* Check whether it is an SPLOOP-family
1211c5dff60aSchristos instruction. */
1212c5dff60aSchristos if (search_num_bits == 32
1213c5dff60aSchristos && ((search_opcode & 0x003ffffe) == 0x00038000
1214c5dff60aSchristos || (search_opcode & 0x003ffffe) == 0x0003a000
1215c5dff60aSchristos || ((search_opcode & 0x003ffffe)
1216c5dff60aSchristos == 0x0003e000)))
1217c5dff60aSchristos {
1218c5dff60aSchristos prev_sploop_found = TRUE;
1219c5dff60aSchristos sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
1220c5dff60aSchristos }
1221c5dff60aSchristos else if (search_num_bits == 16
1222c5dff60aSchristos && (search_opcode & 0x3c7e) == 0x0c66)
1223c5dff60aSchristos {
1224c5dff60aSchristos prev_sploop_found = TRUE;
1225c5dff60aSchristos sploop_ii
1226c5dff60aSchristos = (((search_opcode >> 7) & 0x7)
1227c5dff60aSchristos | ((search_opcode >> 11) & 0x8)) + 1;
1228c5dff60aSchristos }
1229c5dff60aSchristos if (prev_sploop_found)
1230c5dff60aSchristos {
1231c5dff60aSchristos if (sploop_ii <= 0)
12327af5a897Schristos {
12337af5a897Schristos printf ("opcode %x: sloop index not found (%d)\n", opcode, sploop_ii);
1234c5dff60aSchristos abort ();
12357af5a897Schristos }
1236c5dff60aSchristos else if (sploop_ii <= 1)
1237c5dff60aSchristos fcyc_bits = 0;
1238c5dff60aSchristos else if (sploop_ii <= 2)
1239c5dff60aSchristos fcyc_bits = 1;
1240c5dff60aSchristos else if (sploop_ii <= 4)
1241c5dff60aSchristos fcyc_bits = 2;
1242c5dff60aSchristos else if (sploop_ii <= 8)
1243c5dff60aSchristos fcyc_bits = 3;
1244c5dff60aSchristos else if (sploop_ii <= 14)
1245c5dff60aSchristos fcyc_bits = 4;
1246c5dff60aSchristos else
1247c5dff60aSchristos prev_sploop_found = FALSE;
1248c5dff60aSchristos }
1249c5dff60aSchristos if (prev_sploop_found)
1250c5dff60aSchristos break;
1251c5dff60aSchristos }
1252c5dff60aSchristos }
1253c5dff60aSchristos if (!prev_sploop_found)
1254c5dff60aSchristos {
1255c5dff60aSchristos operands_ok = FALSE;
1256c5dff60aSchristos operands_text[op_num] = TRUE;
1257c5dff60aSchristos break;
1258c5dff60aSchristos }
12597af5a897Schristos if (fcyc_bits > tic6x_field_width(field))
12607af5a897Schristos {
12617af5a897Schristos printf ("opcode %x: illegal fcyc value (%d)\n", opcode, fcyc_bits);
1262c5dff60aSchristos abort ();
12637af5a897Schristos }
1264c5dff60aSchristos if (enc->coding_method == tic6x_coding_fstg)
1265c5dff60aSchristos {
1266c5dff60aSchristos int i, t;
1267c5dff60aSchristos for (t = 0, i = fcyc_bits; i < 6; i++)
1268c5dff60aSchristos t = (t << 1) | ((fld_val >> i) & 1);
1269c5dff60aSchristos operands_text[op_num] = TRUE;
1270c5dff60aSchristos snprintf (operands[op_num], 24, "%u", t);
1271c5dff60aSchristos }
1272c5dff60aSchristos else
1273c5dff60aSchristos {
1274c5dff60aSchristos operands_text[op_num] = TRUE;
1275c5dff60aSchristos snprintf (operands[op_num], 24, "%u",
1276c5dff60aSchristos fld_val & ((1 << fcyc_bits) - 1));
1277c5dff60aSchristos }
1278c5dff60aSchristos break;
1279c5dff60aSchristos
1280c5dff60aSchristos case tic6x_coding_spmask:
1281c5dff60aSchristos if (fld_val == 0)
1282c5dff60aSchristos spmask_skip_operand = TRUE;
1283c5dff60aSchristos else
1284c5dff60aSchristos {
1285c5dff60aSchristos char *p;
1286c5dff60aSchristos unsigned int i;
1287c5dff60aSchristos
1288c5dff60aSchristos operands_text[op_num] = TRUE;
1289c5dff60aSchristos p = operands[op_num];
1290c5dff60aSchristos for (i = 0; i < 8; i++)
1291c5dff60aSchristos if (fld_val & (1 << i))
1292c5dff60aSchristos {
1293c5dff60aSchristos *p++ = "LSDM"[i/2];
1294c5dff60aSchristos *p++ = '1' + (i & 1);
1295c5dff60aSchristos *p++ = ',';
1296c5dff60aSchristos }
1297c5dff60aSchristos p[-1] = 0;
1298c5dff60aSchristos }
1299c5dff60aSchristos break;
1300c5dff60aSchristos
1301c5dff60aSchristos case tic6x_coding_fu:
1302c5dff60aSchristos case tic6x_coding_data_fu:
1303c5dff60aSchristos case tic6x_coding_xpath:
13047af5a897Schristos case tic6x_coding_rside:
1305c5dff60aSchristos /* Don't relate to operands, so operand number is
1306c5dff60aSchristos meaningless. */
1307c5dff60aSchristos break;
1308c5dff60aSchristos
1309c5dff60aSchristos default:
13107af5a897Schristos printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method);
1311c5dff60aSchristos abort ();
1312c5dff60aSchristos }
1313c5dff60aSchristos
1314c5dff60aSchristos if (mem_base_reg_known_long && mem_offset_known_long)
1315c5dff60aSchristos {
1316c5dff60aSchristos if (operands_text[op_num] || operands_pcrel[op_num])
13177af5a897Schristos {
13187af5a897Schristos printf ("opcode %x: long access but operands already known ?\n", opcode);
1319c5dff60aSchristos abort ();
13207af5a897Schristos }
1321c5dff60aSchristos operands_text[op_num] = TRUE;
1322c5dff60aSchristos snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
1323c5dff60aSchristos mem_offset * opc->operand_info[op_num].size);
1324c5dff60aSchristos }
1325c5dff60aSchristos
1326c5dff60aSchristos if (mem_base_reg_known && mem_offset_known && mem_mode_known
1327c5dff60aSchristos && (mem_scaled_known
1328c5dff60aSchristos || (opc->operand_info[op_num].form
1329c5dff60aSchristos != tic6x_operand_mem_ndw)))
1330c5dff60aSchristos {
1331c5dff60aSchristos char side;
1332c5dff60aSchristos char base[4];
1333c5dff60aSchristos bfd_boolean offset_is_reg;
1334c5dff60aSchristos bfd_boolean offset_scaled;
1335c5dff60aSchristos char offset[4];
1336c5dff60aSchristos char offsetp[6];
1337c5dff60aSchristos
1338c5dff60aSchristos if (operands_text[op_num] || operands_pcrel[op_num])
13397af5a897Schristos {
13407af5a897Schristos printf ("opcode %x: mem access operands already known ?\n", opcode);
1341c5dff60aSchristos abort ();
13427af5a897Schristos }
1343c5dff60aSchristos
1344c5dff60aSchristos side = func_unit_side == 2 ? 'b' : 'a';
1345c5dff60aSchristos snprintf (base, 4, "%c%u", side, mem_base_reg);
1346c5dff60aSchristos
1347c5dff60aSchristos offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
1348c5dff60aSchristos if (offset_is_reg)
1349c5dff60aSchristos {
13507af5a897Schristos
13517af5a897Schristos if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
13527af5a897Schristos {
13537af5a897Schristos reg_base = 16;
13547af5a897Schristos }
13557af5a897Schristos snprintf (offset, 4, "%c%u", side, reg_base + mem_offset);
1356c5dff60aSchristos if (opc->operand_info[op_num].form
1357c5dff60aSchristos == tic6x_operand_mem_ndw)
1358c5dff60aSchristos offset_scaled = mem_scaled ? TRUE : FALSE;
1359c5dff60aSchristos else
1360c5dff60aSchristos offset_scaled = TRUE;
1361c5dff60aSchristos }
1362c5dff60aSchristos else
1363c5dff60aSchristos {
1364c5dff60aSchristos if (opc->operand_info[op_num].form
1365c5dff60aSchristos == tic6x_operand_mem_ndw)
1366c5dff60aSchristos {
1367c5dff60aSchristos offset_scaled = mem_scaled ? TRUE : FALSE;
1368c5dff60aSchristos snprintf (offset, 4, "%u", mem_offset);
1369c5dff60aSchristos }
1370c5dff60aSchristos else
1371c5dff60aSchristos {
1372c5dff60aSchristos offset_scaled = FALSE;
1373c5dff60aSchristos snprintf (offset, 4, "%u",
1374c5dff60aSchristos (mem_offset
1375c5dff60aSchristos * opc->operand_info[op_num].size));
1376c5dff60aSchristos }
1377c5dff60aSchristos }
1378c5dff60aSchristos
1379c5dff60aSchristos if (offset_scaled)
1380c5dff60aSchristos snprintf (offsetp, 6, "[%s]", offset);
1381c5dff60aSchristos else
1382c5dff60aSchristos snprintf (offsetp, 6, "(%s)", offset);
1383c5dff60aSchristos
1384c5dff60aSchristos operands_text[op_num] = TRUE;
1385c5dff60aSchristos switch (mem_mode & ~4u)
1386c5dff60aSchristos {
1387c5dff60aSchristos case 0:
1388c5dff60aSchristos snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
1389c5dff60aSchristos break;
1390c5dff60aSchristos
1391c5dff60aSchristos case 1:
1392c5dff60aSchristos snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
1393c5dff60aSchristos break;
1394c5dff60aSchristos
1395c5dff60aSchristos case 2:
1396c5dff60aSchristos case 3:
1397c5dff60aSchristos operands_ok = FALSE;
1398c5dff60aSchristos break;
1399c5dff60aSchristos
1400c5dff60aSchristos case 8:
1401c5dff60aSchristos snprintf (operands[op_num], 24, "*--%s%s", base,
1402c5dff60aSchristos offsetp);
1403c5dff60aSchristos break;
1404c5dff60aSchristos
1405c5dff60aSchristos case 9:
1406c5dff60aSchristos snprintf (operands[op_num], 24, "*++%s%s", base,
1407c5dff60aSchristos offsetp);
1408c5dff60aSchristos break;
1409c5dff60aSchristos
1410c5dff60aSchristos case 10:
1411c5dff60aSchristos snprintf (operands[op_num], 24, "*%s--%s", base,
1412c5dff60aSchristos offsetp);
1413c5dff60aSchristos break;
1414c5dff60aSchristos
1415c5dff60aSchristos case 11:
1416c5dff60aSchristos snprintf (operands[op_num], 24, "*%s++%s", base,
1417c5dff60aSchristos offsetp);
1418c5dff60aSchristos break;
1419c5dff60aSchristos
1420c5dff60aSchristos default:
14217af5a897Schristos printf ("*** unknown mem_mode : %d \n", mem_mode);
1422c5dff60aSchristos abort ();
1423c5dff60aSchristos }
1424c5dff60aSchristos }
1425c5dff60aSchristos
1426c5dff60aSchristos if (crlo_known && crhi_known)
1427c5dff60aSchristos {
1428c5dff60aSchristos tic6x_rw rw;
1429c5dff60aSchristos tic6x_ctrl_id crid;
1430c5dff60aSchristos
1431c5dff60aSchristos if (operands_text[op_num] || operands_pcrel[op_num])
14327af5a897Schristos {
14337af5a897Schristos printf ("*** abort crlo crli\n");
1434c5dff60aSchristos abort ();
14357af5a897Schristos }
1436c5dff60aSchristos
1437c5dff60aSchristos rw = opc->operand_info[op_num].rw;
1438c5dff60aSchristos if (rw != tic6x_rw_read
1439c5dff60aSchristos && rw != tic6x_rw_write)
14407af5a897Schristos {
14417af5a897Schristos printf ("*** abort rw : %d\n", rw);
1442c5dff60aSchristos abort ();
14437af5a897Schristos }
1444c5dff60aSchristos
1445c5dff60aSchristos for (crid = 0; crid < tic6x_ctrl_max; crid++)
1446c5dff60aSchristos {
1447c5dff60aSchristos if (crlo == tic6x_ctrl_table[crid].crlo
1448c5dff60aSchristos && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
1449c5dff60aSchristos && (rw == tic6x_rw_read
1450c5dff60aSchristos ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
1451c5dff60aSchristos || (tic6x_ctrl_table[crid].rw
1452c5dff60aSchristos == tic6x_rw_read_write))
1453c5dff60aSchristos : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
1454c5dff60aSchristos || (tic6x_ctrl_table[crid].rw
1455c5dff60aSchristos == tic6x_rw_read_write))))
1456c5dff60aSchristos break;
1457c5dff60aSchristos }
1458c5dff60aSchristos if (crid == tic6x_ctrl_max)
1459c5dff60aSchristos {
1460c5dff60aSchristos operands_text[op_num] = TRUE;
1461c5dff60aSchristos operands_ok = FALSE;
1462c5dff60aSchristos }
1463c5dff60aSchristos else
1464c5dff60aSchristos {
1465c5dff60aSchristos operands_text[op_num] = TRUE;
1466c5dff60aSchristos snprintf (operands[op_num], 24, "%s",
1467c5dff60aSchristos tic6x_ctrl_table[crid].name);
1468c5dff60aSchristos }
1469c5dff60aSchristos }
1470c5dff60aSchristos
1471c5dff60aSchristos if (operands_text[op_num] || operands_pcrel[op_num]
1472c5dff60aSchristos || spmask_skip_operand)
1473c5dff60aSchristos break;
1474c5dff60aSchristos }
14757af5a897Schristos /* end for fld_num */
14767af5a897Schristos
1477c5dff60aSchristos if (spmask_skip_operand)
1478c5dff60aSchristos {
1479c5dff60aSchristos /* SPMASK operands are only valid as the single operand
1480c5dff60aSchristos in the opcode table. */
1481c5dff60aSchristos if (num_operands != 1)
14827af5a897Schristos {
14837af5a897Schristos printf ("opcode: %x, num_operands != 1 : %d\n", opcode, num_operands);
1484c5dff60aSchristos abort ();
14857af5a897Schristos }
1486c5dff60aSchristos num_operands = 0;
1487c5dff60aSchristos break;
1488c5dff60aSchristos }
14897af5a897Schristos
1490c5dff60aSchristos /* The operand must by now have been decoded. */
1491c5dff60aSchristos if (!operands_text[op_num] && !operands_pcrel[op_num])
14927af5a897Schristos {
14937af5a897Schristos printf ("opcode: %x, operand #%d not decoded\n", opcode, op_num);
1494c5dff60aSchristos abort ();
1495c5dff60aSchristos }
14967af5a897Schristos }
14977af5a897Schristos /* end for op_num */
1498c5dff60aSchristos
1499c5dff60aSchristos if (!operands_ok)
1500c5dff60aSchristos continue;
1501c5dff60aSchristos
1502c5dff60aSchristos info->bytes_per_chunk = num_bits / 8;
15037af5a897Schristos info->fprintf_func (info->stream, "%s", parallel);
15047af5a897Schristos info->fprintf_func (info->stream, "%s%s%s", cond, opc->name,
15057af5a897Schristos func_unit);
1506c5dff60aSchristos for (op_num = 0; op_num < num_operands; op_num++)
1507c5dff60aSchristos {
1508c5dff60aSchristos info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
1509c5dff60aSchristos if (operands_pcrel[op_num])
1510c5dff60aSchristos info->print_address_func (operands_addresses[op_num], info);
1511c5dff60aSchristos else
1512c5dff60aSchristos info->fprintf_func (info->stream, "%s", operands[op_num]);
1513c5dff60aSchristos }
1514c5dff60aSchristos if (fetch_packet_header_based && header.prot)
1515c5dff60aSchristos info->fprintf_func (info->stream, " || nop 5");
1516c5dff60aSchristos
1517c5dff60aSchristos return num_bits / 8;
1518c5dff60aSchristos }
1519c5dff60aSchristos
1520c5dff60aSchristos info->bytes_per_chunk = num_bits / 8;
1521c5dff60aSchristos info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
1522c5dff60aSchristos (int) num_bits / 4, opcode);
1523c5dff60aSchristos return num_bits / 8;
1524c5dff60aSchristos }
1525