1 /* Instruction printing code for the ARC.
2 Copyright (C) 1994-2017 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 /* Macros section. */
123 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
125 # define pr_debug(fmt, args...)
128 #define ARRANGE_ENDIAN(info, buf) \
129 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
132 #define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
133 (s + (sizeof (word) * 8 - 1 - e)))
134 #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
136 /* Functions implementation. */
138 /* Initialize private data. */
140 init_arc_disasm_info (struct disassemble_info
*info
)
142 struct arc_disassemble_info
*arc_infop
143 = calloc (sizeof (*arc_infop
), 1);
145 if (arc_infop
== NULL
)
148 info
->private_data
= arc_infop
;
152 /* Add a new element to the decode list. */
155 add_to_decodelist (insn_class_t insn_class
,
156 insn_subclass_t subclass
)
158 linkclass t
= (linkclass
) xmalloc (sizeof (skipclass_t
));
160 t
->insn_class
= insn_class
;
161 t
->subclass
= subclass
;
166 /* Return TRUE if we need to skip the opcode from being
170 skip_this_opcode (const struct arc_opcode
*opcode
)
172 linkclass t
= decodelist
;
174 /* Check opcode for major 0x06, return if it is not in. */
175 if (arc_opcode_len (opcode
) == 4
176 && OPCODE_32BIT_INSN (opcode
->opcode
) != 0x06)
179 /* or not a known truble class. */
180 switch (opcode
->insn_class
)
191 if ((t
->insn_class
== opcode
->insn_class
)
192 && (t
->subclass
== opcode
->subclass
))
201 bfd_getm32 (unsigned int data
)
205 value
= ((data
& 0xff00) | (data
& 0xff)) << 16;
206 value
|= ((data
& 0xff0000) | (data
& 0xff000000)) >> 16;
211 special_flag_p (const char *opname
,
214 const struct arc_flag_special
*flg_spec
;
215 unsigned i
, j
, flgidx
;
217 for (i
= 0; i
< arc_num_flag_special
; i
++)
219 flg_spec
= &arc_flag_special_cases
[i
];
221 if (strcmp (opname
, flg_spec
->name
))
224 /* Found potential special case instruction. */
227 flgidx
= flg_spec
->flags
[j
];
229 break; /* End of the array. */
231 if (strcmp (flgname
, arc_flag_operands
[flgidx
].name
) == 0)
238 /* Find opcode from ARC_TABLE given the instruction described by INSN and
239 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
241 static const struct arc_opcode
*
242 find_format_from_table (struct disassemble_info
*info
,
243 const struct arc_opcode
*arc_table
,
244 unsigned long long insn
,
245 unsigned int insn_len
,
247 bfd_boolean
*has_limm
,
248 bfd_boolean overlaps
)
251 const struct arc_opcode
*opcode
= NULL
;
252 const struct arc_opcode
*t_op
= NULL
;
253 const unsigned char *opidx
;
254 const unsigned char *flgidx
;
255 bfd_boolean warn_p
= FALSE
;
259 bfd_boolean invalid
= FALSE
;
261 opcode
= &arc_table
[i
++];
263 if (!(opcode
->cpu
& isa_mask
))
266 if (arc_opcode_len (opcode
) != (int) insn_len
)
269 if ((insn
& opcode
->mask
) != opcode
->opcode
)
274 /* Possible candidate, check the operands. */
275 for (opidx
= opcode
->operands
; *opidx
; opidx
++)
278 const struct arc_operand
*operand
= &arc_operands
[*opidx
];
280 if (operand
->flags
& ARC_OPERAND_FAKE
)
283 if (operand
->extract
)
284 value
= (*operand
->extract
) (insn
, &invalid
);
286 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
288 /* Check for LIMM indicator. If it is there, then make sure
289 we pick the right format. */
290 limmind
= (isa_mask
& ARC_OPCODE_ARCV2
) ? 0x1E : 0x3E;
291 if (operand
->flags
& ARC_OPERAND_IR
292 && !(operand
->flags
& ARC_OPERAND_LIMM
))
294 if ((value
== 0x3E && insn_len
== 4)
295 || (value
== limmind
&& insn_len
== 2))
302 if (operand
->flags
& ARC_OPERAND_LIMM
303 && !(operand
->flags
& ARC_OPERAND_DUPLICATE
))
307 /* Check the flags. */
308 for (flgidx
= opcode
->flags
; *flgidx
; flgidx
++)
310 /* Get a valid flag class. */
311 const struct arc_flag_class
*cl_flags
= &arc_flag_classes
[*flgidx
];
312 const unsigned *flgopridx
;
313 int foundA
= 0, foundB
= 0;
316 /* Check first the extensions. */
317 if (cl_flags
->flag_class
& F_CLASS_EXTEND
)
319 value
= (insn
& 0x1F);
320 if (arcExtMap_condCodeName (value
))
324 /* Check for the implicit flags. */
325 if (cl_flags
->flag_class
& F_CLASS_IMPLICIT
)
328 for (flgopridx
= cl_flags
->flags
; *flgopridx
; ++flgopridx
)
330 const struct arc_flag_operand
*flg_operand
=
331 &arc_flag_operands
[*flgopridx
];
333 value
= (insn
>> flg_operand
->shift
)
334 & ((1 << flg_operand
->bits
) - 1);
335 if (value
== flg_operand
->code
)
341 if (!foundA
&& foundB
)
356 if (skip_this_opcode (opcode
))
360 /* The instruction is valid. */
363 while (opcode
->mask
);
367 info
->fprintf_func (info
->stream
,
368 _("\nWarning: disassembly may be wrong due to "
369 "guessed opcode class choice.\n"
370 "Use -M<class[,class]> to select the correct "
371 "opcode class(es).\n\t\t\t\t"));
378 /* Find opcode for INSN, trying various different sources. The instruction
379 length in INSN_LEN will be updated if the instruction requires a LIMM
382 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
383 initialised, ready to iterate over the operands of the found opcode. If
384 the found opcode requires a LIMM then the LIMM value will be loaded into a
387 This function returns TRUE in almost all cases, FALSE is reserved to
388 indicate an error (failing to find an opcode is not an error) a returned
389 result of FALSE would indicate that the disassembler can't continue.
391 If no matching opcode is found then the returned result will be TRUE, the
392 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
393 INSN_LEN will be unchanged.
395 If a matching opcode is found, then the returned result will be TRUE, the
396 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
397 4 if the instruction requires a LIMM, and the LIMM value will have been
398 loaded into a field of ITER. Finally, ITER will have been initialised so
399 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
403 find_format (bfd_vma memaddr
,
404 unsigned long long insn
,
405 unsigned int * insn_len
,
407 struct disassemble_info
* info
,
408 const struct arc_opcode
** opcode_result
,
409 struct arc_operand_iterator
* iter
)
411 const struct arc_opcode
*opcode
= NULL
;
412 bfd_boolean needs_limm
;
413 const extInstruction_t
*einsn
, *i
;
415 struct arc_disassemble_info
*arc_infop
= info
->private_data
;
417 /* First, try the extension instructions. */
420 einsn
= arcExtMap_insn (OPCODE_32BIT_INSN (insn
), insn
);
421 for (i
= einsn
; (i
!= NULL
) && (opcode
== NULL
); i
= i
->next
)
423 const char *errmsg
= NULL
;
425 opcode
= arcExtMap_genOpcode (i
, isa_mask
, &errmsg
);
428 (*info
->fprintf_func
) (info
->stream
, "\
429 An error occured while generating the extension instruction operations");
430 *opcode_result
= NULL
;
434 opcode
= find_format_from_table (info
, opcode
, insn
, *insn_len
,
435 isa_mask
, &needs_limm
, FALSE
);
439 /* Then, try finding the first match in the opcode table. */
441 opcode
= find_format_from_table (info
, arc_opcodes
, insn
, *insn_len
,
442 isa_mask
, &needs_limm
, TRUE
);
444 if (needs_limm
&& opcode
!= NULL
)
449 status
= (*info
->read_memory_func
) (memaddr
+ *insn_len
, buffer
,
457 limm
= ARRANGE_ENDIAN (info
, buffer
);
466 iter
->opcode
= opcode
;
467 iter
->opidx
= opcode
->operands
;
470 *opcode_result
= opcode
;
472 /* Update private data. */
473 arc_infop
->opcode
= opcode
;
474 arc_infop
->limm
= (needs_limm
) ? limm
: 0;
475 arc_infop
->limm_p
= needs_limm
;
481 print_flags (const struct arc_opcode
*opcode
,
482 unsigned long long *insn
,
483 struct disassemble_info
*info
)
485 const unsigned char *flgidx
;
487 struct arc_disassemble_info
*arc_infop
= info
->private_data
;
489 /* Now extract and print the flags. */
490 for (flgidx
= opcode
->flags
; *flgidx
; flgidx
++)
492 /* Get a valid flag class. */
493 const struct arc_flag_class
*cl_flags
= &arc_flag_classes
[*flgidx
];
494 const unsigned *flgopridx
;
496 /* Check first the extensions. */
497 if (cl_flags
->flag_class
& F_CLASS_EXTEND
)
500 value
= (insn
[0] & 0x1F);
502 name
= arcExtMap_condCodeName (value
);
505 (*info
->fprintf_func
) (info
->stream
, ".%s", name
);
510 for (flgopridx
= cl_flags
->flags
; *flgopridx
; ++flgopridx
)
512 const struct arc_flag_operand
*flg_operand
=
513 &arc_flag_operands
[*flgopridx
];
515 /* Implicit flags are only used for the insn decoder. */
516 if (cl_flags
->flag_class
& F_CLASS_IMPLICIT
)
518 if (cl_flags
->flag_class
& F_CLASS_COND
)
519 arc_infop
->condition_code
= flg_operand
->code
;
520 else if (cl_flags
->flag_class
& F_CLASS_WB
)
521 arc_infop
->writeback_mode
= flg_operand
->code
;
522 else if (cl_flags
->flag_class
& F_CLASS_ZZ
)
523 info
->data_size
= flg_operand
->code
;
527 if (!flg_operand
->favail
)
530 value
= (insn
[0] >> flg_operand
->shift
)
531 & ((1 << flg_operand
->bits
) - 1);
532 if (value
== flg_operand
->code
)
534 /* FIXME!: print correctly nt/t flag. */
535 if (!special_flag_p (opcode
->name
, flg_operand
->name
))
536 (*info
->fprintf_func
) (info
->stream
, ".");
537 else if (info
->insn_type
== dis_dref
)
539 switch (flg_operand
->name
[0])
553 if (flg_operand
->name
[0] == 'd'
554 && flg_operand
->name
[1] == 0)
555 info
->branch_delay_insns
= 1;
557 /* Check if it is a conditional flag. */
558 if (cl_flags
->flag_class
& F_CLASS_COND
)
560 if (info
->insn_type
== dis_jsr
)
561 info
->insn_type
= dis_condjsr
;
562 else if (info
->insn_type
== dis_branch
)
563 info
->insn_type
= dis_condbranch
;
564 arc_infop
->condition_code
= flg_operand
->code
;
567 /* Check for the write back modes. */
568 if (cl_flags
->flag_class
& F_CLASS_WB
)
569 arc_infop
->writeback_mode
= flg_operand
->code
;
571 (*info
->fprintf_func
) (info
->stream
, "%s", flg_operand
->name
);
578 get_auxreg (const struct arc_opcode
*opcode
,
584 const struct arc_aux_reg
*auxr
= &arc_aux_regs
[0];
586 if (opcode
->insn_class
!= AUXREG
)
589 name
= arcExtMap_auxRegName (value
);
593 for (i
= 0; i
< arc_num_aux_regs
; i
++, auxr
++)
595 if (!(auxr
->cpu
& isa_mask
))
598 if (auxr
->subclass
!= NONE
)
601 if (auxr
->address
== value
)
607 /* Convert a value representing an address type to a string used to refer to
608 the address type in assembly code. */
611 get_addrtype (int value
)
613 if (value
< 0 || value
> addrtypenames_max
)
614 return addrtypeunknown
;
616 return addrtypenames
[value
];
619 /* Calculate the instruction length for an instruction starting with MSB
620 and LSB, the most and least significant byte. The ISA_MASK is used to
621 filter the instructions considered to only those that are part of the
622 current architecture.
624 The instruction lengths are calculated from the ARC_OPCODE table, and
625 cached for later use. */
628 arc_insn_length (bfd_byte msb
, bfd_byte lsb
, struct disassemble_info
*info
)
630 bfd_byte major_opcode
= msb
>> 3;
634 case bfd_mach_arc_arc700
:
635 /* The nps400 extension set requires this special casing of the
636 instruction length calculation. Right now this is not causing any
637 problems as none of the known extensions overlap in opcode space,
638 but, if they ever do then we might need to start carrying
639 information around in the elf about which extensions are in use. */
640 if (major_opcode
== 0xb)
642 bfd_byte minor_opcode
= lsb
& 0x1f;
644 if (minor_opcode
< 4)
646 else if (minor_opcode
== 0x10 || minor_opcode
== 0x11)
649 if (major_opcode
== 0xa)
654 case bfd_mach_arc_arc600
:
655 return (major_opcode
> 0xb) ? 2 : 4;
658 case bfd_mach_arc_arcv2
:
659 return (major_opcode
> 0x7) ? 2 : 4;
667 /* Extract and return the value of OPERAND from the instruction whose value
668 is held in the array INSN. */
671 extract_operand_value (const struct arc_operand
*operand
,
672 unsigned long long insn
,
677 /* Read the limm operand, if required. */
678 if (operand
->flags
& ARC_OPERAND_LIMM
)
679 /* The second part of the instruction value will have been loaded as
680 part of the find_format call made earlier. */
684 if (operand
->extract
)
685 value
= (*operand
->extract
) (insn
, (int *) NULL
);
688 if (operand
->flags
& ARC_OPERAND_ALIGNED32
)
690 value
= (insn
>> operand
->shift
)
691 & ((1 << (operand
->bits
- 2)) - 1);
696 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
698 if (operand
->flags
& ARC_OPERAND_SIGNED
)
700 int signbit
= 1 << (operand
->bits
- 1);
701 value
= (value
^ signbit
) - signbit
;
709 /* Find the next operand, and the operands value from ITER. Return TRUE if
710 there is another operand, otherwise return FALSE. If there is an
711 operand returned then the operand is placed into OPERAND, and the value
712 into VALUE. If there is no operand returned then OPERAND and VALUE are
716 operand_iterator_next (struct arc_operand_iterator
*iter
,
717 const struct arc_operand
**operand
,
720 if (*iter
->opidx
== 0)
726 *operand
= &arc_operands
[*iter
->opidx
];
727 *value
= extract_operand_value (*operand
, iter
->insn
, iter
->limm
);
733 /* Helper for parsing the options. */
736 parse_option (const char *option
)
738 if (CONST_STRNEQ (option
, "dsp"))
739 add_to_decodelist (DSP
, NONE
);
741 else if (CONST_STRNEQ (option
, "spfp"))
742 add_to_decodelist (FLOAT
, SPX
);
744 else if (CONST_STRNEQ (option
, "dpfp"))
745 add_to_decodelist (FLOAT
, DPX
);
747 else if (CONST_STRNEQ (option
, "quarkse_em"))
749 add_to_decodelist (FLOAT
, DPX
);
750 add_to_decodelist (FLOAT
, SPX
);
751 add_to_decodelist (FLOAT
, QUARKSE1
);
752 add_to_decodelist (FLOAT
, QUARKSE2
);
755 else if (CONST_STRNEQ (option
, "fpuda"))
756 add_to_decodelist (FLOAT
, DPA
);
758 else if (CONST_STRNEQ (option
, "fpus"))
760 add_to_decodelist (FLOAT
, SP
);
761 add_to_decodelist (FLOAT
, CVT
);
764 else if (CONST_STRNEQ (option
, "fpud"))
766 add_to_decodelist (FLOAT
, DP
);
767 add_to_decodelist (FLOAT
, CVT
);
770 fprintf (stderr
, _("Unrecognised disassembler option: %s\n"), option
);
773 /* Go over the options list and parse it. */
776 parse_disassembler_options (const char *options
)
783 /* Skip empty options. */
790 parse_option (options
);
792 while (*options
!= ',' && *options
!= '\0')
797 /* Return the instruction type for an instruction described by OPCODE. */
799 static enum dis_insn_type
800 arc_opcode_to_insn_type (const struct arc_opcode
*opcode
)
802 enum dis_insn_type insn_type
;
804 switch (opcode
->insn_class
)
816 if (!strncmp (opcode
->name
, "bl", 2)
817 || !strncmp (opcode
->name
, "jl", 2))
819 if (opcode
->subclass
== COND
)
820 insn_type
= dis_condjsr
;
826 if (opcode
->subclass
== COND
)
827 insn_type
= dis_condbranch
;
829 insn_type
= dis_branch
;
838 insn_type
= dis_dref
;
841 insn_type
= dis_branch
;
844 insn_type
= dis_nonbranch
;
851 /* Disassemble ARC instructions. */
854 print_insn_arc (bfd_vma memaddr
,
855 struct disassemble_info
*info
)
858 unsigned int highbyte
, lowbyte
;
860 unsigned int insn_len
;
861 unsigned long long insn
= 0;
863 const struct arc_opcode
*opcode
;
864 bfd_boolean need_comma
;
865 bfd_boolean open_braket
;
867 const struct arc_operand
*operand
;
869 struct arc_operand_iterator iter
;
870 Elf_Internal_Ehdr
*header
= NULL
;
871 struct arc_disassemble_info
*arc_infop
;
873 if (info
->disassembler_options
)
875 parse_disassembler_options (info
->disassembler_options
);
877 /* Avoid repeated parsing of the options. */
878 info
->disassembler_options
= NULL
;
881 if (info
->private_data
== NULL
&& !init_arc_disasm_info (info
))
884 memset (&iter
, 0, sizeof (iter
));
885 highbyte
= ((info
->endian
== BFD_ENDIAN_LITTLE
) ? 1 : 0);
886 lowbyte
= ((info
->endian
== BFD_ENDIAN_LITTLE
) ? 0 : 1);
888 if (info
->section
&& info
->section
->owner
)
889 header
= elf_elfheader (info
->section
->owner
);
893 case bfd_mach_arc_arc700
:
894 isa_mask
= ARC_OPCODE_ARC700
;
897 case bfd_mach_arc_arc600
:
898 isa_mask
= ARC_OPCODE_ARC600
;
901 case bfd_mach_arc_arcv2
:
903 isa_mask
= ARC_OPCODE_ARCv2EM
;
904 /* TODO: Perhaps remove defitinion of header since it is only used at
907 && (header
->e_flags
& EF_ARC_MACH_MSK
) == EF_ARC_CPU_ARCV2HS
)
909 isa_mask
= ARC_OPCODE_ARCv2HS
;
910 /* FPU instructions are not extensions for HS. */
911 add_to_decodelist (FLOAT
, SP
);
912 add_to_decodelist (FLOAT
, DP
);
913 add_to_decodelist (FLOAT
, CVT
);
918 /* This variable may be set by the instruction decoder. It suggests
919 the number of bytes objdump should display on a single line. If
920 the instruction decoder sets this, it should always set it to
921 the same value in order to get reasonable looking output. */
923 info
->bytes_per_line
= 8;
925 /* In the next lines, we set two info variables control the way
926 objdump displays the raw data. For example, if bytes_per_line is
927 8 and bytes_per_chunk is 4, the output will look like this:
928 00: 00000000 00000000
929 with the chunks displayed according to "display_endian". */
932 && !(info
->section
->flags
& SEC_CODE
))
934 /* This is not a CODE section. */
935 switch (info
->section
->size
)
940 size
= info
->section
->size
;
943 size
= (info
->section
->size
& 0x01) ? 1 : 4;
946 info
->bytes_per_chunk
= 1;
947 info
->display_endian
= info
->endian
;
952 info
->bytes_per_chunk
= 2;
953 info
->display_endian
= info
->endian
;
956 /* Read the insn into a host word. */
957 status
= (*info
->read_memory_func
) (memaddr
, buffer
, size
, info
);
960 (*info
->memory_error_func
) (status
, memaddr
, info
);
965 && !(info
->section
->flags
& SEC_CODE
))
970 data
= bfd_get_bits (buffer
, size
* 8,
971 info
->display_endian
== BFD_ENDIAN_BIG
);
975 (*info
->fprintf_func
) (info
->stream
, ".byte\t0x%02lx", data
);
978 (*info
->fprintf_func
) (info
->stream
, ".short\t0x%04lx", data
);
981 (*info
->fprintf_func
) (info
->stream
, ".word\t0x%08lx", data
);
989 insn_len
= arc_insn_length (buffer
[highbyte
], buffer
[lowbyte
], info
);
990 pr_debug ("instruction length = %d bytes\n", insn_len
);
991 arc_infop
= info
->private_data
;
992 arc_infop
->insn_len
= insn_len
;
997 insn
= (buffer
[highbyte
] << 8) | buffer
[lowbyte
];
1002 /* This is a long instruction: Read the remaning 2 bytes. */
1003 status
= (*info
->read_memory_func
) (memaddr
+ 2, &buffer
[2], 2, info
);
1006 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
1009 insn
= (unsigned long long) ARRANGE_ENDIAN (info
, buffer
);
1015 status
= (*info
->read_memory_func
) (memaddr
+ 2, &buffer
[2], 4, info
);
1018 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
1021 insn
= (unsigned long long) ARRANGE_ENDIAN (info
, &buffer
[2]);
1022 insn
|= ((unsigned long long) buffer
[highbyte
] << 40)
1023 | ((unsigned long long) buffer
[lowbyte
] << 32);
1029 status
= (*info
->read_memory_func
) (memaddr
+ 2, &buffer
[2], 6, info
);
1032 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
1036 ((((unsigned long long) ARRANGE_ENDIAN (info
, buffer
)) << 32)
1037 | ((unsigned long long) ARRANGE_ENDIAN (info
, &buffer
[4])));
1042 /* There is no instruction whose length is not 2, 4, 6, or 8. */
1046 pr_debug ("instruction value = %llx\n", insn
);
1048 /* Set some defaults for the insn info. */
1049 info
->insn_info_valid
= 1;
1050 info
->branch_delay_insns
= 0;
1051 info
->data_size
= 4;
1052 info
->insn_type
= dis_nonbranch
;
1056 /* FIXME to be moved in dissasemble_init_for_target. */
1057 info
->disassembler_needs_relocs
= TRUE
;
1059 /* Find the first match in the opcode table. */
1060 if (!find_format (memaddr
, insn
, &insn_len
, isa_mask
, info
, &opcode
, &iter
))
1068 (*info
->fprintf_func
) (info
->stream
, ".long %#04llx",
1072 (*info
->fprintf_func
) (info
->stream
, ".long %#08llx",
1076 (*info
->fprintf_func
) (info
->stream
, ".long %#08llx",
1078 (*info
->fprintf_func
) (info
->stream
, ".long %#04llx",
1079 (insn
>> 32) & 0xffff);
1082 (*info
->fprintf_func
) (info
->stream
, ".long %#08llx",
1084 (*info
->fprintf_func
) (info
->stream
, ".long %#08llx",
1091 info
->insn_type
= dis_noninsn
;
1095 /* Print the mnemonic. */
1096 (*info
->fprintf_func
) (info
->stream
, "%s", opcode
->name
);
1098 /* Preselect the insn class. */
1099 info
->insn_type
= arc_opcode_to_insn_type (opcode
);
1101 pr_debug ("%s: 0x%08llx\n", opcode
->name
, opcode
->opcode
);
1103 print_flags (opcode
, &insn
, info
);
1105 if (opcode
->operands
[0] != 0)
1106 (*info
->fprintf_func
) (info
->stream
, "\t");
1109 open_braket
= FALSE
;
1110 arc_infop
->operands_count
= 0;
1112 /* Now extract and print the operands. */
1114 while (operand_iterator_next (&iter
, &operand
, &value
))
1116 if (open_braket
&& (operand
->flags
& ARC_OPERAND_BRAKET
))
1118 (*info
->fprintf_func
) (info
->stream
, "]");
1119 open_braket
= FALSE
;
1123 /* Only take input from real operands. */
1124 if (ARC_OPERAND_IS_FAKE (operand
))
1127 if ((operand
->flags
& ARC_OPERAND_IGNORE
)
1128 && (operand
->flags
& ARC_OPERAND_IR
)
1132 if (operand
->flags
& ARC_OPERAND_COLON
)
1134 (*info
->fprintf_func
) (info
->stream
, ":");
1139 (*info
->fprintf_func
) (info
->stream
, ",");
1141 if (!open_braket
&& (operand
->flags
& ARC_OPERAND_BRAKET
))
1143 (*info
->fprintf_func
) (info
->stream
, "[");
1151 /* Print the operand as directed by the flags. */
1152 if (operand
->flags
& ARC_OPERAND_IR
)
1156 assert (value
>=0 && value
< 64);
1157 rname
= arcExtMap_coreRegName (value
);
1159 rname
= regnames
[value
];
1160 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1161 if (operand
->flags
& ARC_OPERAND_TRUNCATE
)
1163 rname
= arcExtMap_coreRegName (value
+ 1);
1165 rname
= regnames
[value
+ 1];
1166 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1169 else if (operand
->flags
& ARC_OPERAND_LIMM
)
1171 const char *rname
= get_auxreg (opcode
, value
, isa_mask
);
1173 if (rname
&& open_braket
)
1174 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1177 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
1178 if (info
->insn_type
== dis_branch
1179 || info
->insn_type
== dis_jsr
)
1180 info
->target
= (bfd_vma
) value
;
1183 else if (operand
->flags
& ARC_OPERAND_PCREL
)
1186 if (info
->flags
& INSN_HAS_RELOC
)
1188 (*info
->print_address_func
) ((memaddr
& ~3) + value
, info
);
1190 info
->target
= (bfd_vma
) (memaddr
& ~3) + value
;
1192 else if (operand
->flags
& ARC_OPERAND_SIGNED
)
1194 const char *rname
= get_auxreg (opcode
, value
, isa_mask
);
1195 if (rname
&& open_braket
)
1196 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1198 (*info
->fprintf_func
) (info
->stream
, "%d", value
);
1200 else if (operand
->flags
& ARC_OPERAND_ADDRTYPE
)
1202 const char *addrtype
= get_addrtype (value
);
1203 (*info
->fprintf_func
) (info
->stream
, "%s", addrtype
);
1204 /* A colon follow an address type. */
1209 if (operand
->flags
& ARC_OPERAND_TRUNCATE
1210 && !(operand
->flags
& ARC_OPERAND_ALIGNED32
)
1211 && !(operand
->flags
& ARC_OPERAND_ALIGNED16
)
1212 && value
>= 0 && value
<= 14)
1220 (*info
->fprintf_func
) (info
->stream
, "r13");
1223 (*info
->fprintf_func
) (info
->stream
, "r13-%s",
1224 regnames
[13 + value
- 1]);
1230 const char *rname
= get_auxreg (opcode
, value
, isa_mask
);
1231 if (rname
&& open_braket
)
1232 (*info
->fprintf_func
) (info
->stream
, "%s", rname
);
1234 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
1238 if (operand
->flags
& ARC_OPERAND_LIMM
)
1240 arc_infop
->operands
[arc_infop
->operands_count
].kind
1241 = ARC_OPERAND_KIND_LIMM
;
1242 /* It is not important to have exactly the LIMM indicator
1244 arc_infop
->operands
[arc_infop
->operands_count
].value
= 63;
1248 arc_infop
->operands
[arc_infop
->operands_count
].value
= value
;
1249 arc_infop
->operands
[arc_infop
->operands_count
].kind
1250 = (operand
->flags
& ARC_OPERAND_IR
1251 ? ARC_OPERAND_KIND_REG
1252 : ARC_OPERAND_KIND_SHIMM
);
1254 arc_infop
->operands_count
++;
1262 arc_get_disassembler (bfd
*abfd
)
1264 /* BFD my be absent, if opcodes is invoked from the debugger that
1265 has connected to remote target and doesn't have an ELF file. */
1268 /* Read the extension insns and registers, if any. */
1269 build_ARC_extmap (abfd
);
1275 return print_insn_arc
;
1279 print_arc_disassembler_options (FILE *stream
)
1281 fprintf (stream
, _("\n\
1282 The following ARC specific disassembler options are supported for use \n\
1283 with -M switch (multiple options should be separated by commas):\n"));
1285 fprintf (stream
, _("\
1286 dsp Recognize DSP instructions.\n"));
1287 fprintf (stream
, _("\
1288 spfp Recognize FPX SP instructions.\n"));
1289 fprintf (stream
, _("\
1290 dpfp Recognize FPX DP instructions.\n"));
1291 fprintf (stream
, _("\
1292 quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1293 fprintf (stream
, _("\
1294 fpuda Recognize double assist FPU instructions.\n"));
1295 fprintf (stream
, _("\
1296 fpus Recognize single precision FPU instructions.\n"));
1297 fprintf (stream
, _("\
1298 fpud Recognize double precision FPU instructions.\n"));
1301 void arc_insn_decode (bfd_vma addr
,
1302 struct disassemble_info
*info
,
1303 disassembler_ftype disasm_func
,
1304 struct arc_instruction
*insn
)
1306 const struct arc_opcode
*opcode
;
1307 struct arc_disassemble_info
*arc_infop
;
1309 /* Ensure that insn would be in the reset state. */
1310 memset (insn
, 0, sizeof (struct arc_instruction
));
1312 /* There was an error when disassembling, for example memory read error. */
1313 if (disasm_func (addr
, info
) < 0)
1315 insn
->valid
= FALSE
;
1319 assert (info
->private_data
!= NULL
);
1320 arc_infop
= info
->private_data
;
1322 insn
->length
= arc_infop
->insn_len
;;
1323 insn
->address
= addr
;
1325 /* Quick exit if memory at this address is not an instruction. */
1326 if (info
->insn_type
== dis_noninsn
)
1328 insn
->valid
= FALSE
;
1334 opcode
= (const struct arc_opcode
*) arc_infop
->opcode
;
1335 insn
->insn_class
= opcode
->insn_class
;
1336 insn
->limm_value
= arc_infop
->limm
;
1337 insn
->limm_p
= arc_infop
->limm_p
;
1339 insn
->is_control_flow
= (info
->insn_type
== dis_branch
1340 || info
->insn_type
== dis_condbranch
1341 || info
->insn_type
== dis_jsr
1342 || info
->insn_type
== dis_condjsr
);
1344 insn
->has_delay_slot
= info
->branch_delay_insns
;
1345 insn
->writeback_mode
1346 = (enum arc_ldst_writeback_mode
) arc_infop
->writeback_mode
;
1347 insn
->data_size_mode
= info
->data_size
;
1348 insn
->condition_code
= arc_infop
->condition_code
;
1349 memcpy (insn
->operands
, arc_infop
->operands
,
1350 sizeof (struct arc_insn_operand
) * MAX_INSN_ARGS
);
1351 insn
->operands_count
= arc_infop
->operands_count
;
1355 eval: (c-set-style "gnu")