tic6x-dis.c revision 1.1.1.6 1 1.1 christos /* TI C6X disassembler.
2 1.1.1.6 christos Copyright (C) 2010-2017 Free Software Foundation, Inc.
3 1.1 christos Contributed by Joseph Myers <joseph (at) codesourcery.com>
4 1.1 christos Bernd Schmidt <bernds (at) codesourcery.com>
5 1.1 christos
6 1.1 christos This file is part of libopcodes.
7 1.1 christos
8 1.1 christos This library is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3 of the License, or
11 1.1 christos (at your option) any later version.
12 1.1 christos
13 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
14 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 1.1 christos License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program; if not, write to the Free Software
20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 1.1 christos MA 02110-1301, USA. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include "dis-asm.h"
25 1.1 christos #include "opcode/tic6x.h"
26 1.1 christos #include "libiberty.h"
27 1.1 christos
28 1.1 christos /* Define the instruction format table. */
29 1.1 christos const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] =
30 1.1 christos {
31 1.1 christos #define FMT(name, num_bits, cst_bits, mask, fields) \
32 1.1 christos { num_bits, cst_bits, mask, fields },
33 1.1 christos #include "opcode/tic6x-insn-formats.h"
34 1.1 christos #undef FMT
35 1.1 christos };
36 1.1 christos
37 1.1 christos /* Define the control register table. */
38 1.1 christos const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] =
39 1.1 christos {
40 1.1 christos #define CTRL(name, isa, rw, crlo, crhi_mask) \
41 1.1 christos { \
42 1.1 christos STRINGX(name), \
43 1.1 christos CONCAT2(TIC6X_INSN_,isa), \
44 1.1 christos CONCAT2(tic6x_rw_,rw), \
45 1.1 christos crlo, \
46 1.1 christos crhi_mask \
47 1.1 christos },
48 1.1 christos #include "opcode/tic6x-control-registers.h"
49 1.1 christos #undef CTRL
50 1.1 christos };
51 1.1 christos
52 1.1 christos /* Define the opcode table. */
53 1.1 christos const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] =
54 1.1 christos {
55 1.1.1.2 christos #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \
56 1.1.1.2 christos { \
57 1.1.1.2 christos STRINGX(name), \
58 1.1.1.2 christos CONCAT2(tic6x_func_unit_,func_unit), \
59 1.1.1.2 christos CONCAT3(tic6x_insn_format,_,format), \
60 1.1.1.2 christos CONCAT2(tic6x_pipeline_,type), \
61 1.1.1.2 christos CONCAT2(TIC6X_INSN_,isa), \
62 1.1.1.2 christos flags, \
63 1.1.1.2 christos fixed, \
64 1.1.1.2 christos ops, \
65 1.1.1.2 christos var \
66 1.1.1.2 christos },
67 1.1.1.2 christos #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
68 1.1.1.2 christos { \
69 1.1.1.2 christos STRINGX(name), \
70 1.1.1.2 christos CONCAT2(tic6x_func_unit_,func_unit), \
71 1.1.1.2 christos CONCAT3(tic6x_insn_format,_,format), \
72 1.1.1.2 christos CONCAT2(tic6x_pipeline_,type), \
73 1.1.1.2 christos CONCAT2(TIC6X_INSN_,isa), \
74 1.1.1.2 christos flags, \
75 1.1.1.2 christos fixed, \
76 1.1.1.2 christos ops, \
77 1.1.1.2 christos var \
78 1.1.1.2 christos },
79 1.1 christos #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \
80 1.1 christos { \
81 1.1 christos STRINGX(name), \
82 1.1 christos CONCAT2(tic6x_func_unit_,func_unit), \
83 1.1 christos CONCAT4(tic6x_insn_format_,func_unit,_,format), \
84 1.1 christos CONCAT2(tic6x_pipeline_,type), \
85 1.1 christos CONCAT2(TIC6X_INSN_,isa), \
86 1.1 christos flags, \
87 1.1 christos fixed, \
88 1.1 christos ops, \
89 1.1 christos var \
90 1.1 christos },
91 1.1 christos #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \
92 1.1 christos { \
93 1.1 christos STRINGX(name), \
94 1.1 christos CONCAT2(tic6x_func_unit_,func_unit), \
95 1.1 christos CONCAT4(tic6x_insn_format_,func_unit,_,format), \
96 1.1 christos CONCAT2(tic6x_pipeline_,type), \
97 1.1 christos CONCAT2(TIC6X_INSN_,isa), \
98 1.1 christos flags, \
99 1.1 christos fixed, \
100 1.1 christos ops, \
101 1.1 christos var \
102 1.1 christos },
103 1.1 christos #include "opcode/tic6x-opcode-table.h"
104 1.1 christos #undef INSN
105 1.1 christos #undef INSNE
106 1.1.1.2 christos #undef INSNU
107 1.1.1.2 christos #undef INSNUE
108 1.1 christos };
109 1.1 christos
110 1.1 christos /* If instruction format FMT has a field FIELD, return a pointer to
111 1.1 christos the description of that field; otherwise return NULL. */
112 1.1 christos
113 1.1 christos const tic6x_insn_field *
114 1.1 christos tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field)
115 1.1 christos {
116 1.1 christos unsigned int f;
117 1.1 christos
118 1.1 christos for (f = 0; f < fmt->num_fields; f++)
119 1.1 christos if (fmt->fields[f].field_id == field)
120 1.1 christos return &fmt->fields[f];
121 1.1 christos
122 1.1 christos return NULL;
123 1.1 christos }
124 1.1 christos
125 1.1.1.2 christos /* Extract the field width. */
126 1.1.1.2 christos
127 1.1.1.2 christos static unsigned int
128 1.1.1.2 christos tic6x_field_width (const tic6x_insn_field *field)
129 1.1.1.2 christos {
130 1.1.1.2 christos unsigned int i;
131 1.1.1.2 christos unsigned int width = 0;
132 1.1.1.2 christos
133 1.1.1.2 christos if (!field->num_bitfields)
134 1.1.1.2 christos return field->bitfields[0].width;
135 1.1.1.2 christos
136 1.1.1.2 christos for (i = 0 ; i < field->num_bitfields ; i++)
137 1.1.1.2 christos width += field->bitfields[i].width;
138 1.1.1.2 christos
139 1.1.1.2 christos return width;
140 1.1.1.2 christos }
141 1.1.1.2 christos
142 1.1 christos /* Extract the bits corresponding to FIELD from OPCODE. */
143 1.1 christos
144 1.1 christos static unsigned int
145 1.1 christos tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field)
146 1.1 christos {
147 1.1.1.2 christos unsigned int i;
148 1.1.1.2 christos unsigned int val = 0;
149 1.1.1.2 christos
150 1.1.1.2 christos if (!field->num_bitfields)
151 1.1.1.2 christos return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1);
152 1.1.1.2 christos
153 1.1.1.2 christos for (i = 0 ; i < field->num_bitfields ; i++)
154 1.1.1.2 christos val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1))
155 1.1.1.2 christos << field->bitfields[i].pos;
156 1.1.1.2 christos
157 1.1.1.2 christos return val;
158 1.1 christos }
159 1.1 christos
160 1.1 christos /* Extract a 32-bit value read from the instruction stream. */
161 1.1 christos
162 1.1 christos static unsigned int
163 1.1 christos tic6x_extract_32 (unsigned char *p, struct disassemble_info *info)
164 1.1 christos {
165 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE)
166 1.1 christos return (p[0]) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
167 1.1 christos else
168 1.1 christos return (p[3]) | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
169 1.1 christos }
170 1.1 christos
171 1.1 christos /* Extract a 16-bit value read from the instruction stream. */
172 1.1 christos
173 1.1 christos static unsigned int
174 1.1.1.2 christos tic6x_extract_16 (unsigned char *p, tic6x_fetch_packet_header *header,
175 1.1.1.2 christos struct disassemble_info *info)
176 1.1 christos {
177 1.1.1.2 christos unsigned int op16;
178 1.1.1.2 christos
179 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE)
180 1.1.1.2 christos op16 = (p[0]) | (p[1] << 8);
181 1.1 christos else
182 1.1.1.2 christos op16 = (p[1]) | (p[0] << 8);
183 1.1.1.2 christos op16 |= (header->sat << TIC6X_COMPACT_SAT_POS);
184 1.1.1.2 christos op16 |= (header->br << TIC6X_COMPACT_BR_POS);
185 1.1.1.2 christos op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS);
186 1.1.1.2 christos return op16;
187 1.1 christos }
188 1.1 christos
189 1.1 christos /* FP points to a fetch packet. Return whether it is header-based; if
190 1.1 christos it is, fill in HEADER. */
191 1.1 christos
192 1.1 christos static bfd_boolean
193 1.1 christos tic6x_check_fetch_packet_header (unsigned char *fp,
194 1.1 christos tic6x_fetch_packet_header *header,
195 1.1 christos struct disassemble_info *info)
196 1.1 christos {
197 1.1 christos int i;
198 1.1 christos
199 1.1 christos header->header = tic6x_extract_32 (fp + 28, info);
200 1.1.1.2 christos
201 1.1 christos if ((header->header & 0xf0000000) != 0xe0000000)
202 1.1.1.2 christos {
203 1.1.1.2 christos header->prot = 0;
204 1.1.1.2 christos header->rs = 0;
205 1.1.1.2 christos header->dsz = 0;
206 1.1.1.2 christos header->br = 0;
207 1.1.1.2 christos header->sat = 0;
208 1.1.1.2 christos for (i = 0; i < 7; i++)
209 1.1.1.2 christos header->word_compact[i] = FALSE;
210 1.1.1.2 christos for (i = 0; i < 14; i++)
211 1.1.1.2 christos header->p_bits[i] = FALSE;
212 1.1.1.2 christos return FALSE;
213 1.1.1.2 christos }
214 1.1 christos
215 1.1 christos for (i = 0; i < 7; i++)
216 1.1 christos header->word_compact[i]
217 1.1 christos = (header->header & (1u << (21 + i))) ? TRUE : FALSE;
218 1.1 christos
219 1.1 christos header->prot = (header->header & (1u << 20)) ? TRUE : FALSE;
220 1.1 christos header->rs = (header->header & (1u << 19)) ? TRUE : FALSE;
221 1.1 christos header->dsz = (header->header >> 16) & 0x7;
222 1.1 christos header->br = (header->header & (1u << 15)) ? TRUE : FALSE;
223 1.1 christos header->sat = (header->header & (1u << 14)) ? TRUE : FALSE;
224 1.1 christos
225 1.1 christos for (i = 0; i < 14; i++)
226 1.1 christos header->p_bits[i]
227 1.1 christos = (header->header & (1u << i)) ? TRUE : FALSE;
228 1.1 christos
229 1.1 christos return TRUE;
230 1.1 christos }
231 1.1 christos
232 1.1 christos /* Disassemble the instruction at ADDR and print it using
233 1.1 christos INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes
234 1.1 christos consumed. */
235 1.1 christos
236 1.1 christos int
237 1.1 christos print_insn_tic6x (bfd_vma addr, struct disassemble_info *info)
238 1.1 christos {
239 1.1 christos int status;
240 1.1 christos bfd_vma fp_addr;
241 1.1 christos bfd_vma fp_offset;
242 1.1 christos unsigned char fp[32];
243 1.1 christos unsigned int opcode;
244 1.1 christos tic6x_opcode_id opcode_id;
245 1.1 christos bfd_boolean fetch_packet_header_based;
246 1.1 christos tic6x_fetch_packet_header header;
247 1.1 christos unsigned int num_bits;
248 1.1 christos bfd_boolean bad_offset = FALSE;
249 1.1 christos
250 1.1 christos fp_offset = addr & 0x1f;
251 1.1 christos fp_addr = addr - fp_offset;
252 1.1.1.4 christos /* Read in a block of instructions. Since there might be a
253 1.1.1.4 christos symbol in the middle of this block, disable stop_vma. */
254 1.1.1.4 christos info->stop_vma = 0;
255 1.1 christos status = info->read_memory_func (fp_addr, fp, 32, info);
256 1.1 christos if (status)
257 1.1 christos {
258 1.1 christos info->memory_error_func (status, addr, info);
259 1.1 christos return -1;
260 1.1 christos }
261 1.1 christos
262 1.1 christos fetch_packet_header_based
263 1.1 christos = tic6x_check_fetch_packet_header (fp, &header, info);
264 1.1 christos if (fetch_packet_header_based)
265 1.1 christos {
266 1.1 christos if (fp_offset & 0x1)
267 1.1 christos bad_offset = TRUE;
268 1.1 christos if ((fp_offset & 0x3) && (fp_offset >= 28
269 1.1 christos || !header.word_compact[fp_offset >> 2]))
270 1.1 christos bad_offset = TRUE;
271 1.1 christos if (fp_offset == 28)
272 1.1 christos {
273 1.1 christos info->bytes_per_chunk = 4;
274 1.1 christos info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>",
275 1.1 christos header.header);
276 1.1 christos return 4;
277 1.1 christos }
278 1.1 christos num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32);
279 1.1 christos }
280 1.1 christos else
281 1.1 christos {
282 1.1 christos num_bits = 32;
283 1.1 christos if (fp_offset & 0x3)
284 1.1 christos bad_offset = TRUE;
285 1.1 christos }
286 1.1 christos
287 1.1 christos if (bad_offset)
288 1.1 christos {
289 1.1 christos info->bytes_per_chunk = 1;
290 1.1 christos info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]);
291 1.1 christos return 1;
292 1.1 christos }
293 1.1 christos
294 1.1 christos if (num_bits == 16)
295 1.1 christos {
296 1.1 christos /* The least-significant part of a 32-bit word comes logically
297 1.1 christos before the most-significant part. For big-endian, follow the
298 1.1 christos TI assembler in showing instructions in logical order by
299 1.1 christos pretending that the two halves of the word are in opposite
300 1.1 christos locations to where they actually are. */
301 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE)
302 1.1.1.2 christos opcode = tic6x_extract_16 (fp + fp_offset, &header, info);
303 1.1 christos else
304 1.1.1.2 christos opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info);
305 1.1 christos }
306 1.1 christos else
307 1.1 christos opcode = tic6x_extract_32 (fp + fp_offset, info);
308 1.1 christos
309 1.1 christos for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++)
310 1.1 christos {
311 1.1 christos const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id];
312 1.1 christos const tic6x_insn_format *const fmt
313 1.1 christos = &tic6x_insn_format_table[opc->format];
314 1.1 christos const tic6x_insn_field *creg_field;
315 1.1 christos bfd_boolean p_bit;
316 1.1 christos const char *parallel;
317 1.1 christos const char *cond = "";
318 1.1 christos const char *func_unit;
319 1.1.1.6 christos char func_unit_buf[8];
320 1.1 christos unsigned int func_unit_side = 0;
321 1.1 christos unsigned int func_unit_data_side = 0;
322 1.1 christos unsigned int func_unit_cross = 0;
323 1.1.1.2 christos unsigned int t_val = 0;
324 1.1 christos /* The maximum length of the text of a non-PC-relative operand
325 1.1 christos is 24 bytes (SPMASK masking all eight functional units, with
326 1.1 christos separating commas and trailing NUL). */
327 1.1 christos char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } };
328 1.1 christos bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 };
329 1.1 christos bfd_boolean operands_text[TIC6X_MAX_OPERANDS] = { FALSE };
330 1.1 christos bfd_boolean operands_pcrel[TIC6X_MAX_OPERANDS] = { FALSE };
331 1.1 christos unsigned int fix;
332 1.1 christos unsigned int num_operands;
333 1.1 christos unsigned int op_num;
334 1.1 christos bfd_boolean fixed_ok;
335 1.1 christos bfd_boolean operands_ok;
336 1.1.1.2 christos bfd_boolean have_t = FALSE;
337 1.1 christos
338 1.1 christos if (opc->flags & TIC6X_FLAG_MACRO)
339 1.1 christos continue;
340 1.1 christos if (fmt->num_bits != num_bits)
341 1.1 christos continue;
342 1.1 christos if ((opcode & fmt->mask) != fmt->cst_bits)
343 1.1 christos continue;
344 1.1 christos
345 1.1 christos /* If the format has a creg field, it is only a candidate for a
346 1.1 christos match if the creg and z fields have values indicating a valid
347 1.1 christos condition; reserved values indicate either an instruction
348 1.1 christos format without a creg field, or an invalid instruction. */
349 1.1 christos creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg);
350 1.1 christos if (creg_field)
351 1.1 christos {
352 1.1 christos const tic6x_insn_field *z_field;
353 1.1 christos unsigned int creg_value, z_value;
354 1.1 christos static const char *const conds[8][2] =
355 1.1 christos {
356 1.1 christos { "", NULL },
357 1.1 christos { "[b0] ", "[!b0] " },
358 1.1 christos { "[b1] ", "[!b1] " },
359 1.1 christos { "[b2] ", "[!b2] " },
360 1.1 christos { "[a1] ", "[!a1] " },
361 1.1 christos { "[a2] ", "[!a2] " },
362 1.1 christos { "[a0] ", "[!a0] " },
363 1.1 christos { NULL, NULL }
364 1.1 christos };
365 1.1 christos
366 1.1 christos /* A creg field is not meaningful without a z field, so if
367 1.1 christos the z field is not present this is an error in the format
368 1.1 christos table. */
369 1.1 christos z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
370 1.1 christos if (!z_field)
371 1.1.1.2 christos {
372 1.1.1.2 christos printf ("*** opcode %x: missing z field", opcode);
373 1.1.1.2 christos abort ();
374 1.1.1.2 christos }
375 1.1 christos
376 1.1 christos creg_value = tic6x_field_bits (opcode, creg_field);
377 1.1 christos z_value = tic6x_field_bits (opcode, z_field);
378 1.1 christos cond = conds[creg_value][z_value];
379 1.1 christos if (cond == NULL)
380 1.1 christos continue;
381 1.1 christos }
382 1.1 christos
383 1.1.1.2 christos if (opc->flags & TIC6X_FLAG_INSN16_SPRED)
384 1.1.1.2 christos {
385 1.1.1.2 christos const tic6x_insn_field *cc_field;
386 1.1.1.2 christos unsigned int s_value = 0;
387 1.1.1.2 christos unsigned int z_value = 0;
388 1.1.1.2 christos bfd_boolean cond_known = FALSE;
389 1.1.1.2 christos static const char *const conds[2][2] =
390 1.1.1.2 christos {
391 1.1.1.2 christos { "[a0] ", "[!a0] " },
392 1.1.1.2 christos { "[b0] ", "[!b0] " }
393 1.1.1.2 christos };
394 1.1.1.2 christos
395 1.1.1.2 christos cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc);
396 1.1.1.2 christos
397 1.1.1.2 christos if (cc_field)
398 1.1.1.2 christos {
399 1.1.1.2 christos unsigned int cc_value;
400 1.1.1.2 christos
401 1.1.1.2 christos cc_value = tic6x_field_bits (opcode, cc_field);
402 1.1.1.2 christos s_value = (cc_value & 0x2) >> 1;
403 1.1.1.2 christos z_value = (cc_value & 0x1);
404 1.1.1.2 christos cond_known = TRUE;
405 1.1.1.2 christos }
406 1.1.1.2 christos else
407 1.1.1.2 christos {
408 1.1.1.2 christos const tic6x_insn_field *z_field;
409 1.1.1.2 christos const tic6x_insn_field *s_field;
410 1.1.1.2 christos
411 1.1.1.2 christos s_field = tic6x_field_from_fmt (fmt, tic6x_field_s);
412 1.1.1.2 christos
413 1.1.1.2 christos if (!s_field)
414 1.1.1.2 christos {
415 1.1.1.2 christos printf ("opcode %x: missing compact insn predicate register field (s field)\n",
416 1.1.1.2 christos opcode);
417 1.1.1.2 christos abort ();
418 1.1.1.2 christos }
419 1.1.1.2 christos s_value = tic6x_field_bits (opcode, s_field);
420 1.1.1.2 christos z_field = tic6x_field_from_fmt (fmt, tic6x_field_z);
421 1.1.1.2 christos if (!z_field)
422 1.1.1.2 christos {
423 1.1.1.2 christos printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode);
424 1.1.1.2 christos abort ();
425 1.1.1.2 christos }
426 1.1.1.2 christos
427 1.1.1.2 christos z_value = tic6x_field_bits (opcode, z_field);
428 1.1.1.2 christos cond_known = TRUE;
429 1.1.1.2 christos }
430 1.1.1.2 christos
431 1.1.1.2 christos if (!cond_known)
432 1.1.1.2 christos {
433 1.1.1.2 christos printf ("opcode %x: unspecified ompact insn predicate\n", opcode);
434 1.1.1.2 christos abort ();
435 1.1.1.2 christos }
436 1.1.1.2 christos cond = conds[s_value][z_value];
437 1.1.1.2 christos }
438 1.1.1.2 christos
439 1.1 christos /* All fixed fields must have matching values; all fields with
440 1.1 christos restricted ranges must have values within those ranges. */
441 1.1 christos fixed_ok = TRUE;
442 1.1 christos for (fix = 0; fix < opc->num_fixed_fields; fix++)
443 1.1 christos {
444 1.1 christos unsigned int field_bits;
445 1.1 christos const tic6x_insn_field *const field
446 1.1 christos = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id);
447 1.1 christos
448 1.1 christos if (!field)
449 1.1.1.2 christos {
450 1.1.1.2 christos printf ("opcode %x: missing field #%d for FIX #%d\n",
451 1.1.1.2 christos opcode, opc->fixed_fields[fix].field_id, fix);
452 1.1.1.2 christos abort ();
453 1.1.1.2 christos }
454 1.1.1.2 christos
455 1.1 christos field_bits = tic6x_field_bits (opcode, field);
456 1.1 christos if (field_bits < opc->fixed_fields[fix].min_val
457 1.1 christos || field_bits > opc->fixed_fields[fix].max_val)
458 1.1 christos {
459 1.1 christos fixed_ok = FALSE;
460 1.1 christos break;
461 1.1 christos }
462 1.1 christos }
463 1.1 christos if (!fixed_ok)
464 1.1 christos continue;
465 1.1 christos
466 1.1 christos /* The instruction matches. */
467 1.1 christos
468 1.1 christos /* The p-bit indicates whether this instruction is in parallel
469 1.1 christos with the *next* instruction, whereas the parallel bars
470 1.1 christos indicate the instruction is in parallel with the *previous*
471 1.1 christos instruction. Thus, we must find the p-bit for the previous
472 1.1 christos instruction. */
473 1.1 christos if (num_bits == 16 && (fp_offset & 0x2) == 2)
474 1.1 christos {
475 1.1 christos /* This is the logically second (most significant; second in
476 1.1 christos fp_offset terms because fp_offset relates to logical not
477 1.1 christos physical addresses) instruction of a compact pair; find
478 1.1 christos the p-bit for the first (least significant). */
479 1.1 christos p_bit = header.p_bits[(fp_offset >> 2) << 1];
480 1.1 christos }
481 1.1 christos else if (fp_offset >= 4)
482 1.1 christos {
483 1.1 christos /* Find the last instruction of the previous word in this
484 1.1 christos fetch packet. For compact instructions, this is the most
485 1.1 christos significant 16 bits. */
486 1.1 christos if (fetch_packet_header_based
487 1.1 christos && header.word_compact[(fp_offset >> 2) - 1])
488 1.1 christos p_bit = header.p_bits[(fp_offset >> 1) - 1];
489 1.1 christos else
490 1.1 christos {
491 1.1 christos unsigned int prev_opcode
492 1.1 christos = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info);
493 1.1 christos p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
494 1.1 christos }
495 1.1 christos }
496 1.1 christos else
497 1.1 christos {
498 1.1 christos /* Find the last instruction of the previous fetch
499 1.1 christos packet. */
500 1.1 christos unsigned char fp_prev[32];
501 1.1.1.2 christos
502 1.1 christos status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info);
503 1.1 christos if (status)
504 1.1 christos /* No previous instruction to be parallel with. */
505 1.1 christos p_bit = FALSE;
506 1.1 christos else
507 1.1 christos {
508 1.1 christos bfd_boolean prev_header_based;
509 1.1 christos tic6x_fetch_packet_header prev_header;
510 1.1 christos
511 1.1 christos prev_header_based
512 1.1 christos = tic6x_check_fetch_packet_header (fp_prev, &prev_header, info);
513 1.1.1.6 christos if (prev_header_based)
514 1.1.1.6 christos {
515 1.1.1.6 christos if (prev_header.word_compact[6])
516 1.1.1.6 christos p_bit = prev_header.p_bits[13];
517 1.1.1.6 christos else
518 1.1.1.6 christos {
519 1.1.1.6 christos unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 24,
520 1.1.1.6 christos info);
521 1.1.1.6 christos p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
522 1.1.1.6 christos }
523 1.1.1.6 christos }
524 1.1 christos else
525 1.1 christos {
526 1.1 christos unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28,
527 1.1 christos info);
528 1.1 christos p_bit = (prev_opcode & 0x1) ? TRUE : FALSE;
529 1.1 christos }
530 1.1 christos }
531 1.1 christos }
532 1.1 christos parallel = p_bit ? "|| " : "";
533 1.1 christos
534 1.1 christos if (opc->func_unit == tic6x_func_unit_nfu)
535 1.1 christos func_unit = "";
536 1.1 christos else
537 1.1 christos {
538 1.1 christos unsigned int fld_num;
539 1.1 christos char func_unit_char;
540 1.1 christos const char *data_str;
541 1.1 christos bfd_boolean have_areg = FALSE;
542 1.1 christos bfd_boolean have_cross = FALSE;
543 1.1 christos
544 1.1 christos func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0;
545 1.1 christos func_unit_cross = 0;
546 1.1 christos func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0;
547 1.1 christos
548 1.1 christos for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
549 1.1 christos {
550 1.1 christos const tic6x_coding_field *const enc = &opc->variable_fields[fld_num];
551 1.1 christos const tic6x_insn_field *field;
552 1.1 christos unsigned int fld_val;
553 1.1 christos
554 1.1 christos field = tic6x_field_from_fmt (fmt, enc->field_id);
555 1.1.1.2 christos
556 1.1 christos if (!field)
557 1.1.1.2 christos {
558 1.1.1.2 christos printf ("opcode %x: could not retrieve field (field_id:%d)\n",
559 1.1.1.2 christos opcode, fld_num);
560 1.1.1.2 christos abort ();
561 1.1.1.2 christos }
562 1.1.1.2 christos
563 1.1 christos fld_val = tic6x_field_bits (opcode, field);
564 1.1.1.2 christos
565 1.1 christos switch (enc->coding_method)
566 1.1 christos {
567 1.1 christos case tic6x_coding_fu:
568 1.1 christos /* The side must be specified exactly once. */
569 1.1 christos if (func_unit_side)
570 1.1.1.2 christos {
571 1.1.1.2 christos printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
572 1.1.1.2 christos opcode, fld_num);
573 1.1.1.2 christos abort ();
574 1.1.1.2 christos }
575 1.1 christos func_unit_side = (fld_val ? 2 : 1);
576 1.1 christos break;
577 1.1 christos
578 1.1 christos case tic6x_coding_data_fu:
579 1.1 christos /* The data side must be specified exactly once. */
580 1.1 christos if (func_unit_data_side)
581 1.1.1.2 christos {
582 1.1.1.2 christos printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n",
583 1.1.1.2 christos opcode, fld_num);
584 1.1.1.2 christos abort ();
585 1.1.1.2 christos }
586 1.1 christos func_unit_data_side = (fld_val ? 2 : 1);
587 1.1 christos break;
588 1.1 christos
589 1.1 christos case tic6x_coding_xpath:
590 1.1 christos /* Cross path use must be specified exactly
591 1.1 christos once. */
592 1.1 christos if (have_cross)
593 1.1.1.2 christos {
594 1.1.1.2 christos printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n",
595 1.1.1.2 christos opcode, fld_num);
596 1.1.1.2 christos abort ();
597 1.1.1.2 christos }
598 1.1 christos have_cross = TRUE;
599 1.1 christos func_unit_cross = fld_val;
600 1.1 christos break;
601 1.1 christos
602 1.1.1.2 christos case tic6x_coding_rside:
603 1.1.1.2 christos /* If the format has a t field, use it for src/dst register side. */
604 1.1.1.2 christos have_t = TRUE;
605 1.1.1.2 christos t_val = fld_val;
606 1.1.1.2 christos func_unit_data_side = (t_val ? 2 : 1);
607 1.1.1.2 christos break;
608 1.1.1.2 christos
609 1.1 christos case tic6x_coding_areg:
610 1.1 christos have_areg = TRUE;
611 1.1 christos break;
612 1.1 christos
613 1.1 christos default:
614 1.1 christos /* Don't relate to functional units. */
615 1.1 christos break;
616 1.1 christos }
617 1.1 christos }
618 1.1 christos
619 1.1 christos /* The side of the functional unit used must now have been
620 1.1 christos determined either from the flags or from an instruction
621 1.1 christos field. */
622 1.1 christos if (func_unit_side != 1 && func_unit_side != 2)
623 1.1.1.2 christos {
624 1.1.1.2 christos printf ("opcode %x: func_unit_side is not encoded!\n", opcode);
625 1.1.1.2 christos abort ();
626 1.1.1.2 christos }
627 1.1 christos
628 1.1 christos /* Cross paths are not applicable when sides are specified
629 1.1 christos for both address and data paths. */
630 1.1 christos if (func_unit_data_side && have_cross)
631 1.1.1.2 christos {
632 1.1.1.2 christos printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n",
633 1.1.1.2 christos opcode);
634 1.1.1.2 christos abort ();
635 1.1.1.2 christos }
636 1.1 christos
637 1.1 christos /* Separate address and data paths are only applicable for
638 1.1 christos the D unit. */
639 1.1 christos if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d)
640 1.1.1.2 christos {
641 1.1.1.2 christos printf ("opcode %x: separate address and data paths only applicable for D unit!\n",
642 1.1.1.2 christos opcode);
643 1.1.1.2 christos abort ();
644 1.1.1.2 christos }
645 1.1 christos
646 1.1 christos /* If an address register is being used but in ADDA rather
647 1.1 christos than a load or store, it uses a cross path for side-A
648 1.1 christos instructions, and the cross path use is not specified by
649 1.1 christos an instruction field. */
650 1.1 christos if (have_areg && !func_unit_data_side)
651 1.1 christos {
652 1.1 christos if (have_cross)
653 1.1.1.2 christos {
654 1.1.1.2 christos printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode);
655 1.1.1.2 christos abort ();
656 1.1.1.2 christos }
657 1.1 christos func_unit_cross = (func_unit_side == 1 ? TRUE : FALSE);
658 1.1 christos }
659 1.1 christos
660 1.1 christos switch (opc->func_unit)
661 1.1 christos {
662 1.1 christos case tic6x_func_unit_d:
663 1.1 christos func_unit_char = 'D';
664 1.1 christos break;
665 1.1 christos
666 1.1 christos case tic6x_func_unit_l:
667 1.1 christos func_unit_char = 'L';
668 1.1 christos break;
669 1.1 christos
670 1.1 christos case tic6x_func_unit_m:
671 1.1 christos func_unit_char = 'M';
672 1.1 christos break;
673 1.1 christos
674 1.1 christos case tic6x_func_unit_s:
675 1.1 christos func_unit_char = 'S';
676 1.1 christos break;
677 1.1 christos
678 1.1 christos default:
679 1.1.1.2 christos printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit);
680 1.1 christos abort ();
681 1.1 christos }
682 1.1 christos
683 1.1 christos switch (func_unit_data_side)
684 1.1 christos {
685 1.1 christos case 0:
686 1.1 christos data_str = "";
687 1.1 christos break;
688 1.1 christos
689 1.1 christos case 1:
690 1.1 christos data_str = "T1";
691 1.1 christos break;
692 1.1 christos
693 1.1 christos case 2:
694 1.1 christos data_str = "T2";
695 1.1 christos break;
696 1.1 christos
697 1.1 christos default:
698 1.1.1.2 christos printf ("opcode %x: illegal data func_unit specifier %d\n",
699 1.1.1.2 christos opcode, func_unit_data_side);
700 1.1 christos abort ();
701 1.1 christos }
702 1.1 christos
703 1.1.1.2 christos if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1)
704 1.1.1.2 christos func_unit_cross = 1;
705 1.1.1.2 christos
706 1.1.1.6 christos snprintf (func_unit_buf, sizeof func_unit_buf, " .%c%u%s%s",
707 1.1.1.6 christos func_unit_char, func_unit_side,
708 1.1.1.6 christos (func_unit_cross ? "X" : ""), data_str);
709 1.1 christos func_unit = func_unit_buf;
710 1.1 christos }
711 1.1 christos
712 1.1 christos /* For each operand there must be one or more fields set based
713 1.1 christos on that operand, that can together be used to derive the
714 1.1 christos operand value. */
715 1.1 christos operands_ok = TRUE;
716 1.1 christos num_operands = opc->num_operands;
717 1.1 christos for (op_num = 0; op_num < num_operands; op_num++)
718 1.1 christos {
719 1.1 christos unsigned int fld_num;
720 1.1 christos unsigned int mem_base_reg = 0;
721 1.1 christos bfd_boolean mem_base_reg_known = FALSE;
722 1.1 christos bfd_boolean mem_base_reg_known_long = FALSE;
723 1.1 christos unsigned int mem_offset = 0;
724 1.1 christos bfd_boolean mem_offset_known = FALSE;
725 1.1 christos bfd_boolean mem_offset_known_long = FALSE;
726 1.1 christos unsigned int mem_mode = 0;
727 1.1 christos bfd_boolean mem_mode_known = FALSE;
728 1.1 christos unsigned int mem_scaled = 0;
729 1.1 christos bfd_boolean mem_scaled_known = FALSE;
730 1.1 christos unsigned int crlo = 0;
731 1.1 christos bfd_boolean crlo_known = FALSE;
732 1.1 christos unsigned int crhi = 0;
733 1.1 christos bfd_boolean crhi_known = FALSE;
734 1.1 christos bfd_boolean spmask_skip_operand = FALSE;
735 1.1 christos unsigned int fcyc_bits = 0;
736 1.1 christos bfd_boolean prev_sploop_found = FALSE;
737 1.1 christos
738 1.1 christos switch (opc->operand_info[op_num].form)
739 1.1 christos {
740 1.1.1.2 christos case tic6x_operand_b15reg:
741 1.1.1.2 christos /* Fully determined by the functional unit. */
742 1.1.1.2 christos operands_text[op_num] = TRUE;
743 1.1.1.2 christos snprintf (operands[op_num], 24, "b15");
744 1.1.1.2 christos continue;
745 1.1.1.2 christos
746 1.1.1.2 christos case tic6x_operand_zreg:
747 1.1.1.2 christos /* Fully determined by the functional unit. */
748 1.1.1.2 christos operands_text[op_num] = TRUE;
749 1.1.1.2 christos snprintf (operands[op_num], 24, "%c0",
750 1.1.1.2 christos (func_unit_side == 2 ? 'b' : 'a'));
751 1.1.1.2 christos continue;
752 1.1.1.2 christos
753 1.1 christos case tic6x_operand_retreg:
754 1.1 christos /* Fully determined by the functional unit. */
755 1.1 christos operands_text[op_num] = TRUE;
756 1.1 christos snprintf (operands[op_num], 24, "%c3",
757 1.1 christos (func_unit_side == 2 ? 'b' : 'a'));
758 1.1 christos continue;
759 1.1 christos
760 1.1 christos case tic6x_operand_irp:
761 1.1 christos operands_text[op_num] = TRUE;
762 1.1 christos snprintf (operands[op_num], 24, "irp");
763 1.1 christos continue;
764 1.1 christos
765 1.1 christos case tic6x_operand_nrp:
766 1.1 christos operands_text[op_num] = TRUE;
767 1.1 christos snprintf (operands[op_num], 24, "nrp");
768 1.1 christos continue;
769 1.1 christos
770 1.1.1.2 christos case tic6x_operand_ilc:
771 1.1.1.2 christos operands_text[op_num] = TRUE;
772 1.1.1.2 christos snprintf (operands[op_num], 24, "ilc");
773 1.1.1.2 christos continue;
774 1.1.1.2 christos
775 1.1.1.2 christos case tic6x_operand_hw_const_minus_1:
776 1.1.1.2 christos operands_text[op_num] = TRUE;
777 1.1.1.2 christos snprintf (operands[op_num], 24, "-1");
778 1.1.1.2 christos continue;
779 1.1.1.2 christos
780 1.1.1.2 christos case tic6x_operand_hw_const_0:
781 1.1.1.2 christos operands_text[op_num] = TRUE;
782 1.1.1.2 christos snprintf (operands[op_num], 24, "0");
783 1.1.1.2 christos continue;
784 1.1.1.2 christos
785 1.1.1.2 christos case tic6x_operand_hw_const_1:
786 1.1.1.2 christos operands_text[op_num] = TRUE;
787 1.1.1.2 christos snprintf (operands[op_num], 24, "1");
788 1.1.1.2 christos continue;
789 1.1.1.2 christos
790 1.1.1.2 christos case tic6x_operand_hw_const_5:
791 1.1.1.2 christos operands_text[op_num] = TRUE;
792 1.1.1.2 christos snprintf (operands[op_num], 24, "5");
793 1.1.1.2 christos continue;
794 1.1.1.2 christos
795 1.1.1.2 christos case tic6x_operand_hw_const_16:
796 1.1.1.2 christos operands_text[op_num] = TRUE;
797 1.1.1.2 christos snprintf (operands[op_num], 24, "16");
798 1.1.1.2 christos continue;
799 1.1.1.2 christos
800 1.1.1.2 christos case tic6x_operand_hw_const_24:
801 1.1.1.2 christos operands_text[op_num] = TRUE;
802 1.1.1.2 christos snprintf (operands[op_num], 24, "24");
803 1.1.1.2 christos continue;
804 1.1.1.2 christos
805 1.1.1.2 christos case tic6x_operand_hw_const_31:
806 1.1.1.2 christos operands_text[op_num] = TRUE;
807 1.1.1.2 christos snprintf (operands[op_num], 24, "31");
808 1.1.1.2 christos continue;
809 1.1.1.2 christos
810 1.1 christos default:
811 1.1 christos break;
812 1.1 christos }
813 1.1 christos
814 1.1 christos for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++)
815 1.1 christos {
816 1.1 christos const tic6x_coding_field *const enc
817 1.1 christos = &opc->variable_fields[fld_num];
818 1.1 christos const tic6x_insn_field *field;
819 1.1 christos unsigned int fld_val;
820 1.1.1.2 christos unsigned int reg_base = 0;
821 1.1 christos signed int signed_fld_val;
822 1.1.1.2 christos char reg_side = '?';
823 1.1 christos
824 1.1 christos if (enc->operand_num != op_num)
825 1.1 christos continue;
826 1.1 christos field = tic6x_field_from_fmt (fmt, enc->field_id);
827 1.1 christos if (!field)
828 1.1.1.2 christos {
829 1.1.1.2 christos printf ("opcode %x: missing field (field_id:%d) in format\n", opcode, enc->field_id);
830 1.1.1.2 christos abort ();
831 1.1.1.2 christos }
832 1.1.1.2 christos fld_val = tic6x_field_bits (opcode, field);
833 1.1 christos switch (enc->coding_method)
834 1.1 christos {
835 1.1.1.2 christos case tic6x_coding_cst_s3i:
836 1.1.1.2 christos (fld_val == 0x00) && (fld_val = 0x10);
837 1.1.1.2 christos (fld_val == 0x07) && (fld_val = 0x08);
838 1.1.1.2 christos /* Fall through. */
839 1.1 christos case tic6x_coding_ucst:
840 1.1 christos case tic6x_coding_ulcst_dpr_byte:
841 1.1 christos case tic6x_coding_ulcst_dpr_half:
842 1.1 christos case tic6x_coding_ulcst_dpr_word:
843 1.1 christos case tic6x_coding_lcst_low16:
844 1.1 christos switch (opc->operand_info[op_num].form)
845 1.1 christos {
846 1.1 christos case tic6x_operand_asm_const:
847 1.1 christos case tic6x_operand_link_const:
848 1.1 christos operands_text[op_num] = TRUE;
849 1.1 christos snprintf (operands[op_num], 24, "%u", fld_val);
850 1.1 christos break;
851 1.1 christos
852 1.1 christos case tic6x_operand_mem_long:
853 1.1 christos mem_offset = fld_val;
854 1.1 christos mem_offset_known_long = TRUE;
855 1.1 christos break;
856 1.1 christos
857 1.1 christos default:
858 1.1.1.2 christos printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num);
859 1.1 christos abort ();
860 1.1 christos }
861 1.1 christos break;
862 1.1 christos
863 1.1 christos case tic6x_coding_lcst_high16:
864 1.1 christos operands_text[op_num] = TRUE;
865 1.1 christos snprintf (operands[op_num], 24, "%u", fld_val << 16);
866 1.1 christos break;
867 1.1 christos
868 1.1.1.2 christos case tic6x_coding_scst_l3i:
869 1.1.1.2 christos operands_text[op_num] = TRUE;
870 1.1.1.2 christos if (fld_val == 0)
871 1.1.1.2 christos {
872 1.1.1.2 christos signed_fld_val = 8;
873 1.1.1.2 christos }
874 1.1.1.2 christos else
875 1.1.1.2 christos {
876 1.1.1.2 christos signed_fld_val = (signed int) fld_val;
877 1.1.1.2 christos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
878 1.1.1.2 christos signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
879 1.1.1.2 christos }
880 1.1.1.2 christos snprintf (operands[op_num], 24, "%d", signed_fld_val);
881 1.1.1.2 christos break;
882 1.1.1.2 christos
883 1.1 christos case tic6x_coding_scst:
884 1.1 christos operands_text[op_num] = TRUE;
885 1.1 christos signed_fld_val = (signed int) fld_val;
886 1.1.1.2 christos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
887 1.1.1.2 christos signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
888 1.1 christos snprintf (operands[op_num], 24, "%d", signed_fld_val);
889 1.1 christos break;
890 1.1 christos
891 1.1 christos case tic6x_coding_ucst_minus_one:
892 1.1 christos operands_text[op_num] = TRUE;
893 1.1 christos snprintf (operands[op_num], 24, "%u", fld_val + 1);
894 1.1 christos break;
895 1.1 christos
896 1.1 christos case tic6x_coding_pcrel:
897 1.1 christos case tic6x_coding_pcrel_half:
898 1.1 christos signed_fld_val = (signed int) fld_val;
899 1.1.1.2 christos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1));
900 1.1.1.2 christos signed_fld_val -= (1 << (tic6x_field_width (field) - 1));
901 1.1 christos if (fetch_packet_header_based
902 1.1 christos && enc->coding_method == tic6x_coding_pcrel_half)
903 1.1 christos signed_fld_val *= 2;
904 1.1 christos else
905 1.1 christos signed_fld_val *= 4;
906 1.1 christos operands_pcrel[op_num] = TRUE;
907 1.1 christos operands_addresses[op_num] = fp_addr + signed_fld_val;
908 1.1 christos break;
909 1.1 christos
910 1.1.1.2 christos case tic6x_coding_regpair_msb:
911 1.1.1.2 christos if (opc->operand_info[op_num].form != tic6x_operand_regpair)
912 1.1.1.2 christos abort ();
913 1.1.1.2 christos operands_text[op_num] = TRUE;
914 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u:%c%u",
915 1.1.1.2 christos (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1),
916 1.1.1.2 christos (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1);
917 1.1.1.2 christos break;
918 1.1.1.2 christos
919 1.1.1.2 christos case tic6x_coding_pcrel_half_unsigned:
920 1.1.1.2 christos operands_pcrel[op_num] = TRUE;
921 1.1.1.2 christos operands_addresses[op_num] = fp_addr + 2 * fld_val;
922 1.1.1.2 christos break;
923 1.1.1.2 christos
924 1.1 christos case tic6x_coding_reg_shift:
925 1.1 christos fld_val <<= 1;
926 1.1 christos /* Fall through. */
927 1.1 christos case tic6x_coding_reg:
928 1.1.1.2 christos if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
929 1.1.1.2 christos {
930 1.1.1.2 christos reg_base = 16;
931 1.1.1.2 christos }
932 1.1 christos switch (opc->operand_info[op_num].form)
933 1.1 christos {
934 1.1.1.2 christos case tic6x_operand_treg:
935 1.1.1.2 christos if (!have_t)
936 1.1.1.2 christos {
937 1.1.1.2 christos printf ("opcode %x: operand treg but missing t field\n", opcode);
938 1.1.1.2 christos abort ();
939 1.1.1.2 christos }
940 1.1.1.2 christos operands_text[op_num] = TRUE;
941 1.1.1.2 christos reg_side = t_val ? 'b' : 'a';
942 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
943 1.1.1.2 christos break;
944 1.1.1.2 christos
945 1.1 christos case tic6x_operand_reg:
946 1.1 christos operands_text[op_num] = TRUE;
947 1.1.1.2 christos reg_side = (func_unit_side == 2) ? 'b' : 'a';
948 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
949 1.1.1.2 christos break;
950 1.1.1.2 christos
951 1.1.1.2 christos case tic6x_operand_reg_nors:
952 1.1.1.2 christos operands_text[op_num] = TRUE;
953 1.1.1.2 christos reg_side = (func_unit_side == 2) ? 'b' : 'a';
954 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val);
955 1.1.1.2 christos break;
956 1.1.1.2 christos
957 1.1.1.2 christos case tic6x_operand_reg_bside:
958 1.1.1.2 christos operands_text[op_num] = TRUE;
959 1.1.1.2 christos snprintf (operands[op_num], 24, "b%u", reg_base + fld_val);
960 1.1.1.2 christos break;
961 1.1.1.2 christos
962 1.1.1.2 christos case tic6x_operand_reg_bside_nors:
963 1.1.1.2 christos operands_text[op_num] = TRUE;
964 1.1.1.2 christos snprintf (operands[op_num], 24, "b%u", fld_val);
965 1.1 christos break;
966 1.1 christos
967 1.1 christos case tic6x_operand_xreg:
968 1.1 christos operands_text[op_num] = TRUE;
969 1.1.1.2 christos reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
970 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
971 1.1 christos break;
972 1.1 christos
973 1.1 christos case tic6x_operand_dreg:
974 1.1 christos operands_text[op_num] = TRUE;
975 1.1.1.2 christos reg_side = (func_unit_data_side == 2) ? 'b' : 'a';
976 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val);
977 1.1 christos break;
978 1.1 christos
979 1.1 christos case tic6x_operand_regpair:
980 1.1 christos operands_text[op_num] = TRUE;
981 1.1 christos if (fld_val & 1)
982 1.1 christos operands_ok = FALSE;
983 1.1.1.2 christos reg_side = (func_unit_side == 2) ? 'b' : 'a';
984 1.1 christos snprintf (operands[op_num], 24, "%c%u:%c%u",
985 1.1.1.2 christos reg_side, reg_base + fld_val + 1,
986 1.1.1.2 christos reg_side, reg_base + fld_val);
987 1.1 christos break;
988 1.1 christos
989 1.1 christos case tic6x_operand_xregpair:
990 1.1 christos operands_text[op_num] = TRUE;
991 1.1 christos if (fld_val & 1)
992 1.1 christos operands_ok = FALSE;
993 1.1.1.2 christos reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a';
994 1.1 christos snprintf (operands[op_num], 24, "%c%u:%c%u",
995 1.1.1.2 christos reg_side, reg_base + fld_val + 1,
996 1.1.1.2 christos reg_side, reg_base + fld_val);
997 1.1.1.2 christos break;
998 1.1.1.2 christos
999 1.1.1.2 christos case tic6x_operand_tregpair:
1000 1.1.1.2 christos if (!have_t)
1001 1.1.1.2 christos {
1002 1.1.1.2 christos printf ("opcode %x: operand tregpair but missing t field\n", opcode);
1003 1.1.1.2 christos abort ();
1004 1.1.1.2 christos }
1005 1.1.1.2 christos operands_text[op_num] = TRUE;
1006 1.1.1.2 christos if (fld_val & 1)
1007 1.1.1.2 christos operands_ok = FALSE;
1008 1.1.1.2 christos reg_side = t_val ? 'b' : 'a';
1009 1.1.1.2 christos snprintf (operands[op_num], 24, "%c%u:%c%u",
1010 1.1.1.2 christos reg_side, reg_base + fld_val + 1,
1011 1.1.1.2 christos reg_side, reg_base + fld_val);
1012 1.1 christos break;
1013 1.1 christos
1014 1.1 christos case tic6x_operand_dregpair:
1015 1.1 christos operands_text[op_num] = TRUE;
1016 1.1 christos if (fld_val & 1)
1017 1.1 christos operands_ok = FALSE;
1018 1.1.1.2 christos reg_side = (func_unit_data_side) == 2 ? 'b' : 'a';
1019 1.1 christos snprintf (operands[op_num], 24, "%c%u:%c%u",
1020 1.1.1.2 christos reg_side, reg_base + fld_val + 1,
1021 1.1.1.2 christos reg_side, reg_base + fld_val);
1022 1.1 christos break;
1023 1.1 christos
1024 1.1 christos case tic6x_operand_mem_deref:
1025 1.1 christos operands_text[op_num] = TRUE;
1026 1.1.1.2 christos reg_side = func_unit_side == 2 ? 'b' : 'a';
1027 1.1.1.2 christos snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val);
1028 1.1 christos break;
1029 1.1 christos
1030 1.1 christos case tic6x_operand_mem_short:
1031 1.1 christos case tic6x_operand_mem_ndw:
1032 1.1 christos mem_base_reg = fld_val;
1033 1.1 christos mem_base_reg_known = TRUE;
1034 1.1 christos break;
1035 1.1 christos
1036 1.1 christos default:
1037 1.1.1.2 christos printf ("opcode %x: unexpected operand form %d for operand #%d",
1038 1.1.1.2 christos opcode, opc->operand_info[op_num].form, op_num);
1039 1.1.1.2 christos abort ();
1040 1.1.1.2 christos }
1041 1.1.1.2 christos break;
1042 1.1.1.2 christos
1043 1.1.1.2 christos case tic6x_coding_reg_ptr:
1044 1.1.1.2 christos switch (opc->operand_info[op_num].form)
1045 1.1.1.2 christos {
1046 1.1.1.2 christos case tic6x_operand_mem_short:
1047 1.1.1.2 christos case tic6x_operand_mem_ndw:
1048 1.1.1.2 christos if (fld_val > 0x3u)
1049 1.1.1.2 christos {
1050 1.1.1.2 christos printf("opcode %x: illegal field value for ptr register of operand #%d (%d)",
1051 1.1.1.2 christos opcode, op_num, fld_val);
1052 1.1.1.2 christos abort ();
1053 1.1.1.2 christos }
1054 1.1.1.2 christos mem_base_reg = 0x4 | fld_val;
1055 1.1.1.2 christos mem_base_reg_known = TRUE;
1056 1.1.1.2 christos break;
1057 1.1.1.2 christos
1058 1.1.1.2 christos default:
1059 1.1.1.2 christos printf ("opcode %x: unexpected operand form %d for operand #%d",
1060 1.1.1.2 christos opcode, opc->operand_info[op_num].form, op_num);
1061 1.1 christos abort ();
1062 1.1 christos }
1063 1.1 christos break;
1064 1.1 christos
1065 1.1 christos case tic6x_coding_areg:
1066 1.1 christos switch (opc->operand_info[op_num].form)
1067 1.1 christos {
1068 1.1 christos case tic6x_operand_areg:
1069 1.1 christos operands_text[op_num] = TRUE;
1070 1.1 christos snprintf (operands[op_num], 24, "b%u",
1071 1.1 christos fld_val ? 15u : 14u);
1072 1.1 christos break;
1073 1.1 christos
1074 1.1 christos case tic6x_operand_mem_long:
1075 1.1 christos mem_base_reg = fld_val ? 15u : 14u;
1076 1.1 christos mem_base_reg_known_long = TRUE;
1077 1.1 christos break;
1078 1.1 christos
1079 1.1 christos default:
1080 1.1.1.2 christos printf ("opcode %x: bad operand form\n", opcode);
1081 1.1 christos abort ();
1082 1.1 christos }
1083 1.1 christos break;
1084 1.1 christos
1085 1.1.1.2 christos case tic6x_coding_mem_offset_minus_one_noscale:
1086 1.1.1.2 christos case tic6x_coding_mem_offset_minus_one:
1087 1.1.1.2 christos fld_val += 1;
1088 1.1.1.6 christos /* Fall through. */
1089 1.1 christos case tic6x_coding_mem_offset_noscale:
1090 1.1.1.2 christos case tic6x_coding_mem_offset:
1091 1.1 christos mem_offset = fld_val;
1092 1.1 christos mem_offset_known = TRUE;
1093 1.1.1.2 christos if (num_bits == 16)
1094 1.1.1.2 christos {
1095 1.1.1.2 christos mem_mode_known = TRUE;
1096 1.1.1.2 christos mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags);
1097 1.1.1.2 christos mem_scaled_known = TRUE;
1098 1.1.1.2 christos mem_scaled = TRUE;
1099 1.1.1.2 christos if (opc->flags & TIC6X_FLAG_INSN16_B15PTR)
1100 1.1.1.2 christos {
1101 1.1.1.2 christos mem_base_reg_known = TRUE;
1102 1.1.1.2 christos mem_base_reg = 15;
1103 1.1.1.2 christos }
1104 1.1.1.2 christos if ( enc->coding_method == tic6x_coding_mem_offset_noscale
1105 1.1.1.2 christos || enc->coding_method == tic6x_coding_mem_offset_noscale )
1106 1.1.1.2 christos mem_scaled = FALSE;
1107 1.1.1.2 christos }
1108 1.1 christos break;
1109 1.1 christos
1110 1.1 christos case tic6x_coding_mem_mode:
1111 1.1 christos mem_mode = fld_val;
1112 1.1 christos mem_mode_known = TRUE;
1113 1.1 christos break;
1114 1.1 christos
1115 1.1 christos case tic6x_coding_scaled:
1116 1.1 christos mem_scaled = fld_val;
1117 1.1 christos mem_scaled_known = TRUE;
1118 1.1 christos break;
1119 1.1 christos
1120 1.1 christos case tic6x_coding_crlo:
1121 1.1 christos crlo = fld_val;
1122 1.1 christos crlo_known = TRUE;
1123 1.1 christos break;
1124 1.1 christos
1125 1.1 christos case tic6x_coding_crhi:
1126 1.1 christos crhi = fld_val;
1127 1.1 christos crhi_known = TRUE;
1128 1.1 christos break;
1129 1.1 christos
1130 1.1 christos case tic6x_coding_fstg:
1131 1.1 christos case tic6x_coding_fcyc:
1132 1.1 christos if (!prev_sploop_found)
1133 1.1 christos {
1134 1.1 christos bfd_vma search_fp_addr = fp_addr;
1135 1.1 christos bfd_vma search_fp_offset = fp_offset;
1136 1.1 christos bfd_boolean search_fp_header_based
1137 1.1 christos = fetch_packet_header_based;
1138 1.1 christos tic6x_fetch_packet_header search_fp_header = header;
1139 1.1 christos unsigned char search_fp[32];
1140 1.1 christos unsigned int search_num_bits;
1141 1.1 christos unsigned int search_opcode;
1142 1.1 christos unsigned int sploop_ii = 0;
1143 1.1 christos int i;
1144 1.1 christos
1145 1.1 christos memcpy (search_fp, fp, 32);
1146 1.1 christos
1147 1.1 christos /* To interpret these bits in an SPKERNEL
1148 1.1 christos instruction, we must find the previous
1149 1.1 christos SPLOOP-family instruction. It may come up to
1150 1.1 christos 48 execute packets earlier. */
1151 1.1 christos for (i = 0; i < 48 * 8; i++)
1152 1.1 christos {
1153 1.1 christos /* Find the previous instruction. */
1154 1.1 christos if (search_fp_offset & 2)
1155 1.1 christos search_fp_offset -= 2;
1156 1.1 christos else if (search_fp_offset >= 4)
1157 1.1 christos {
1158 1.1 christos if (search_fp_header_based
1159 1.1 christos && (search_fp_header.word_compact
1160 1.1 christos [(search_fp_offset >> 2) - 1]))
1161 1.1 christos search_fp_offset -= 2;
1162 1.1 christos else
1163 1.1 christos search_fp_offset -= 4;
1164 1.1 christos }
1165 1.1 christos else
1166 1.1 christos {
1167 1.1 christos search_fp_addr -= 32;
1168 1.1 christos status = info->read_memory_func (search_fp_addr,
1169 1.1 christos search_fp,
1170 1.1 christos 32, info);
1171 1.1 christos if (status)
1172 1.1 christos /* No previous SPLOOP instruction. */
1173 1.1 christos break;
1174 1.1 christos search_fp_header_based
1175 1.1 christos = (tic6x_check_fetch_packet_header
1176 1.1 christos (search_fp, &search_fp_header, info));
1177 1.1 christos if (search_fp_header_based)
1178 1.1 christos search_fp_offset
1179 1.1 christos = search_fp_header.word_compact[6] ? 26 : 24;
1180 1.1 christos else
1181 1.1 christos search_fp_offset = 28;
1182 1.1 christos }
1183 1.1 christos
1184 1.1 christos /* Extract the previous instruction. */
1185 1.1 christos if (search_fp_header_based)
1186 1.1 christos search_num_bits
1187 1.1 christos = (search_fp_header.word_compact[search_fp_offset
1188 1.1 christos >> 2]
1189 1.1 christos ? 16
1190 1.1 christos : 32);
1191 1.1 christos else
1192 1.1 christos search_num_bits = 32;
1193 1.1 christos if (search_num_bits == 16)
1194 1.1 christos {
1195 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE)
1196 1.1 christos search_opcode
1197 1.1 christos = (tic6x_extract_16
1198 1.1.1.2 christos (search_fp + search_fp_offset, &header, info));
1199 1.1 christos else
1200 1.1 christos search_opcode
1201 1.1 christos = (tic6x_extract_16
1202 1.1.1.2 christos (search_fp + (search_fp_offset ^ 2), &header,
1203 1.1 christos info));
1204 1.1 christos }
1205 1.1 christos else
1206 1.1 christos search_opcode
1207 1.1 christos = tic6x_extract_32 (search_fp + search_fp_offset,
1208 1.1 christos info);
1209 1.1 christos
1210 1.1 christos /* Check whether it is an SPLOOP-family
1211 1.1 christos instruction. */
1212 1.1 christos if (search_num_bits == 32
1213 1.1 christos && ((search_opcode & 0x003ffffe) == 0x00038000
1214 1.1 christos || (search_opcode & 0x003ffffe) == 0x0003a000
1215 1.1 christos || ((search_opcode & 0x003ffffe)
1216 1.1 christos == 0x0003e000)))
1217 1.1 christos {
1218 1.1 christos prev_sploop_found = TRUE;
1219 1.1 christos sploop_ii = ((search_opcode >> 23) & 0x1f) + 1;
1220 1.1 christos }
1221 1.1 christos else if (search_num_bits == 16
1222 1.1 christos && (search_opcode & 0x3c7e) == 0x0c66)
1223 1.1 christos {
1224 1.1 christos prev_sploop_found = TRUE;
1225 1.1 christos sploop_ii
1226 1.1 christos = (((search_opcode >> 7) & 0x7)
1227 1.1 christos | ((search_opcode >> 11) & 0x8)) + 1;
1228 1.1 christos }
1229 1.1 christos if (prev_sploop_found)
1230 1.1 christos {
1231 1.1 christos if (sploop_ii <= 0)
1232 1.1.1.2 christos {
1233 1.1.1.2 christos printf ("opcode %x: sloop index not found (%d)\n", opcode, sploop_ii);
1234 1.1.1.2 christos abort ();
1235 1.1.1.2 christos }
1236 1.1 christos else if (sploop_ii <= 1)
1237 1.1 christos fcyc_bits = 0;
1238 1.1 christos else if (sploop_ii <= 2)
1239 1.1 christos fcyc_bits = 1;
1240 1.1 christos else if (sploop_ii <= 4)
1241 1.1 christos fcyc_bits = 2;
1242 1.1 christos else if (sploop_ii <= 8)
1243 1.1 christos fcyc_bits = 3;
1244 1.1 christos else if (sploop_ii <= 14)
1245 1.1 christos fcyc_bits = 4;
1246 1.1 christos else
1247 1.1 christos prev_sploop_found = FALSE;
1248 1.1 christos }
1249 1.1 christos if (prev_sploop_found)
1250 1.1 christos break;
1251 1.1 christos }
1252 1.1 christos }
1253 1.1 christos if (!prev_sploop_found)
1254 1.1 christos {
1255 1.1 christos operands_ok = FALSE;
1256 1.1 christos operands_text[op_num] = TRUE;
1257 1.1 christos break;
1258 1.1 christos }
1259 1.1.1.2 christos if (fcyc_bits > tic6x_field_width(field))
1260 1.1.1.2 christos {
1261 1.1.1.2 christos printf ("opcode %x: illegal fcyc value (%d)\n", opcode, fcyc_bits);
1262 1.1.1.2 christos abort ();
1263 1.1.1.2 christos }
1264 1.1 christos if (enc->coding_method == tic6x_coding_fstg)
1265 1.1 christos {
1266 1.1 christos int i, t;
1267 1.1 christos for (t = 0, i = fcyc_bits; i < 6; i++)
1268 1.1 christos t = (t << 1) | ((fld_val >> i) & 1);
1269 1.1 christos operands_text[op_num] = TRUE;
1270 1.1 christos snprintf (operands[op_num], 24, "%u", t);
1271 1.1 christos }
1272 1.1 christos else
1273 1.1 christos {
1274 1.1 christos operands_text[op_num] = TRUE;
1275 1.1 christos snprintf (operands[op_num], 24, "%u",
1276 1.1 christos fld_val & ((1 << fcyc_bits) - 1));
1277 1.1 christos }
1278 1.1 christos break;
1279 1.1 christos
1280 1.1 christos case tic6x_coding_spmask:
1281 1.1 christos if (fld_val == 0)
1282 1.1 christos spmask_skip_operand = TRUE;
1283 1.1 christos else
1284 1.1 christos {
1285 1.1 christos char *p;
1286 1.1 christos unsigned int i;
1287 1.1 christos
1288 1.1 christos operands_text[op_num] = TRUE;
1289 1.1 christos p = operands[op_num];
1290 1.1 christos for (i = 0; i < 8; i++)
1291 1.1 christos if (fld_val & (1 << i))
1292 1.1 christos {
1293 1.1 christos *p++ = "LSDM"[i/2];
1294 1.1 christos *p++ = '1' + (i & 1);
1295 1.1 christos *p++ = ',';
1296 1.1 christos }
1297 1.1 christos p[-1] = 0;
1298 1.1 christos }
1299 1.1 christos break;
1300 1.1 christos
1301 1.1 christos case tic6x_coding_fu:
1302 1.1 christos case tic6x_coding_data_fu:
1303 1.1 christos case tic6x_coding_xpath:
1304 1.1.1.2 christos case tic6x_coding_rside:
1305 1.1 christos /* Don't relate to operands, so operand number is
1306 1.1 christos meaningless. */
1307 1.1 christos break;
1308 1.1 christos
1309 1.1 christos default:
1310 1.1.1.2 christos printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method);
1311 1.1 christos abort ();
1312 1.1 christos }
1313 1.1 christos
1314 1.1 christos if (mem_base_reg_known_long && mem_offset_known_long)
1315 1.1 christos {
1316 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num])
1317 1.1.1.2 christos {
1318 1.1.1.2 christos printf ("opcode %x: long access but operands already known ?\n", opcode);
1319 1.1.1.2 christos abort ();
1320 1.1.1.2 christos }
1321 1.1 christos operands_text[op_num] = TRUE;
1322 1.1 christos snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg,
1323 1.1 christos mem_offset * opc->operand_info[op_num].size);
1324 1.1 christos }
1325 1.1 christos
1326 1.1 christos if (mem_base_reg_known && mem_offset_known && mem_mode_known
1327 1.1 christos && (mem_scaled_known
1328 1.1 christos || (opc->operand_info[op_num].form
1329 1.1 christos != tic6x_operand_mem_ndw)))
1330 1.1 christos {
1331 1.1 christos char side;
1332 1.1 christos char base[4];
1333 1.1 christos bfd_boolean offset_is_reg;
1334 1.1 christos bfd_boolean offset_scaled;
1335 1.1 christos char offset[4];
1336 1.1 christos char offsetp[6];
1337 1.1 christos
1338 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num])
1339 1.1.1.2 christos {
1340 1.1.1.2 christos printf ("opcode %x: mem access operands already known ?\n", opcode);
1341 1.1.1.2 christos abort ();
1342 1.1.1.2 christos }
1343 1.1 christos
1344 1.1 christos side = func_unit_side == 2 ? 'b' : 'a';
1345 1.1 christos snprintf (base, 4, "%c%u", side, mem_base_reg);
1346 1.1 christos
1347 1.1 christos offset_is_reg = ((mem_mode & 4) ? TRUE : FALSE);
1348 1.1 christos if (offset_is_reg)
1349 1.1 christos {
1350 1.1.1.2 christos
1351 1.1.1.2 christos if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS))
1352 1.1.1.2 christos {
1353 1.1.1.2 christos reg_base = 16;
1354 1.1.1.2 christos }
1355 1.1.1.2 christos snprintf (offset, 4, "%c%u", side, reg_base + mem_offset);
1356 1.1 christos if (opc->operand_info[op_num].form
1357 1.1 christos == tic6x_operand_mem_ndw)
1358 1.1 christos offset_scaled = mem_scaled ? TRUE : FALSE;
1359 1.1 christos else
1360 1.1 christos offset_scaled = TRUE;
1361 1.1 christos }
1362 1.1 christos else
1363 1.1 christos {
1364 1.1 christos if (opc->operand_info[op_num].form
1365 1.1 christos == tic6x_operand_mem_ndw)
1366 1.1 christos {
1367 1.1 christos offset_scaled = mem_scaled ? TRUE : FALSE;
1368 1.1 christos snprintf (offset, 4, "%u", mem_offset);
1369 1.1 christos }
1370 1.1 christos else
1371 1.1 christos {
1372 1.1 christos offset_scaled = FALSE;
1373 1.1 christos snprintf (offset, 4, "%u",
1374 1.1 christos (mem_offset
1375 1.1 christos * opc->operand_info[op_num].size));
1376 1.1 christos }
1377 1.1 christos }
1378 1.1 christos
1379 1.1 christos if (offset_scaled)
1380 1.1 christos snprintf (offsetp, 6, "[%s]", offset);
1381 1.1 christos else
1382 1.1 christos snprintf (offsetp, 6, "(%s)", offset);
1383 1.1 christos
1384 1.1 christos operands_text[op_num] = TRUE;
1385 1.1 christos switch (mem_mode & ~4u)
1386 1.1 christos {
1387 1.1 christos case 0:
1388 1.1 christos snprintf (operands[op_num], 24, "*-%s%s", base, offsetp);
1389 1.1 christos break;
1390 1.1 christos
1391 1.1 christos case 1:
1392 1.1 christos snprintf (operands[op_num], 24, "*+%s%s", base, offsetp);
1393 1.1 christos break;
1394 1.1 christos
1395 1.1 christos case 2:
1396 1.1 christos case 3:
1397 1.1 christos operands_ok = FALSE;
1398 1.1 christos break;
1399 1.1 christos
1400 1.1 christos case 8:
1401 1.1 christos snprintf (operands[op_num], 24, "*--%s%s", base,
1402 1.1 christos offsetp);
1403 1.1 christos break;
1404 1.1 christos
1405 1.1 christos case 9:
1406 1.1 christos snprintf (operands[op_num], 24, "*++%s%s", base,
1407 1.1 christos offsetp);
1408 1.1 christos break;
1409 1.1 christos
1410 1.1 christos case 10:
1411 1.1 christos snprintf (operands[op_num], 24, "*%s--%s", base,
1412 1.1 christos offsetp);
1413 1.1 christos break;
1414 1.1 christos
1415 1.1 christos case 11:
1416 1.1 christos snprintf (operands[op_num], 24, "*%s++%s", base,
1417 1.1 christos offsetp);
1418 1.1 christos break;
1419 1.1 christos
1420 1.1 christos default:
1421 1.1.1.2 christos printf ("*** unknown mem_mode : %d \n", mem_mode);
1422 1.1 christos abort ();
1423 1.1 christos }
1424 1.1 christos }
1425 1.1 christos
1426 1.1 christos if (crlo_known && crhi_known)
1427 1.1 christos {
1428 1.1 christos tic6x_rw rw;
1429 1.1 christos tic6x_ctrl_id crid;
1430 1.1 christos
1431 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num])
1432 1.1.1.2 christos {
1433 1.1.1.2 christos printf ("*** abort crlo crli\n");
1434 1.1.1.2 christos abort ();
1435 1.1.1.2 christos }
1436 1.1 christos
1437 1.1 christos rw = opc->operand_info[op_num].rw;
1438 1.1 christos if (rw != tic6x_rw_read
1439 1.1 christos && rw != tic6x_rw_write)
1440 1.1.1.2 christos {
1441 1.1.1.2 christos printf ("*** abort rw : %d\n", rw);
1442 1.1.1.2 christos abort ();
1443 1.1.1.2 christos }
1444 1.1 christos
1445 1.1 christos for (crid = 0; crid < tic6x_ctrl_max; crid++)
1446 1.1 christos {
1447 1.1 christos if (crlo == tic6x_ctrl_table[crid].crlo
1448 1.1 christos && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0
1449 1.1 christos && (rw == tic6x_rw_read
1450 1.1 christos ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read
1451 1.1 christos || (tic6x_ctrl_table[crid].rw
1452 1.1 christos == tic6x_rw_read_write))
1453 1.1 christos : (tic6x_ctrl_table[crid].rw == tic6x_rw_write
1454 1.1 christos || (tic6x_ctrl_table[crid].rw
1455 1.1 christos == tic6x_rw_read_write))))
1456 1.1 christos break;
1457 1.1 christos }
1458 1.1 christos if (crid == tic6x_ctrl_max)
1459 1.1 christos {
1460 1.1 christos operands_text[op_num] = TRUE;
1461 1.1 christos operands_ok = FALSE;
1462 1.1 christos }
1463 1.1 christos else
1464 1.1 christos {
1465 1.1 christos operands_text[op_num] = TRUE;
1466 1.1 christos snprintf (operands[op_num], 24, "%s",
1467 1.1 christos tic6x_ctrl_table[crid].name);
1468 1.1 christos }
1469 1.1 christos }
1470 1.1 christos
1471 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num]
1472 1.1 christos || spmask_skip_operand)
1473 1.1 christos break;
1474 1.1 christos }
1475 1.1.1.2 christos /* end for fld_num */
1476 1.1.1.2 christos
1477 1.1 christos if (spmask_skip_operand)
1478 1.1 christos {
1479 1.1 christos /* SPMASK operands are only valid as the single operand
1480 1.1 christos in the opcode table. */
1481 1.1 christos if (num_operands != 1)
1482 1.1.1.2 christos {
1483 1.1.1.2 christos printf ("opcode: %x, num_operands != 1 : %d\n", opcode, num_operands);
1484 1.1.1.2 christos abort ();
1485 1.1.1.2 christos }
1486 1.1 christos num_operands = 0;
1487 1.1 christos break;
1488 1.1 christos }
1489 1.1.1.2 christos
1490 1.1 christos /* The operand must by now have been decoded. */
1491 1.1 christos if (!operands_text[op_num] && !operands_pcrel[op_num])
1492 1.1.1.2 christos {
1493 1.1.1.2 christos printf ("opcode: %x, operand #%d not decoded\n", opcode, op_num);
1494 1.1.1.2 christos abort ();
1495 1.1.1.2 christos }
1496 1.1.1.2 christos }
1497 1.1.1.2 christos /* end for op_num */
1498 1.1 christos
1499 1.1 christos if (!operands_ok)
1500 1.1 christos continue;
1501 1.1 christos
1502 1.1 christos info->bytes_per_chunk = num_bits / 8;
1503 1.1.1.2 christos info->fprintf_func (info->stream, "%s", parallel);
1504 1.1.1.2 christos info->fprintf_func (info->stream, "%s%s%s", cond, opc->name,
1505 1.1.1.2 christos func_unit);
1506 1.1 christos for (op_num = 0; op_num < num_operands; op_num++)
1507 1.1 christos {
1508 1.1 christos info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ','));
1509 1.1 christos if (operands_pcrel[op_num])
1510 1.1 christos info->print_address_func (operands_addresses[op_num], info);
1511 1.1 christos else
1512 1.1 christos info->fprintf_func (info->stream, "%s", operands[op_num]);
1513 1.1 christos }
1514 1.1 christos if (fetch_packet_header_based && header.prot)
1515 1.1 christos info->fprintf_func (info->stream, " || nop 5");
1516 1.1 christos
1517 1.1 christos return num_bits / 8;
1518 1.1 christos }
1519 1.1 christos
1520 1.1 christos info->bytes_per_chunk = num_bits / 8;
1521 1.1 christos info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>",
1522 1.1 christos (int) num_bits / 4, opcode);
1523 1.1 christos return num_bits / 8;
1524 1.1 christos }
1525