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