1 /* Instruction printing code for the ARC.
2 Copyright (C) 1994-2018 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)
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. */
27 #include "opcode/arc.h"
32 #include "libiberty.h"
35 /* Structure used to iterate over, and extract the values for, operands of
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. */
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. */
63 /* TRUE if we have limm. */
66 /* LIMM value, if exists. */
69 /* Condition code, if exists. */
70 unsigned condition_code
;
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
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. */
131 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
133 # define pr_debug(fmt, args...)
136 #define ARRANGE_ENDIAN(info, buf) \
137 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (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. */
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
)
156 info
->private_data
= arc_infop
;
160 /* Add a new element to the decode list. */
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
;
174 /* Return TRUE if we need to skip the opcode from being
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)
187 /* or not a known truble class. */
188 switch (opcode
->insn_class
)
200 if ((t
->insn_class
== opcode
->insn_class
)
201 && (t
->subclass
== opcode
->subclass
))
210 bfd_getm32 (unsigned int data
)
214 value
= ((data
& 0xff00) | (data
& 0xff)) << 16;
215 value
|= ((data
& 0xff0000) | (data
& 0xff000000)) >> 16;
220 special_flag_p (const char *opname
,
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
))
233 /* Found potential special case instruction. */
236 flgidx
= flg_spec
->flags
[j
];
238 break; /* End of the array. */
240 if (strcmp (flgname
, arc_flag_operands
[flgidx
].name
) == 0)
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
,
256 bfd_boolean
*has_limm
,
257 bfd_boolean overlaps
)
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
))
275 if (arc_opcode_len (opcode
) != (int) insn_len
)
278 if ((insn
& opcode
->mask
) != opcode
->opcode
)
283 /* Possible candidate, check the operands. */
284 for (opidx
= opcode
->operands
; *opidx
; opidx
++)
287 const struct arc_operand
*operand
= &arc_operands
[*opidx
];
289 if (operand
->flags
& ARC_OPERAND_FAKE
)
292 if (operand
->extract
)
293 value
= (*operand
->extract
) (insn
, &invalid
);
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))
311 if (operand
->flags
& ARC_OPERAND_LIMM
312 && !(operand
->flags
& ARC_OPERAND_DUPLICATE
))
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;
325 /* Check first the extensions. */
326 if (cl_flags
->flag_class
& F_CLASS_EXTEND
)
328 value
= (insn
& 0x1F);
329 if (arcExtMap_condCodeName (value
))
333 /* Check for the implicit flags. */
334 if (cl_flags
->flag_class
& F_CLASS_IMPLICIT
)
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
)
350 if (!foundA
&& foundB
)
365 if (skip_this_opcode (opcode
))
369 /* The instruction is valid. */
372 while (opcode
->mask
);
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"));
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
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
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
412 find_format (bfd_vma memaddr
,
413 unsigned long long insn
,
414 unsigned int * insn_len
,
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
;
424 struct arc_disassemble_info
*arc_infop
= info
->private_data
;
426 /* First, try the extension instructions. */
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
);
437 (*info
->fprintf_func
) (info
->stream
, "\
438 An error occured while generating the extension instruction operations");
439 *opcode_result
= NULL
;
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. */
450 opcode
= find_format_from_table (info
, arc_opcodes
, insn
, *insn_len
,
451 isa_mask
, &needs_limm
, TRUE
);
453 if (needs_limm
&& opcode
!= NULL
)
458 status
= (*info
->read_memory_func
) (memaddr
+ *insn_len
, buffer
,
466 limm
= ARRANGE_ENDIAN (info
, buffer
);
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
;
490 print_flags (const struct arc_opcode
*opcode
,
491 unsigned long long *insn
,
492 struct disassemble_info
*info
)
494 const unsigned char *flgidx
;
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
)
509 value
= (insn
[0] & 0x1F);
511 name
= arcExtMap_condCodeName (value
);
514 (*info
->fprintf_func
) (info
->stream
, ".%s", name
);
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
;
536 if (!flg_operand
->favail
)
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])
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
);
587 get_auxreg (const struct arc_opcode
*opcode
,
593 const struct arc_aux_reg
*auxr
= &arc_aux_regs
[0];
595 if (opcode
->insn_class
!= AUXREG
)
598 name
= arcExtMap_auxRegName (value
);
602 for (i
= 0; i
< arc_num_aux_regs
; i
++, auxr
++)
604 if (!(auxr
->cpu
& isa_mask
))
607 if (auxr
->subclass
!= NONE
)
610 if (auxr
->address
== value
)
616 /* Convert a value representing an address type to a string used to refer to
617 the address type in assembly code. */
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. */
637 arc_insn_length (bfd_byte msb
, bfd_byte lsb
, struct disassemble_info
*info
)
639 bfd_byte major_opcode
= msb
>> 3;
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)
655 else if (minor_opcode
== 0x10 || minor_opcode
== 0x11)
658 if (major_opcode
== 0xa)
663 case bfd_mach_arc_arc600
:
664 return (major_opcode
> 0xb) ? 2 : 4;
667 case bfd_mach_arc_arcv2
:
668 return (major_opcode
> 0x7) ? 2 : 4;
676 /* Extract and return the value of OPERAND from the instruction whose value
677 is held in the array INSN. */
680 extract_operand_value (const struct arc_operand
*operand
,
681 unsigned long long insn
,
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. */
693 if (operand
->extract
)
694 value
= (*operand
->extract
) (insn
, (int *) NULL
);
697 if (operand
->flags
& ARC_OPERAND_ALIGNED32
)
699 value
= (insn
>> operand
->shift
)
700 & ((1 << (operand
->bits
- 2)) - 1);
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
;
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
725 operand_iterator_next (struct arc_operand_iterator
*iter
,
726 const struct arc_operand
**operand
,
729 if (*iter
->opidx
== 0)
735 *operand
= &arc_operands
[*iter
->opidx
];
736 *value
= extract_operand_value (*operand
, iter
->insn
, iter
->limm
);
742 /* Helper for parsing the options. */
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"))
781 fprintf (stderr
, _("Unrecognised disassembler option: %s\n"), option
);
784 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \
785 { #NAME, ARC_OPCODE_ARC600, "ARC600" }
786 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \
787 { #NAME, ARC_OPCODE_ARC700, "ARC700" }
788 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \
789 { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" }
790 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \
791 { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" }
792 #define ARC_CPU_TYPE_NONE \
795 /* A table of CPU names and opcode sets. */
796 static const struct cpu_type
804 #include "elf/arc-cpu.def"
807 /* Helper for parsing the CPU options. Accept any of the ARC architectures
808 values. OPTION should be a value passed to cpu=. */
811 parse_cpu_option (const char *option
)
815 for (i
= 0; cpu_types
[i
].name
; ++i
)
817 if (!disassembler_options_cmp (cpu_types
[i
].name
, option
))
819 return cpu_types
[i
].flags
;
823 fprintf (stderr
, _("Unrecognised disassembler CPU option: %s\n"), option
);
824 return ARC_OPCODE_NONE
;
827 /* Go over the options list and parse it. */
830 parse_disassembler_options (const char *options
)
837 /* Disassembler might be reused for difference CPU's, and cpu option set for
838 the first one shouldn't be applied to second (which might not have
839 explicit cpu in its options. Therefore it is required to reset enforced
840 CPU when new options are being parsed. */
841 enforced_isa_mask
= ARC_OPCODE_NONE
;
843 FOR_EACH_DISASSEMBLER_OPTION (option
, options
)
845 /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a
846 preprocessor macro. */
847 if (strncmp (option
, "cpu=", 4) == 0)
848 /* Strip leading `cpu=`. */
849 enforced_isa_mask
= parse_cpu_option (option
+ 4);
851 parse_option (option
);
855 /* Return the instruction type for an instruction described by OPCODE. */
857 static enum dis_insn_type
858 arc_opcode_to_insn_type (const struct arc_opcode
*opcode
)
860 enum dis_insn_type insn_type
;
862 switch (opcode
->insn_class
)
874 if (!strncmp (opcode
->name
, "bl", 2)
875 || !strncmp (opcode
->name
, "jl", 2))
877 if (opcode
->subclass
== COND
)
878 insn_type
= dis_condjsr
;
884 if (opcode
->subclass
== COND
)
885 insn_type
= dis_condbranch
;
887 insn_type
= dis_branch
;
896 insn_type
= dis_dref
;
899 insn_type
= dis_branch
;
902 insn_type
= dis_nonbranch
;
909 /* Disassemble ARC instructions. */
912 print_insn_arc (bfd_vma memaddr
,
913 struct disassemble_info
*info
)
916 unsigned int highbyte
, lowbyte
;
918 unsigned int insn_len
;
919 unsigned long long insn
= 0;
920 unsigned isa_mask
= ARC_OPCODE_NONE
;
921 const struct arc_opcode
*opcode
;
922 bfd_boolean need_comma
;
923 bfd_boolean open_braket
;
925 const struct arc_operand
*operand
;
927 struct arc_operand_iterator iter
;
928 struct arc_disassemble_info
*arc_infop
;
929 bfd_boolean rpcl
= FALSE
, rset
= FALSE
;
931 if (info
->disassembler_options
)
933 parse_disassembler_options (info
->disassembler_options
);
935 /* Avoid repeated parsing of the options. */
936 info
->disassembler_options
= NULL
;
939 if (info
->private_data
== NULL
&& !init_arc_disasm_info (info
))
942 memset (&iter
, 0, sizeof (iter
));
943 highbyte
= ((info
->endian
== BFD_ENDIAN_LITTLE
) ? 1 : 0);
944 lowbyte
= ((info
->endian
== BFD_ENDIAN_LITTLE
) ? 0 : 1);
946 /* Figure out CPU type, unless it was enforced via disassembler options. */
947 if (enforced_isa_mask
== ARC_OPCODE_NONE
)
949 Elf_Internal_Ehdr
*header
= NULL
;
951 if (info
->section
&& info
->section
->owner
)
952 header
= elf_elfheader (info
->section
->owner
);
956 case bfd_mach_arc_arc700
:
957 isa_mask
= ARC_OPCODE_ARC700
;
960 case bfd_mach_arc_arc600
:
961 isa_mask
= ARC_OPCODE_ARC600
;
964 case bfd_mach_arc_arcv2
:
966 isa_mask
= ARC_OPCODE_ARCv2EM
;
967 /* TODO: Perhaps remove definition of header since it is only used at
970 && (header
->e_flags
& EF_ARC_MACH_MSK
) == EF_ARC_CPU_ARCV2HS
)
971 isa_mask
= ARC_OPCODE_ARCv2HS
;
976 isa_mask
= enforced_isa_mask
;
978 if (isa_mask
== ARC_OPCODE_ARCv2HS
)
980 /* FPU instructions are not extensions for HS. */
981 add_to_decodelist (FLOAT
, SP
);
982 add_to_decodelist (FLOAT
, DP
);
983 add_to_decodelist (FLOAT
, CVT
);
986 /* This variable may be set by the instruction decoder. It suggests
987 the number of bytes objdump should display on a single line. If
988 the instruction decoder sets this, it should always set it to
989 the same value in order to get reasonable looking output. */
991 info
->bytes_per_line
= 8;
993 /* In the next lines, we set two info variables control the way
994 objdump displays the raw data. For example, if bytes_per_line is
995 8 and bytes_per_chunk is 4, the output will look like this:
996 00: 00000000 00000000
997 with the chunks displayed according to "display_endian". */
1000 && !(info
->section
->flags
& SEC_CODE
))
1002 /* This is not a CODE section. */
1003 switch (info
->section
->size
)
1008 size
= info
->section
->size
;
1011 size
= (info
->section
->size
& 0x01) ? 1 : 4;
1014 info
->bytes_per_chunk
= 1;
1015 info
->display_endian
= info
->endian
;
1020 info
->bytes_per_chunk
= 2;
1021 info
->display_endian
= info
->endian
;
1024 /* Read the insn into a host word. */
1025 status
= (*info
->read_memory_func
) (memaddr
, buffer
, size
, info
);
1029 (*info
->memory_error_func
) (status
, memaddr
, info
);
1034 && !(info
->section
->flags
& SEC_CODE
))
1039 data
= bfd_get_bits (buffer
, size
* 8,
1040 info
->display_endian
== BFD_ENDIAN_BIG
);
1044 (*info
->fprintf_func
) (info
->stream
, ".byte\t0x%02lx", data
);
1047 (*info
->fprintf_func
) (info
->stream
, ".short\t0x%04lx", data
);
1050 (*info
->fprintf_func
) (info
->stream
, ".word\t0x%08lx", data
);
1058 insn_len
= arc_insn_length (buffer
[highbyte
], buffer
[lowbyte
], info
);
1059 pr_debug ("instruction length = %d bytes\n", insn_len
);
1060 arc_infop
= info
->private_data
;
1061 arc_infop
->insn_len
= insn_len
;
1066 insn
= (buffer
[highbyte
] << 8) | buffer
[lowbyte
];
1071 /* This is a long instruction: Read the remaning 2 bytes. */
1072 status
= (*info
->read_memory_func
) (memaddr
+ 2, &buffer
[2], 2, info
);
1075 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
1078 insn
= (unsigned long long) ARRANGE_ENDIAN (info
, buffer
);
1084 status
= (*info
->read_memory_func
) (memaddr
+ 2, &buffer
[2], 4, info
);
1087 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
1090 insn
= (unsigned long long) ARRANGE_ENDIAN (info
, &buffer
[2]);
1091 insn
|= ((unsigned long long) buffer
[highbyte
] << 40)
1092 | ((unsigned long long) buffer
[lowbyte
] << 32);
1098 status
= (*info
->read_memory_func
) (memaddr
+ 2, &buffer
[2], 6, info
);
1101 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
1105 ((((unsigned long long) ARRANGE_ENDIAN (info
, buffer
)) << 32)
1106 | ((unsigned long long) ARRANGE_ENDIAN (info
, &buffer
[4])));
1111 /* There is no instruction whose length is not 2, 4, 6, or 8. */
1115 pr_debug ("instruction value = %llx\n", insn
);
1117 /* Set some defaults for the insn info. */
1118 info
->insn_info_valid
= 1;
1119 info
->branch_delay_insns
= 0;
1120 info
->data_size
= 4;
1121 info
->insn_type
= dis_nonbranch
;
1125 /* FIXME to be moved in dissasemble_init_for_target. */
1126 info
->disassembler_needs_relocs
= TRUE
;
1128 /* Find the first match in the opcode table. */
1129 if (!find_format (memaddr
, insn
, &insn_len
, isa_mask
, info
, &opcode
, &iter
))
1137 (*info
->fprintf_func
) (info
->stream
, ".shor\t%#04llx",
1141 (*info
->fprintf_func
) (info
->stream
, ".word\t%#08llx",
1145 (*info
->fprintf_func
) (info
->stream
, ".long\t%#08llx",
1147 (*info
->fprintf_func
) (info
->stream
, ".long\t%#04llx",
1148 (insn
>> 32) & 0xffff);
1151 (*info
->fprintf_func
) (info
->stream
, ".long\t%#08llx",
1153 (*info
->fprintf_func
) (info
->stream
, ".long\t%#08llx",
1160 info
->insn_type
= dis_noninsn
;
1164 /* Print the mnemonic. */
1165 (*info
->fprintf_func
) (info
->stream
, "%s", opcode
->name
);
1167 /* Preselect the insn class. */
1168 info
->insn_type
= arc_opcode_to_insn_type (opcode
);
1170 pr_debug ("%s: 0x%08llx\n", opcode
->name
, opcode
->opcode
);
1172 print_flags (opcode
, &insn
, info
);
1174 if (opcode
->operands
[0] != 0)
1175 (*info
->fprintf_func
) (info
->stream
, "\t");
1178 open_braket
= FALSE
;
1179 arc_infop
->operands_count
= 0;
1181 /* Now extract and print the operands. */
1184 while (operand_iterator_next (&iter
, &operand
, &value
))
1186 if (open_braket
&& (operand
->flags
& ARC_OPERAND_BRAKET
))
1188 (*info
->fprintf_func
) (info
->stream
, "]");
1189 open_braket
= FALSE
;
1193 /* Only take input from real operands. */
1194 if (ARC_OPERAND_IS_FAKE (operand
))
1197 if ((operand
->flags
& ARC_OPERAND_IGNORE
)
1198 && (operand
->flags
& ARC_OPERAND_IR
)
1202 if (operand
->flags
& ARC_OPERAND_COLON
)
1204 (*info
->fprintf_func
) (info
->stream
, ":");
1209 (*info
->fprintf_func
) (info
->stream
, ",");
1211 if (!open_braket
&& (operand
->flags
& ARC_OPERAND_BRAKET
))
1213 (*info
->fprintf_func
) (info
->stream
, "[");
1221 if (operand
->flags
& ARC_OPERAND_PCREL
)
1227 info
->target
= (bfd_vma
) (memaddr
& ~3) + value
;
1229 else if (!(operand
->flags
& ARC_OPERAND_IR
))
1235 /* Print the operand as directed by the flags. */
1236 if (operand
->flags
& ARC_OPERAND_IR
)
1240 assert (value
>=0 && value
< 64);
1241 rname
= arcExtMap_coreRegName (value
);
1243 rname
= regnames
[value
];
1244 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1245 if (operand
->flags
& ARC_OPERAND_TRUNCATE
)
1247 rname
= arcExtMap_coreRegName (value
+ 1);
1249 rname
= regnames
[value
+ 1];
1250 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1257 else if (operand
->flags
& ARC_OPERAND_LIMM
)
1259 const char *rname
= get_auxreg (opcode
, value
, isa_mask
);
1261 if (rname
&& open_braket
)
1262 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1265 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
1266 if (info
->insn_type
== dis_branch
1267 || info
->insn_type
== dis_jsr
)
1268 info
->target
= (bfd_vma
) value
;
1271 else if (operand
->flags
& ARC_OPERAND_SIGNED
)
1273 const char *rname
= get_auxreg (opcode
, value
, isa_mask
);
1274 if (rname
&& open_braket
)
1275 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1279 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
1281 (*info
->fprintf_func
) (info
->stream
, "%d", value
);
1284 else if (operand
->flags
& ARC_OPERAND_ADDRTYPE
)
1286 const char *addrtype
= get_addrtype (value
);
1287 (*info
->fprintf_func
) (info
->stream
, "%s", addrtype
);
1288 /* A colon follow an address type. */
1293 if (operand
->flags
& ARC_OPERAND_TRUNCATE
1294 && !(operand
->flags
& ARC_OPERAND_ALIGNED32
)
1295 && !(operand
->flags
& ARC_OPERAND_ALIGNED16
)
1296 && value
>= 0 && value
<= 14)
1298 /* Leave/Enter mnemonics. */
1305 (*info
->fprintf_func
) (info
->stream
, "r13");
1308 (*info
->fprintf_func
) (info
->stream
, "r13-%s",
1309 regnames
[13 + value
- 1]);
1317 const char *rname
= get_auxreg (opcode
, value
, isa_mask
);
1318 if (rname
&& open_braket
)
1319 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1321 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
1325 if (operand
->flags
& ARC_OPERAND_LIMM
)
1327 arc_infop
->operands
[arc_infop
->operands_count
].kind
1328 = ARC_OPERAND_KIND_LIMM
;
1329 /* It is not important to have exactly the LIMM indicator
1331 arc_infop
->operands
[arc_infop
->operands_count
].value
= 63;
1335 arc_infop
->operands
[arc_infop
->operands_count
].value
= value
;
1336 arc_infop
->operands
[arc_infop
->operands_count
].kind
1337 = (operand
->flags
& ARC_OPERAND_IR
1338 ? ARC_OPERAND_KIND_REG
1339 : ARC_OPERAND_KIND_SHIMM
);
1341 arc_infop
->operands_count
++;
1344 /* Pretty print extra info for pc-relative operands. */
1347 if (info
->flags
& INSN_HAS_RELOC
)
1348 /* If the instruction has a reloc associated with it, then the
1349 offset field in the instruction will actually be the addend
1350 for the reloc. (We are using REL type relocs). In such
1351 cases, we can ignore the pc when computing addresses, since
1352 the addend is not currently pc-relative. */
1355 (*info
->fprintf_func
) (info
->stream
, "\t;");
1356 (*info
->print_address_func
) ((memaddr
& ~3) + vpcl
, info
);
1364 arc_get_disassembler (bfd
*abfd
)
1366 /* BFD my be absent, if opcodes is invoked from the debugger that
1367 has connected to remote target and doesn't have an ELF file. */
1370 /* Read the extension insns and registers, if any. */
1371 build_ARC_extmap (abfd
);
1377 return print_insn_arc
;
1381 print_arc_disassembler_options (FILE *stream
)
1385 fprintf (stream
, _("\n\
1386 The following ARC specific disassembler options are supported for use \n\
1387 with -M switch (multiple options should be separated by commas):\n"));
1389 /* cpu=... options. */
1390 for (i
= 0; cpu_types
[i
].name
; ++i
)
1392 /* As of now all value CPU values are less than 16 characters. */
1393 fprintf (stream
, " cpu=%-16s\tEnforce %s ISA.\n",
1394 cpu_types
[i
].name
, cpu_types
[i
].isa
);
1397 fprintf (stream
, _("\
1398 dsp Recognize DSP instructions.\n"));
1399 fprintf (stream
, _("\
1400 spfp Recognize FPX SP instructions.\n"));
1401 fprintf (stream
, _("\
1402 dpfp Recognize FPX DP instructions.\n"));
1403 fprintf (stream
, _("\
1404 quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1405 fprintf (stream
, _("\
1406 fpuda Recognize double assist FPU instructions.\n"));
1407 fprintf (stream
, _("\
1408 fpus Recognize single precision FPU instructions.\n"));
1409 fprintf (stream
, _("\
1410 fpud Recognize double precision FPU instructions.\n"));
1411 fprintf (stream
, _("\
1412 hex Use only hexadecimal number to print immediates.\n"));
1415 void arc_insn_decode (bfd_vma addr
,
1416 struct disassemble_info
*info
,
1417 disassembler_ftype disasm_func
,
1418 struct arc_instruction
*insn
)
1420 const struct arc_opcode
*opcode
;
1421 struct arc_disassemble_info
*arc_infop
;
1423 /* Ensure that insn would be in the reset state. */
1424 memset (insn
, 0, sizeof (struct arc_instruction
));
1426 /* There was an error when disassembling, for example memory read error. */
1427 if (disasm_func (addr
, info
) < 0)
1429 insn
->valid
= FALSE
;
1433 assert (info
->private_data
!= NULL
);
1434 arc_infop
= info
->private_data
;
1436 insn
->length
= arc_infop
->insn_len
;;
1437 insn
->address
= addr
;
1439 /* Quick exit if memory at this address is not an instruction. */
1440 if (info
->insn_type
== dis_noninsn
)
1442 insn
->valid
= FALSE
;
1448 opcode
= (const struct arc_opcode
*) arc_infop
->opcode
;
1449 insn
->insn_class
= opcode
->insn_class
;
1450 insn
->limm_value
= arc_infop
->limm
;
1451 insn
->limm_p
= arc_infop
->limm_p
;
1453 insn
->is_control_flow
= (info
->insn_type
== dis_branch
1454 || info
->insn_type
== dis_condbranch
1455 || info
->insn_type
== dis_jsr
1456 || info
->insn_type
== dis_condjsr
);
1458 insn
->has_delay_slot
= info
->branch_delay_insns
;
1459 insn
->writeback_mode
1460 = (enum arc_ldst_writeback_mode
) arc_infop
->writeback_mode
;
1461 insn
->data_size_mode
= info
->data_size
;
1462 insn
->condition_code
= arc_infop
->condition_code
;
1463 memcpy (insn
->operands
, arc_infop
->operands
,
1464 sizeof (struct arc_insn_operand
) * MAX_INSN_ARGS
);
1465 insn
->operands_count
= arc_infop
->operands_count
;
1469 eval: (c-set-style "gnu")