[PATCH 6/57][Arm][GAS] Add support for MVE instructions: vst/vld{2,4}
[binutils-gdb.git] / opcodes / arc-dis.c
blobee598918c51ff7506d50d364dcdf962769af69dd
1 /* Instruction printing code for the ARC.
2 Copyright (C) 1994-2019 Free Software Foundation, Inc.
4 Contributed by Claudiu Zissulescu (claziss@synopsys.com)
6 This file is part of libopcodes.
8 This library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #include "sysdep.h"
24 #include <stdio.h>
25 #include <assert.h>
26 #include "dis-asm.h"
27 #include "opcode/arc.h"
28 #include "elf/arc.h"
29 #include "arc-dis.h"
30 #include "arc-ext.h"
31 #include "elf-bfd.h"
32 #include "libiberty.h"
33 #include "opintl.h"
35 /* Structure used to iterate over, and extract the values for, operands of
36 an opcode. */
38 struct arc_operand_iterator
40 /* The complete instruction value to extract operands from. */
41 unsigned long long insn;
43 /* The LIMM if this is being tracked separately. This field is only
44 valid if we find the LIMM operand in the operand list. */
45 unsigned limm;
47 /* The opcode this iterator is operating on. */
48 const struct arc_opcode *opcode;
50 /* The index into the opcodes operand index list. */
51 const unsigned char *opidx;
54 /* A private data used by ARC decoder. */
55 struct arc_disassemble_info
57 /* The current disassembled arc opcode. */
58 const struct arc_opcode *opcode;
60 /* Instruction length w/o limm field. */
61 unsigned insn_len;
63 /* TRUE if we have limm. */
64 bfd_boolean limm_p;
66 /* LIMM value, if exists. */
67 unsigned limm;
69 /* Condition code, if exists. */
70 unsigned condition_code;
72 /* Writeback mode. */
73 unsigned writeback_mode;
75 /* Number of operands. */
76 unsigned operands_count;
78 struct arc_insn_operand operands[MAX_INSN_ARGS];
81 /* Globals variables. */
83 static const char * const regnames[64] =
85 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
86 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
87 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
88 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
90 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
91 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
92 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
93 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
96 static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
98 "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
99 "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
102 static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
104 static const char * const addrtypeunknown = "unknown";
106 /* This structure keeps track which instruction class(es)
107 should be ignored durring disassembling. */
109 typedef struct skipclass
111 insn_class_t insn_class;
112 insn_subclass_t subclass;
113 struct skipclass *nxt;
114 } skipclass_t, *linkclass;
116 /* Intial classes of instructions to be consider first when
117 disassembling. */
118 static linkclass decodelist = NULL;
120 /* ISA mask value enforced via disassembler info options. ARC_OPCODE_NONE
121 value means that no CPU is enforced. */
123 static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
125 /* True if we want to print using only hex numbers. */
126 static bfd_boolean print_hex = FALSE;
128 /* Macros section. */
130 #ifdef DEBUG
131 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
132 #else
133 # define pr_debug(fmt, args...)
134 #endif
136 #define ARRANGE_ENDIAN(info, buf) \
137 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
138 : bfd_getb32 (buf))
140 #define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
141 (s + (sizeof (word) * 8 - 1 - e)))
142 #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
144 /* Functions implementation. */
146 /* Initialize private data. */
147 static bfd_boolean
148 init_arc_disasm_info (struct disassemble_info *info)
150 struct arc_disassemble_info *arc_infop
151 = calloc (sizeof (*arc_infop), 1);
153 if (arc_infop == NULL)
154 return FALSE;
156 info->private_data = arc_infop;
157 return TRUE;
160 /* Add a new element to the decode list. */
162 static void
163 add_to_decodelist (insn_class_t insn_class,
164 insn_subclass_t subclass)
166 linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
168 t->insn_class = insn_class;
169 t->subclass = subclass;
170 t->nxt = decodelist;
171 decodelist = t;
174 /* Return TRUE if we need to skip the opcode from being
175 disassembled. */
177 static bfd_boolean
178 skip_this_opcode (const struct arc_opcode *opcode)
180 linkclass t = decodelist;
182 /* Check opcode for major 0x06, return if it is not in. */
183 if (arc_opcode_len (opcode) == 4
184 && OPCODE_32BIT_INSN (opcode->opcode) != 0x06)
185 return FALSE;
187 /* or not a known truble class. */
188 switch (opcode->insn_class)
190 case FLOAT:
191 case DSP:
192 case ARITH:
193 break;
194 default:
195 return FALSE;
198 while (t != NULL)
200 if ((t->insn_class == opcode->insn_class)
201 && (t->subclass == opcode->subclass))
202 return FALSE;
203 t = t->nxt;
206 return TRUE;
209 static bfd_vma
210 bfd_getm32 (unsigned int data)
212 bfd_vma value = 0;
214 value = ((data & 0xff00) | (data & 0xff)) << 16;
215 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
216 return value;
219 static bfd_boolean
220 special_flag_p (const char *opname,
221 const char *flgname)
223 const struct arc_flag_special *flg_spec;
224 unsigned i, j, flgidx;
226 for (i = 0; i < arc_num_flag_special; i++)
228 flg_spec = &arc_flag_special_cases[i];
230 if (strcmp (opname, flg_spec->name))
231 continue;
233 /* Found potential special case instruction. */
234 for (j=0;; ++j)
236 flgidx = flg_spec->flags[j];
237 if (flgidx == 0)
238 break; /* End of the array. */
240 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
241 return TRUE;
244 return FALSE;
247 /* Find opcode from ARC_TABLE given the instruction described by INSN and
248 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
250 static const struct arc_opcode *
251 find_format_from_table (struct disassemble_info *info,
252 const struct arc_opcode *arc_table,
253 unsigned long long insn,
254 unsigned int insn_len,
255 unsigned isa_mask,
256 bfd_boolean *has_limm,
257 bfd_boolean overlaps)
259 unsigned int i = 0;
260 const struct arc_opcode *opcode = NULL;
261 const struct arc_opcode *t_op = NULL;
262 const unsigned char *opidx;
263 const unsigned char *flgidx;
264 bfd_boolean warn_p = FALSE;
268 bfd_boolean invalid = FALSE;
270 opcode = &arc_table[i++];
272 if (!(opcode->cpu & isa_mask))
273 continue;
275 if (arc_opcode_len (opcode) != (int) insn_len)
276 continue;
278 if ((insn & opcode->mask) != opcode->opcode)
279 continue;
281 *has_limm = FALSE;
283 /* Possible candidate, check the operands. */
284 for (opidx = opcode->operands; *opidx; opidx++)
286 int value, limmind;
287 const struct arc_operand *operand = &arc_operands[*opidx];
289 if (operand->flags & ARC_OPERAND_FAKE)
290 continue;
292 if (operand->extract)
293 value = (*operand->extract) (insn, &invalid);
294 else
295 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
297 /* Check for LIMM indicator. If it is there, then make sure
298 we pick the right format. */
299 limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
300 if (operand->flags & ARC_OPERAND_IR
301 && !(operand->flags & ARC_OPERAND_LIMM))
303 if ((value == 0x3E && insn_len == 4)
304 || (value == limmind && insn_len == 2))
306 invalid = TRUE;
307 break;
311 if (operand->flags & ARC_OPERAND_LIMM
312 && !(operand->flags & ARC_OPERAND_DUPLICATE))
313 *has_limm = TRUE;
316 /* Check the flags. */
317 for (flgidx = opcode->flags; *flgidx; flgidx++)
319 /* Get a valid flag class. */
320 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
321 const unsigned *flgopridx;
322 int foundA = 0, foundB = 0;
323 unsigned int value;
325 /* Check first the extensions. */
326 if (cl_flags->flag_class & F_CLASS_EXTEND)
328 value = (insn & 0x1F);
329 if (arcExtMap_condCodeName (value))
330 continue;
333 /* Check for the implicit flags. */
334 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
335 continue;
337 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
339 const struct arc_flag_operand *flg_operand =
340 &arc_flag_operands[*flgopridx];
342 value = (insn >> flg_operand->shift)
343 & ((1 << flg_operand->bits) - 1);
344 if (value == flg_operand->code)
345 foundA = 1;
346 if (value)
347 foundB = 1;
350 if (!foundA && foundB)
352 invalid = TRUE;
353 break;
357 if (invalid)
358 continue;
360 if (insn_len == 4
361 && overlaps)
363 warn_p = TRUE;
364 t_op = opcode;
365 if (skip_this_opcode (opcode))
366 continue;
369 /* The instruction is valid. */
370 return opcode;
372 while (opcode->mask);
374 if (warn_p)
376 info->fprintf_func (info->stream,
377 _("\nWarning: disassembly may be wrong due to "
378 "guessed opcode class choice.\n"
379 "Use -M<class[,class]> to select the correct "
380 "opcode class(es).\n\t\t\t\t"));
381 return t_op;
384 return NULL;
387 /* Find opcode for INSN, trying various different sources. The instruction
388 length in INSN_LEN will be updated if the instruction requires a LIMM
389 extension.
391 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
392 initialised, ready to iterate over the operands of the found opcode. If
393 the found opcode requires a LIMM then the LIMM value will be loaded into a
394 field of ITER.
396 This function returns TRUE in almost all cases, FALSE is reserved to
397 indicate an error (failing to find an opcode is not an error) a returned
398 result of FALSE would indicate that the disassembler can't continue.
400 If no matching opcode is found then the returned result will be TRUE, the
401 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
402 INSN_LEN will be unchanged.
404 If a matching opcode is found, then the returned result will be TRUE, the
405 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
406 4 if the instruction requires a LIMM, and the LIMM value will have been
407 loaded into a field of ITER. Finally, ITER will have been initialised so
408 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
409 operands. */
411 static bfd_boolean
412 find_format (bfd_vma memaddr,
413 unsigned long long insn,
414 unsigned int * insn_len,
415 unsigned isa_mask,
416 struct disassemble_info * info,
417 const struct arc_opcode ** opcode_result,
418 struct arc_operand_iterator * iter)
420 const struct arc_opcode *opcode = NULL;
421 bfd_boolean needs_limm;
422 const extInstruction_t *einsn, *i;
423 unsigned limm = 0;
424 struct arc_disassemble_info *arc_infop = info->private_data;
426 /* First, try the extension instructions. */
427 if (*insn_len == 4)
429 einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
430 for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
432 const char *errmsg = NULL;
434 opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
435 if (opcode == NULL)
437 (*info->fprintf_func) (info->stream, "\
438 An error occured while generating the extension instruction operations");
439 *opcode_result = NULL;
440 return FALSE;
443 opcode = find_format_from_table (info, opcode, insn, *insn_len,
444 isa_mask, &needs_limm, FALSE);
448 /* Then, try finding the first match in the opcode table. */
449 if (opcode == NULL)
450 opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
451 isa_mask, &needs_limm, TRUE);
453 if (needs_limm && opcode != NULL)
455 bfd_byte buffer[4];
456 int status;
458 status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
459 4, info);
460 if (status != 0)
462 opcode = NULL;
464 else
466 limm = ARRANGE_ENDIAN (info, buffer);
467 *insn_len += 4;
471 if (opcode != NULL)
473 iter->insn = insn;
474 iter->limm = limm;
475 iter->opcode = opcode;
476 iter->opidx = opcode->operands;
479 *opcode_result = opcode;
481 /* Update private data. */
482 arc_infop->opcode = opcode;
483 arc_infop->limm = (needs_limm) ? limm : 0;
484 arc_infop->limm_p = needs_limm;
486 return TRUE;
489 static void
490 print_flags (const struct arc_opcode *opcode,
491 unsigned long long *insn,
492 struct disassemble_info *info)
494 const unsigned char *flgidx;
495 unsigned int value;
496 struct arc_disassemble_info *arc_infop = info->private_data;
498 /* Now extract and print the flags. */
499 for (flgidx = opcode->flags; *flgidx; flgidx++)
501 /* Get a valid flag class. */
502 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
503 const unsigned *flgopridx;
505 /* Check first the extensions. */
506 if (cl_flags->flag_class & F_CLASS_EXTEND)
508 const char *name;
509 value = (insn[0] & 0x1F);
511 name = arcExtMap_condCodeName (value);
512 if (name)
514 (*info->fprintf_func) (info->stream, ".%s", name);
515 continue;
519 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
521 const struct arc_flag_operand *flg_operand =
522 &arc_flag_operands[*flgopridx];
524 /* Implicit flags are only used for the insn decoder. */
525 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
527 if (cl_flags->flag_class & F_CLASS_COND)
528 arc_infop->condition_code = flg_operand->code;
529 else if (cl_flags->flag_class & F_CLASS_WB)
530 arc_infop->writeback_mode = flg_operand->code;
531 else if (cl_flags->flag_class & F_CLASS_ZZ)
532 info->data_size = flg_operand->code;
533 continue;
536 if (!flg_operand->favail)
537 continue;
539 value = (insn[0] >> flg_operand->shift)
540 & ((1 << flg_operand->bits) - 1);
541 if (value == flg_operand->code)
543 /* FIXME!: print correctly nt/t flag. */
544 if (!special_flag_p (opcode->name, flg_operand->name))
545 (*info->fprintf_func) (info->stream, ".");
546 else if (info->insn_type == dis_dref)
548 switch (flg_operand->name[0])
550 case 'b':
551 info->data_size = 1;
552 break;
553 case 'h':
554 case 'w':
555 info->data_size = 2;
556 break;
557 default:
558 info->data_size = 4;
559 break;
562 if (flg_operand->name[0] == 'd'
563 && flg_operand->name[1] == 0)
564 info->branch_delay_insns = 1;
566 /* Check if it is a conditional flag. */
567 if (cl_flags->flag_class & F_CLASS_COND)
569 if (info->insn_type == dis_jsr)
570 info->insn_type = dis_condjsr;
571 else if (info->insn_type == dis_branch)
572 info->insn_type = dis_condbranch;
573 arc_infop->condition_code = flg_operand->code;
576 /* Check for the write back modes. */
577 if (cl_flags->flag_class & F_CLASS_WB)
578 arc_infop->writeback_mode = flg_operand->code;
580 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
586 static const char *
587 get_auxreg (const struct arc_opcode *opcode,
588 int value,
589 unsigned isa_mask)
591 const char *name;
592 unsigned int i;
593 const struct arc_aux_reg *auxr = &arc_aux_regs[0];
595 if (opcode->insn_class != AUXREG)
596 return NULL;
598 name = arcExtMap_auxRegName (value);
599 if (name)
600 return name;
602 for (i = 0; i < arc_num_aux_regs; i++, auxr++)
604 if (!(auxr->cpu & isa_mask))
605 continue;
607 if (auxr->subclass != NONE)
608 return NULL;
610 if (auxr->address == value)
611 return auxr->name;
613 return NULL;
616 /* Convert a value representing an address type to a string used to refer to
617 the address type in assembly code. */
619 static const char *
620 get_addrtype (int value)
622 if (value < 0 || value > addrtypenames_max)
623 return addrtypeunknown;
625 return addrtypenames[value];
628 /* Calculate the instruction length for an instruction starting with MSB
629 and LSB, the most and least significant byte. The ISA_MASK is used to
630 filter the instructions considered to only those that are part of the
631 current architecture.
633 The instruction lengths are calculated from the ARC_OPCODE table, and
634 cached for later use. */
636 static unsigned int
637 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
639 bfd_byte major_opcode = msb >> 3;
641 switch (info->mach)
643 case bfd_mach_arc_arc700:
644 /* The nps400 extension set requires this special casing of the
645 instruction length calculation. Right now this is not causing any
646 problems as none of the known extensions overlap in opcode space,
647 but, if they ever do then we might need to start carrying
648 information around in the elf about which extensions are in use. */
649 if (major_opcode == 0xb)
651 bfd_byte minor_opcode = lsb & 0x1f;
653 if (minor_opcode < 4)
654 return 6;
655 else if (minor_opcode == 0x10 || minor_opcode == 0x11)
656 return 8;
658 if (major_opcode == 0xa)
660 return 8;
662 /* Fall through. */
663 case bfd_mach_arc_arc600:
664 return (major_opcode > 0xb) ? 2 : 4;
665 break;
667 case bfd_mach_arc_arcv2:
668 return (major_opcode > 0x7) ? 2 : 4;
669 break;
671 default:
672 abort ();
676 /* Extract and return the value of OPERAND from the instruction whose value
677 is held in the array INSN. */
679 static int
680 extract_operand_value (const struct arc_operand *operand,
681 unsigned long long insn,
682 unsigned limm)
684 int value;
686 /* Read the limm operand, if required. */
687 if (operand->flags & ARC_OPERAND_LIMM)
688 /* The second part of the instruction value will have been loaded as
689 part of the find_format call made earlier. */
690 value = limm;
691 else
693 if (operand->extract)
694 value = (*operand->extract) (insn, (int *) NULL);
695 else
697 if (operand->flags & ARC_OPERAND_ALIGNED32)
699 value = (insn >> operand->shift)
700 & ((1 << (operand->bits - 2)) - 1);
701 value = value << 2;
703 else
705 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
707 if (operand->flags & ARC_OPERAND_SIGNED)
709 int signbit = 1 << (operand->bits - 1);
710 value = (value ^ signbit) - signbit;
715 return value;
718 /* Find the next operand, and the operands value from ITER. Return TRUE if
719 there is another operand, otherwise return FALSE. If there is an
720 operand returned then the operand is placed into OPERAND, and the value
721 into VALUE. If there is no operand returned then OPERAND and VALUE are
722 unchanged. */
724 static bfd_boolean
725 operand_iterator_next (struct arc_operand_iterator *iter,
726 const struct arc_operand **operand,
727 int *value)
729 if (*iter->opidx == 0)
731 *operand = NULL;
732 return FALSE;
735 *operand = &arc_operands[*iter->opidx];
736 *value = extract_operand_value (*operand, iter->insn, iter->limm);
737 iter->opidx++;
739 return TRUE;
742 /* Helper for parsing the options. */
744 static void
745 parse_option (const char *option)
747 if (disassembler_options_cmp (option, "dsp") == 0)
748 add_to_decodelist (DSP, NONE);
750 else if (disassembler_options_cmp (option, "spfp") == 0)
751 add_to_decodelist (FLOAT, SPX);
753 else if (disassembler_options_cmp (option, "dpfp") == 0)
754 add_to_decodelist (FLOAT, DPX);
756 else if (disassembler_options_cmp (option, "quarkse_em") == 0)
758 add_to_decodelist (FLOAT, DPX);
759 add_to_decodelist (FLOAT, SPX);
760 add_to_decodelist (FLOAT, QUARKSE1);
761 add_to_decodelist (FLOAT, QUARKSE2);
764 else if (disassembler_options_cmp (option, "fpuda") == 0)
765 add_to_decodelist (FLOAT, DPA);
767 else if (disassembler_options_cmp (option, "fpus") == 0)
769 add_to_decodelist (FLOAT, SP);
770 add_to_decodelist (FLOAT, CVT);
773 else if (disassembler_options_cmp (option, "fpud") == 0)
775 add_to_decodelist (FLOAT, DP);
776 add_to_decodelist (FLOAT, CVT);
778 else if (CONST_STRNEQ (option, "hex"))
779 print_hex = TRUE;
780 else
781 /* xgettext:c-format */
782 opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
785 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \
786 { #NAME, ARC_OPCODE_ARC600, "ARC600" }
787 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \
788 { #NAME, ARC_OPCODE_ARC700, "ARC700" }
789 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \
790 { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" }
791 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \
792 { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" }
793 #define ARC_CPU_TYPE_NONE \
794 { 0, 0, 0 }
796 /* A table of CPU names and opcode sets. */
797 static const struct cpu_type
799 const char *name;
800 unsigned flags;
801 const char *isa;
803 cpu_types[] =
805 #include "elf/arc-cpu.def"
808 /* Helper for parsing the CPU options. Accept any of the ARC architectures
809 values. OPTION should be a value passed to cpu=. */
811 static unsigned
812 parse_cpu_option (const char *option)
814 int i;
816 for (i = 0; cpu_types[i].name; ++i)
818 if (!disassembler_options_cmp (cpu_types[i].name, option))
820 return cpu_types[i].flags;
824 /* xgettext:c-format */
825 opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
826 return ARC_OPCODE_NONE;
829 /* Go over the options list and parse it. */
831 static void
832 parse_disassembler_options (const char *options)
834 const char *option;
836 if (options == NULL)
837 return;
839 /* Disassembler might be reused for difference CPU's, and cpu option set for
840 the first one shouldn't be applied to second (which might not have
841 explicit cpu in its options. Therefore it is required to reset enforced
842 CPU when new options are being parsed. */
843 enforced_isa_mask = ARC_OPCODE_NONE;
845 FOR_EACH_DISASSEMBLER_OPTION (option, options)
847 /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a
848 preprocessor macro. */
849 if (strncmp (option, "cpu=", 4) == 0)
850 /* Strip leading `cpu=`. */
851 enforced_isa_mask = parse_cpu_option (option + 4);
852 else
853 parse_option (option);
857 /* Return the instruction type for an instruction described by OPCODE. */
859 static enum dis_insn_type
860 arc_opcode_to_insn_type (const struct arc_opcode *opcode)
862 enum dis_insn_type insn_type;
864 switch (opcode->insn_class)
866 case BRANCH:
867 case BBIT0:
868 case BBIT1:
869 case BI:
870 case BIH:
871 case BRCC:
872 case EI:
873 case JLI:
874 case JUMP:
875 case LOOP:
876 if (!strncmp (opcode->name, "bl", 2)
877 || !strncmp (opcode->name, "jl", 2))
879 if (opcode->subclass == COND)
880 insn_type = dis_condjsr;
881 else
882 insn_type = dis_jsr;
884 else
886 if (opcode->subclass == COND)
887 insn_type = dis_condbranch;
888 else
889 insn_type = dis_branch;
891 break;
892 case LOAD:
893 case STORE:
894 case MEMORY:
895 case ENTER:
896 case PUSH:
897 case POP:
898 insn_type = dis_dref;
899 break;
900 case LEAVE:
901 insn_type = dis_branch;
902 break;
903 default:
904 insn_type = dis_nonbranch;
905 break;
908 return insn_type;
911 /* Disassemble ARC instructions. */
913 static int
914 print_insn_arc (bfd_vma memaddr,
915 struct disassemble_info *info)
917 bfd_byte buffer[8];
918 unsigned int highbyte, lowbyte;
919 int status;
920 unsigned int insn_len;
921 unsigned long long insn = 0;
922 unsigned isa_mask = ARC_OPCODE_NONE;
923 const struct arc_opcode *opcode;
924 bfd_boolean need_comma;
925 bfd_boolean open_braket;
926 int size;
927 const struct arc_operand *operand;
928 int value, vpcl;
929 struct arc_operand_iterator iter;
930 struct arc_disassemble_info *arc_infop;
931 bfd_boolean rpcl = FALSE, rset = FALSE;
933 if (info->disassembler_options)
935 parse_disassembler_options (info->disassembler_options);
937 /* Avoid repeated parsing of the options. */
938 info->disassembler_options = NULL;
941 if (info->private_data == NULL && !init_arc_disasm_info (info))
942 return -1;
944 memset (&iter, 0, sizeof (iter));
945 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
946 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
948 /* Figure out CPU type, unless it was enforced via disassembler options. */
949 if (enforced_isa_mask == ARC_OPCODE_NONE)
951 Elf_Internal_Ehdr *header = NULL;
953 if (info->section && info->section->owner)
954 header = elf_elfheader (info->section->owner);
956 switch (info->mach)
958 case bfd_mach_arc_arc700:
959 isa_mask = ARC_OPCODE_ARC700;
960 break;
962 case bfd_mach_arc_arc600:
963 isa_mask = ARC_OPCODE_ARC600;
964 break;
966 case bfd_mach_arc_arcv2:
967 default:
968 isa_mask = ARC_OPCODE_ARCv2EM;
969 /* TODO: Perhaps remove definition of header since it is only used at
970 this location. */
971 if (header != NULL
972 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
973 isa_mask = ARC_OPCODE_ARCv2HS;
974 break;
977 else
978 isa_mask = enforced_isa_mask;
980 if (isa_mask == ARC_OPCODE_ARCv2HS)
982 /* FPU instructions are not extensions for HS. */
983 add_to_decodelist (FLOAT, SP);
984 add_to_decodelist (FLOAT, DP);
985 add_to_decodelist (FLOAT, CVT);
988 /* This variable may be set by the instruction decoder. It suggests
989 the number of bytes objdump should display on a single line. If
990 the instruction decoder sets this, it should always set it to
991 the same value in order to get reasonable looking output. */
993 info->bytes_per_line = 8;
995 /* In the next lines, we set two info variables control the way
996 objdump displays the raw data. For example, if bytes_per_line is
997 8 and bytes_per_chunk is 4, the output will look like this:
998 00: 00000000 00000000
999 with the chunks displayed according to "display_endian". */
1001 if (info->section
1002 && !(info->section->flags & SEC_CODE))
1004 /* This is not a CODE section. */
1005 switch (info->section->size)
1007 case 1:
1008 case 2:
1009 case 4:
1010 size = info->section->size;
1011 break;
1012 default:
1013 size = (info->section->size & 0x01) ? 1 : 4;
1014 break;
1016 info->bytes_per_chunk = 1;
1017 info->display_endian = info->endian;
1019 else
1021 size = 2;
1022 info->bytes_per_chunk = 2;
1023 info->display_endian = info->endian;
1026 /* Read the insn into a host word. */
1027 status = (*info->read_memory_func) (memaddr, buffer, size, info);
1029 if (status != 0)
1031 (*info->memory_error_func) (status, memaddr, info);
1032 return -1;
1035 if (info->section
1036 && !(info->section->flags & SEC_CODE))
1038 /* Data section. */
1039 unsigned long data;
1041 data = bfd_get_bits (buffer, size * 8,
1042 info->display_endian == BFD_ENDIAN_BIG);
1043 switch (size)
1045 case 1:
1046 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
1047 break;
1048 case 2:
1049 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
1050 break;
1051 case 4:
1052 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
1053 break;
1054 default:
1055 abort ();
1057 return size;
1060 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1061 pr_debug ("instruction length = %d bytes\n", insn_len);
1062 arc_infop = info->private_data;
1063 arc_infop->insn_len = insn_len;
1065 switch (insn_len)
1067 case 2:
1068 insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1069 break;
1071 case 4:
1073 /* This is a long instruction: Read the remaning 2 bytes. */
1074 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1075 if (status != 0)
1077 (*info->memory_error_func) (status, memaddr + 2, info);
1078 return -1;
1080 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1082 break;
1084 case 6:
1086 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1087 if (status != 0)
1089 (*info->memory_error_func) (status, memaddr + 2, info);
1090 return -1;
1092 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1093 insn |= ((unsigned long long) buffer[highbyte] << 40)
1094 | ((unsigned long long) buffer[lowbyte] << 32);
1096 break;
1098 case 8:
1100 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1101 if (status != 0)
1103 (*info->memory_error_func) (status, memaddr + 2, info);
1104 return -1;
1106 insn =
1107 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1108 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1110 break;
1112 default:
1113 /* There is no instruction whose length is not 2, 4, 6, or 8. */
1114 abort ();
1117 pr_debug ("instruction value = %llx\n", insn);
1119 /* Set some defaults for the insn info. */
1120 info->insn_info_valid = 1;
1121 info->branch_delay_insns = 0;
1122 info->data_size = 4;
1123 info->insn_type = dis_nonbranch;
1124 info->target = 0;
1125 info->target2 = 0;
1127 /* FIXME to be moved in dissasemble_init_for_target. */
1128 info->disassembler_needs_relocs = TRUE;
1130 /* Find the first match in the opcode table. */
1131 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1132 return -1;
1134 if (!opcode)
1136 switch (insn_len)
1138 case 2:
1139 (*info->fprintf_func) (info->stream, ".shor\t%#04llx",
1140 insn & 0xffff);
1141 break;
1142 case 4:
1143 (*info->fprintf_func) (info->stream, ".word\t%#08llx",
1144 insn & 0xffffffff);
1145 break;
1146 case 6:
1147 (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1148 insn & 0xffffffff);
1149 (*info->fprintf_func) (info->stream, ".long\t%#04llx",
1150 (insn >> 32) & 0xffff);
1151 break;
1152 case 8:
1153 (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1154 insn & 0xffffffff);
1155 (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1156 insn >> 32);
1157 break;
1158 default:
1159 abort ();
1162 info->insn_type = dis_noninsn;
1163 return insn_len;
1166 /* Print the mnemonic. */
1167 (*info->fprintf_func) (info->stream, "%s", opcode->name);
1169 /* Preselect the insn class. */
1170 info->insn_type = arc_opcode_to_insn_type (opcode);
1172 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1174 print_flags (opcode, &insn, info);
1176 if (opcode->operands[0] != 0)
1177 (*info->fprintf_func) (info->stream, "\t");
1179 need_comma = FALSE;
1180 open_braket = FALSE;
1181 arc_infop->operands_count = 0;
1183 /* Now extract and print the operands. */
1184 operand = NULL;
1185 vpcl = 0;
1186 while (operand_iterator_next (&iter, &operand, &value))
1188 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1190 (*info->fprintf_func) (info->stream, "]");
1191 open_braket = FALSE;
1192 continue;
1195 /* Only take input from real operands. */
1196 if (ARC_OPERAND_IS_FAKE (operand))
1197 continue;
1199 if ((operand->flags & ARC_OPERAND_IGNORE)
1200 && (operand->flags & ARC_OPERAND_IR)
1201 && value == -1)
1202 continue;
1204 if (operand->flags & ARC_OPERAND_COLON)
1206 (*info->fprintf_func) (info->stream, ":");
1207 continue;
1210 if (need_comma)
1211 (*info->fprintf_func) (info->stream, ",");
1213 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1215 (*info->fprintf_func) (info->stream, "[");
1216 open_braket = TRUE;
1217 need_comma = FALSE;
1218 continue;
1221 need_comma = TRUE;
1223 if (operand->flags & ARC_OPERAND_PCREL)
1225 rpcl = TRUE;
1226 vpcl = value;
1227 rset = TRUE;
1229 info->target = (bfd_vma) (memaddr & ~3) + value;
1231 else if (!(operand->flags & ARC_OPERAND_IR))
1233 vpcl = value;
1234 rset = TRUE;
1237 /* Print the operand as directed by the flags. */
1238 if (operand->flags & ARC_OPERAND_IR)
1240 const char *rname;
1242 assert (value >=0 && value < 64);
1243 rname = arcExtMap_coreRegName (value);
1244 if (!rname)
1245 rname = regnames[value];
1246 (*info->fprintf_func) (info->stream, "%s", rname);
1247 if (operand->flags & ARC_OPERAND_TRUNCATE)
1249 rname = arcExtMap_coreRegName (value + 1);
1250 if (!rname)
1251 rname = regnames[value + 1];
1252 (*info->fprintf_func) (info->stream, "%s", rname);
1254 if (value == 63)
1255 rpcl = TRUE;
1256 else
1257 rpcl = FALSE;
1259 else if (operand->flags & ARC_OPERAND_LIMM)
1261 const char *rname = get_auxreg (opcode, value, isa_mask);
1263 if (rname && open_braket)
1264 (*info->fprintf_func) (info->stream, "%s", rname);
1265 else
1267 (*info->fprintf_func) (info->stream, "%#x", value);
1268 if (info->insn_type == dis_branch
1269 || info->insn_type == dis_jsr)
1270 info->target = (bfd_vma) value;
1273 else if (operand->flags & ARC_OPERAND_SIGNED)
1275 const char *rname = get_auxreg (opcode, value, isa_mask);
1276 if (rname && open_braket)
1277 (*info->fprintf_func) (info->stream, "%s", rname);
1278 else
1280 if (print_hex)
1281 (*info->fprintf_func) (info->stream, "%#x", value);
1282 else
1283 (*info->fprintf_func) (info->stream, "%d", value);
1286 else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1288 const char *addrtype = get_addrtype (value);
1289 (*info->fprintf_func) (info->stream, "%s", addrtype);
1290 /* A colon follow an address type. */
1291 need_comma = FALSE;
1293 else
1295 if (operand->flags & ARC_OPERAND_TRUNCATE
1296 && !(operand->flags & ARC_OPERAND_ALIGNED32)
1297 && !(operand->flags & ARC_OPERAND_ALIGNED16)
1298 && value >= 0 && value <= 14)
1300 /* Leave/Enter mnemonics. */
1301 switch (value)
1303 case 0:
1304 need_comma = FALSE;
1305 break;
1306 case 1:
1307 (*info->fprintf_func) (info->stream, "r13");
1308 break;
1309 default:
1310 (*info->fprintf_func) (info->stream, "r13-%s",
1311 regnames[13 + value - 1]);
1312 break;
1314 rpcl = FALSE;
1315 rset = FALSE;
1317 else
1319 const char *rname = get_auxreg (opcode, value, isa_mask);
1320 if (rname && open_braket)
1321 (*info->fprintf_func) (info->stream, "%s", rname);
1322 else
1323 (*info->fprintf_func) (info->stream, "%#x", value);
1327 if (operand->flags & ARC_OPERAND_LIMM)
1329 arc_infop->operands[arc_infop->operands_count].kind
1330 = ARC_OPERAND_KIND_LIMM;
1331 /* It is not important to have exactly the LIMM indicator
1332 here. */
1333 arc_infop->operands[arc_infop->operands_count].value = 63;
1335 else
1337 arc_infop->operands[arc_infop->operands_count].value = value;
1338 arc_infop->operands[arc_infop->operands_count].kind
1339 = (operand->flags & ARC_OPERAND_IR
1340 ? ARC_OPERAND_KIND_REG
1341 : ARC_OPERAND_KIND_SHIMM);
1343 arc_infop->operands_count ++;
1346 /* Pretty print extra info for pc-relative operands. */
1347 if (rpcl && rset)
1349 if (info->flags & INSN_HAS_RELOC)
1350 /* If the instruction has a reloc associated with it, then the
1351 offset field in the instruction will actually be the addend
1352 for the reloc. (We are using REL type relocs). In such
1353 cases, we can ignore the pc when computing addresses, since
1354 the addend is not currently pc-relative. */
1355 memaddr = 0;
1357 (*info->fprintf_func) (info->stream, "\t;");
1358 (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1361 return insn_len;
1365 disassembler_ftype
1366 arc_get_disassembler (bfd *abfd)
1368 /* BFD my be absent, if opcodes is invoked from the debugger that
1369 has connected to remote target and doesn't have an ELF file. */
1370 if (abfd != NULL)
1372 /* Read the extension insns and registers, if any. */
1373 build_ARC_extmap (abfd);
1374 #ifdef DEBUG
1375 dump_ARC_extmap ();
1376 #endif
1379 return print_insn_arc;
1382 void
1383 print_arc_disassembler_options (FILE *stream)
1385 int i;
1387 fprintf (stream, _("\n\
1388 The following ARC specific disassembler options are supported for use \n\
1389 with -M switch (multiple options should be separated by commas):\n"));
1391 /* cpu=... options. */
1392 for (i = 0; cpu_types[i].name; ++i)
1394 /* As of now all value CPU values are less than 16 characters. */
1395 fprintf (stream, " cpu=%-16s\tEnforce %s ISA.\n",
1396 cpu_types[i].name, cpu_types[i].isa);
1399 fprintf (stream, _("\
1400 dsp Recognize DSP instructions.\n"));
1401 fprintf (stream, _("\
1402 spfp Recognize FPX SP instructions.\n"));
1403 fprintf (stream, _("\
1404 dpfp Recognize FPX DP instructions.\n"));
1405 fprintf (stream, _("\
1406 quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1407 fprintf (stream, _("\
1408 fpuda Recognize double assist FPU instructions.\n"));
1409 fprintf (stream, _("\
1410 fpus Recognize single precision FPU instructions.\n"));
1411 fprintf (stream, _("\
1412 fpud Recognize double precision FPU instructions.\n"));
1413 fprintf (stream, _("\
1414 hex Use only hexadecimal number to print immediates.\n"));
1417 void arc_insn_decode (bfd_vma addr,
1418 struct disassemble_info *info,
1419 disassembler_ftype disasm_func,
1420 struct arc_instruction *insn)
1422 const struct arc_opcode *opcode;
1423 struct arc_disassemble_info *arc_infop;
1425 /* Ensure that insn would be in the reset state. */
1426 memset (insn, 0, sizeof (struct arc_instruction));
1428 /* There was an error when disassembling, for example memory read error. */
1429 if (disasm_func (addr, info) < 0)
1431 insn->valid = FALSE;
1432 return;
1435 assert (info->private_data != NULL);
1436 arc_infop = info->private_data;
1438 insn->length = arc_infop->insn_len;;
1439 insn->address = addr;
1441 /* Quick exit if memory at this address is not an instruction. */
1442 if (info->insn_type == dis_noninsn)
1444 insn->valid = FALSE;
1445 return;
1448 insn->valid = TRUE;
1450 opcode = (const struct arc_opcode *) arc_infop->opcode;
1451 insn->insn_class = opcode->insn_class;
1452 insn->limm_value = arc_infop->limm;
1453 insn->limm_p = arc_infop->limm_p;
1455 insn->is_control_flow = (info->insn_type == dis_branch
1456 || info->insn_type == dis_condbranch
1457 || info->insn_type == dis_jsr
1458 || info->insn_type == dis_condjsr);
1460 insn->has_delay_slot = info->branch_delay_insns;
1461 insn->writeback_mode
1462 = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1463 insn->data_size_mode = info->data_size;
1464 insn->condition_code = arc_infop->condition_code;
1465 memcpy (insn->operands, arc_infop->operands,
1466 sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1467 insn->operands_count = arc_infop->operands_count;
1470 /* Local variables:
1471 eval: (c-set-style "gnu")
1472 indent-tabs-mode: t
1473 End: */