Fix: A potential null_pointer_deference bug
[binutils-gdb.git] / opcodes / arc-dis.c
blob59b668ff64e0df65d38979ec29beb573ee7b5c11
1 /* Instruction printing code for the ARC.
2 Copyright (C) 1994-2023 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 bool 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", "r58", "r59", "lp_count", "reserved", "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 bool 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) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
141 #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
143 /* Functions implementation. */
145 /* Initialize private data. */
146 static bool
147 init_arc_disasm_info (struct disassemble_info *info)
149 struct arc_disassemble_info *arc_infop
150 = calloc (sizeof (*arc_infop), 1);
152 if (arc_infop == NULL)
153 return false;
155 info->private_data = arc_infop;
156 return true;
159 /* Add a new element to the decode list. */
161 static void
162 add_to_decodelist (insn_class_t insn_class,
163 insn_subclass_t subclass)
165 linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
167 t->insn_class = insn_class;
168 t->subclass = subclass;
169 t->nxt = decodelist;
170 decodelist = t;
173 /* Return TRUE if we need to skip the opcode from being
174 disassembled. */
176 static bool
177 skip_this_opcode (const struct arc_opcode *opcode)
179 linkclass t = decodelist;
181 /* Check opcode for major 0x06, return if it is not in. */
182 if (arc_opcode_len (opcode) == 4
183 && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06
184 /* Can be an APEX extensions. */
185 && OPCODE_32BIT_INSN (opcode->opcode) != 0x07))
186 return false;
188 /* or not a known truble class. */
189 switch (opcode->insn_class)
191 case FLOAT:
192 case DSP:
193 case ARITH:
194 case MPY:
195 break;
196 default:
197 return false;
200 while (t != NULL)
202 if ((t->insn_class == opcode->insn_class)
203 && (t->subclass == opcode->subclass))
204 return false;
205 t = t->nxt;
208 return true;
211 static bfd_vma
212 bfd_getm32 (unsigned int data)
214 bfd_vma value = 0;
216 value = ((data & 0xff00) | (data & 0xff)) << 16;
217 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
218 return value;
221 static bool
222 special_flag_p (const char *opname,
223 const char *flgname)
225 const struct arc_flag_special *flg_spec;
226 unsigned i, j, flgidx;
228 for (i = 0; i < arc_num_flag_special; i++)
230 flg_spec = &arc_flag_special_cases[i];
232 if (strcmp (opname, flg_spec->name))
233 continue;
235 /* Found potential special case instruction. */
236 for (j=0;; ++j)
238 flgidx = flg_spec->flags[j];
239 if (flgidx == 0)
240 break; /* End of the array. */
242 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
243 return true;
246 return false;
249 /* Find opcode from ARC_TABLE given the instruction described by INSN and
250 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
252 static const struct arc_opcode *
253 find_format_from_table (struct disassemble_info *info,
254 const struct arc_opcode *arc_table,
255 unsigned long long insn,
256 unsigned int insn_len,
257 unsigned isa_mask,
258 bool *has_limm,
259 bool overlaps)
261 unsigned int i = 0;
262 const struct arc_opcode *opcode = NULL;
263 const struct arc_opcode *t_op = NULL;
264 const unsigned char *opidx;
265 const unsigned char *flgidx;
266 bool warn_p = false;
270 bool invalid = false;
272 opcode = &arc_table[i++];
274 if (!(opcode->cpu & isa_mask))
275 continue;
277 if (arc_opcode_len (opcode) != (int) insn_len)
278 continue;
280 if ((insn & opcode->mask) != opcode->opcode)
281 continue;
283 *has_limm = false;
285 /* Possible candidate, check the operands. */
286 for (opidx = opcode->operands; *opidx; opidx++)
288 int value, limmind;
289 const struct arc_operand *operand = &arc_operands[*opidx];
291 if (operand->flags & ARC_OPERAND_FAKE)
292 continue;
294 if (operand->extract)
295 value = (*operand->extract) (insn, &invalid);
296 else
297 value = (insn >> operand->shift) & ((1ull << operand->bits) - 1);
299 /* Check for LIMM indicator. If it is there, then make sure
300 we pick the right format. */
301 limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
302 if (operand->flags & ARC_OPERAND_IR
303 && !(operand->flags & ARC_OPERAND_LIMM))
305 if ((value == 0x3E && insn_len == 4)
306 || (value == limmind && insn_len == 2))
308 invalid = true;
309 break;
313 if (operand->flags & ARC_OPERAND_LIMM
314 && !(operand->flags & ARC_OPERAND_DUPLICATE))
315 *has_limm = true;
318 /* Check the flags. */
319 for (flgidx = opcode->flags; *flgidx; flgidx++)
321 /* Get a valid flag class. */
322 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
323 const unsigned *flgopridx;
324 int foundA = 0, foundB = 0;
325 unsigned int value;
327 /* Check first the extensions. */
328 if (cl_flags->flag_class & F_CLASS_EXTEND)
330 value = (insn & 0x1F);
331 if (arcExtMap_condCodeName (value))
332 continue;
335 /* Check for the implicit flags. */
336 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
337 continue;
339 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
341 const struct arc_flag_operand *flg_operand =
342 &arc_flag_operands[*flgopridx];
344 value = (insn >> flg_operand->shift)
345 & ((1 << flg_operand->bits) - 1);
346 if (value == flg_operand->code)
347 foundA = 1;
348 if (value)
349 foundB = 1;
352 if (!foundA && foundB)
354 invalid = true;
355 break;
359 if (invalid)
360 continue;
362 if (insn_len == 4
363 && overlaps)
365 warn_p = true;
366 t_op = opcode;
367 if (skip_this_opcode (opcode))
368 continue;
371 /* The instruction is valid. */
372 return opcode;
374 while (opcode->mask);
376 if (warn_p)
378 info->fprintf_styled_func
379 (info->stream, dis_style_text,
380 _("\nWarning: disassembly may be wrong due to "
381 "guessed opcode class choice.\n"
382 "Use -M<class[,class]> to select the correct "
383 "opcode class(es).\n\t\t\t\t"));
384 return t_op;
387 return NULL;
390 /* Find opcode for INSN, trying various different sources. The instruction
391 length in INSN_LEN will be updated if the instruction requires a LIMM
392 extension.
394 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
395 initialised, ready to iterate over the operands of the found opcode. If
396 the found opcode requires a LIMM then the LIMM value will be loaded into a
397 field of ITER.
399 This function returns TRUE in almost all cases, FALSE is reserved to
400 indicate an error (failing to find an opcode is not an error) a returned
401 result of FALSE would indicate that the disassembler can't continue.
403 If no matching opcode is found then the returned result will be TRUE, the
404 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
405 INSN_LEN will be unchanged.
407 If a matching opcode is found, then the returned result will be TRUE, the
408 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
409 4 if the instruction requires a LIMM, and the LIMM value will have been
410 loaded into a field of ITER. Finally, ITER will have been initialised so
411 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
412 operands. */
414 static bool
415 find_format (bfd_vma memaddr,
416 unsigned long long insn,
417 unsigned int * insn_len,
418 unsigned isa_mask,
419 struct disassemble_info * info,
420 const struct arc_opcode ** opcode_result,
421 struct arc_operand_iterator * iter)
423 const struct arc_opcode *opcode = NULL;
424 bool needs_limm = false;
425 const extInstruction_t *einsn, *i;
426 unsigned limm = 0;
427 struct arc_disassemble_info *arc_infop = info->private_data;
429 /* First, try the extension instructions. */
430 if (*insn_len == 4)
432 einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
433 for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
435 const char *errmsg = NULL;
437 opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
438 if (opcode == NULL)
440 (*info->fprintf_styled_func)
441 (info->stream, dis_style_text,
442 _("An error occurred while generating "
443 "the extension instruction operations"));
444 *opcode_result = NULL;
445 return false;
448 opcode = find_format_from_table (info, opcode, insn, *insn_len,
449 isa_mask, &needs_limm, false);
453 /* Then, try finding the first match in the opcode table. */
454 if (opcode == NULL)
455 opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
456 isa_mask, &needs_limm, true);
458 if (opcode != NULL && needs_limm)
460 bfd_byte buffer[4];
461 int status;
463 status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
464 4, info);
465 if (status != 0)
467 opcode = NULL;
469 else
471 limm = ARRANGE_ENDIAN (info, buffer);
472 *insn_len += 4;
476 if (opcode != NULL)
478 iter->insn = insn;
479 iter->limm = limm;
480 iter->opcode = opcode;
481 iter->opidx = opcode->operands;
484 *opcode_result = opcode;
486 /* Update private data. */
487 arc_infop->opcode = opcode;
488 arc_infop->limm = limm;
489 arc_infop->limm_p = needs_limm;
491 return true;
494 static void
495 print_flags (const struct arc_opcode *opcode,
496 unsigned long long *insn,
497 struct disassemble_info *info)
499 const unsigned char *flgidx;
500 unsigned int value;
501 struct arc_disassemble_info *arc_infop = info->private_data;
503 /* Now extract and print the flags. */
504 for (flgidx = opcode->flags; *flgidx; flgidx++)
506 /* Get a valid flag class. */
507 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
508 const unsigned *flgopridx;
510 /* Check first the extensions. */
511 if (cl_flags->flag_class & F_CLASS_EXTEND)
513 const char *name;
514 value = (insn[0] & 0x1F);
516 name = arcExtMap_condCodeName (value);
517 if (name)
519 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
520 ".%s", name);
521 continue;
525 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
527 const struct arc_flag_operand *flg_operand =
528 &arc_flag_operands[*flgopridx];
530 /* Implicit flags are only used for the insn decoder. */
531 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
533 if (cl_flags->flag_class & F_CLASS_COND)
534 arc_infop->condition_code = flg_operand->code;
535 else if (cl_flags->flag_class & F_CLASS_WB)
536 arc_infop->writeback_mode = flg_operand->code;
537 else if (cl_flags->flag_class & F_CLASS_ZZ)
538 info->data_size = flg_operand->code;
539 continue;
542 if (!flg_operand->favail)
543 continue;
545 value = (insn[0] >> flg_operand->shift)
546 & ((1 << flg_operand->bits) - 1);
547 if (value == flg_operand->code)
549 /* FIXME!: print correctly nt/t flag. */
550 if (!special_flag_p (opcode->name, flg_operand->name))
551 (*info->fprintf_styled_func) (info->stream,
552 dis_style_mnemonic, ".");
553 else if (info->insn_type == dis_dref)
555 switch (flg_operand->name[0])
557 case 'b':
558 info->data_size = 1;
559 break;
560 case 'h':
561 case 'w':
562 info->data_size = 2;
563 break;
564 default:
565 info->data_size = 4;
566 break;
569 if (flg_operand->name[0] == 'd'
570 && flg_operand->name[1] == 0)
571 info->branch_delay_insns = 1;
573 /* Check if it is a conditional flag. */
574 if (cl_flags->flag_class & F_CLASS_COND)
576 if (info->insn_type == dis_jsr)
577 info->insn_type = dis_condjsr;
578 else if (info->insn_type == dis_branch)
579 info->insn_type = dis_condbranch;
580 arc_infop->condition_code = flg_operand->code;
583 /* Check for the write back modes. */
584 if (cl_flags->flag_class & F_CLASS_WB)
585 arc_infop->writeback_mode = flg_operand->code;
587 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
588 "%s", flg_operand->name);
594 static const char *
595 get_auxreg (const struct arc_opcode *opcode,
596 int value,
597 unsigned isa_mask)
599 const char *name;
600 unsigned int i;
601 const struct arc_aux_reg *auxr = &arc_aux_regs[0];
603 if (opcode->insn_class != AUXREG)
604 return NULL;
606 name = arcExtMap_auxRegName (value);
607 if (name)
608 return name;
610 for (i = 0; i < arc_num_aux_regs; i++, auxr++)
612 if (!(auxr->cpu & isa_mask))
613 continue;
615 if (auxr->subclass != NONE)
616 return NULL;
618 if (auxr->address == value)
619 return auxr->name;
621 return NULL;
624 /* Convert a value representing an address type to a string used to refer to
625 the address type in assembly code. */
627 static const char *
628 get_addrtype (int value)
630 if (value < 0 || value > addrtypenames_max)
631 return addrtypeunknown;
633 return addrtypenames[value];
636 /* Calculate the instruction length for an instruction starting with MSB
637 and LSB, the most and least significant byte. The ISA_MASK is used to
638 filter the instructions considered to only those that are part of the
639 current architecture.
641 The instruction lengths are calculated from the ARC_OPCODE table, and
642 cached for later use. */
644 static unsigned int
645 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
647 bfd_byte major_opcode = msb >> 3;
649 switch (info->mach)
651 case bfd_mach_arc_arc700:
652 /* The nps400 extension set requires this special casing of the
653 instruction length calculation. Right now this is not causing any
654 problems as none of the known extensions overlap in opcode space,
655 but, if they ever do then we might need to start carrying
656 information around in the elf about which extensions are in use. */
657 if (major_opcode == 0xb)
659 bfd_byte minor_opcode = lsb & 0x1f;
661 if (minor_opcode < 4)
662 return 6;
663 else if (minor_opcode == 0x10 || minor_opcode == 0x11)
664 return 8;
666 if (major_opcode == 0xa)
668 return 8;
670 /* Fall through. */
671 case bfd_mach_arc_arc600:
672 return (major_opcode > 0xb) ? 2 : 4;
673 break;
675 case bfd_mach_arc_arcv2:
676 return (major_opcode > 0x7) ? 2 : 4;
677 break;
679 default:
680 return 0;
684 /* Extract and return the value of OPERAND from the instruction whose value
685 is held in the array INSN. */
687 static int
688 extract_operand_value (const struct arc_operand *operand,
689 unsigned long long insn,
690 unsigned limm)
692 int value;
694 /* Read the limm operand, if required. */
695 if (operand->flags & ARC_OPERAND_LIMM)
696 /* The second part of the instruction value will have been loaded as
697 part of the find_format call made earlier. */
698 value = limm;
699 else
701 if (operand->extract)
702 value = (*operand->extract) (insn, (bool *) NULL);
703 else
705 if (operand->flags & ARC_OPERAND_ALIGNED32)
707 value = (insn >> operand->shift)
708 & ((1 << (operand->bits - 2)) - 1);
709 value = value << 2;
711 else
713 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
715 if (operand->flags & ARC_OPERAND_SIGNED)
717 int signbit = 1 << (operand->bits - 1);
718 value = (value ^ signbit) - signbit;
723 return value;
726 /* Find the next operand, and the operands value from ITER. Return TRUE if
727 there is another operand, otherwise return FALSE. If there is an
728 operand returned then the operand is placed into OPERAND, and the value
729 into VALUE. If there is no operand returned then OPERAND and VALUE are
730 unchanged. */
732 static bool
733 operand_iterator_next (struct arc_operand_iterator *iter,
734 const struct arc_operand **operand,
735 int *value)
737 if (*iter->opidx == 0)
739 *operand = NULL;
740 return false;
743 *operand = &arc_operands[*iter->opidx];
744 *value = extract_operand_value (*operand, iter->insn, iter->limm);
745 iter->opidx++;
747 return true;
750 /* Helper for parsing the options. */
752 static void
753 parse_option (const char *option)
755 if (disassembler_options_cmp (option, "dsp") == 0)
756 add_to_decodelist (DSP, NONE);
758 else if (disassembler_options_cmp (option, "spfp") == 0)
759 add_to_decodelist (FLOAT, SPX);
761 else if (disassembler_options_cmp (option, "dpfp") == 0)
762 add_to_decodelist (FLOAT, DPX);
764 else if (disassembler_options_cmp (option, "quarkse_em") == 0)
766 add_to_decodelist (FLOAT, DPX);
767 add_to_decodelist (FLOAT, SPX);
768 add_to_decodelist (FLOAT, QUARKSE1);
769 add_to_decodelist (FLOAT, QUARKSE2);
772 else if (disassembler_options_cmp (option, "fpuda") == 0)
773 add_to_decodelist (FLOAT, DPA);
775 else if (disassembler_options_cmp (option, "nps400") == 0)
777 add_to_decodelist (ACL, NPS400);
778 add_to_decodelist (ARITH, NPS400);
779 add_to_decodelist (BITOP, NPS400);
780 add_to_decodelist (BMU, NPS400);
781 add_to_decodelist (CONTROL, NPS400);
782 add_to_decodelist (DMA, NPS400);
783 add_to_decodelist (DPI, NPS400);
784 add_to_decodelist (MEMORY, NPS400);
785 add_to_decodelist (MISC, NPS400);
786 add_to_decodelist (NET, NPS400);
787 add_to_decodelist (PMU, NPS400);
788 add_to_decodelist (PROTOCOL_DECODE, NPS400);
789 add_to_decodelist (ULTRAIP, NPS400);
792 else if (disassembler_options_cmp (option, "fpus") == 0)
794 add_to_decodelist (FLOAT, SP);
795 add_to_decodelist (FLOAT, CVT);
798 else if (disassembler_options_cmp (option, "fpud") == 0)
800 add_to_decodelist (FLOAT, DP);
801 add_to_decodelist (FLOAT, CVT);
803 else if (startswith (option, "hex"))
804 print_hex = true;
805 else
806 /* xgettext:c-format */
807 opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
810 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \
811 { #NAME, ARC_OPCODE_ARC600, "ARC600" }
812 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \
813 { #NAME, ARC_OPCODE_ARC700, "ARC700" }
814 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \
815 { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" }
816 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \
817 { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" }
818 #define ARC_CPU_TYPE_NONE \
819 { 0, 0, 0 }
821 /* A table of CPU names and opcode sets. */
822 static const struct cpu_type
824 const char *name;
825 unsigned flags;
826 const char *isa;
828 cpu_types[] =
830 #include "elf/arc-cpu.def"
833 /* Helper for parsing the CPU options. Accept any of the ARC architectures
834 values. OPTION should be a value passed to cpu=. */
836 static unsigned
837 parse_cpu_option (const char *option)
839 int i;
841 for (i = 0; cpu_types[i].name; ++i)
843 if (!disassembler_options_cmp (cpu_types[i].name, option))
845 return cpu_types[i].flags;
849 /* xgettext:c-format */
850 opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
851 return ARC_OPCODE_NONE;
854 /* Go over the options list and parse it. */
856 static void
857 parse_disassembler_options (const char *options)
859 const char *option;
861 if (options == NULL)
862 return;
864 /* Disassembler might be reused for difference CPU's, and cpu option set for
865 the first one shouldn't be applied to second (which might not have
866 explicit cpu in its options. Therefore it is required to reset enforced
867 CPU when new options are being parsed. */
868 enforced_isa_mask = ARC_OPCODE_NONE;
870 FOR_EACH_DISASSEMBLER_OPTION (option, options)
872 /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a
873 preprocessor macro. */
874 if (strncmp (option, "cpu=", 4) == 0)
875 /* Strip leading `cpu=`. */
876 enforced_isa_mask = parse_cpu_option (option + 4);
877 else
878 parse_option (option);
882 /* Return the instruction type for an instruction described by OPCODE. */
884 static enum dis_insn_type
885 arc_opcode_to_insn_type (const struct arc_opcode *opcode)
887 enum dis_insn_type insn_type;
889 switch (opcode->insn_class)
891 case BRANCH:
892 case BBIT0:
893 case BBIT1:
894 case BI:
895 case BIH:
896 case BRCC:
897 case EI:
898 case JLI:
899 case JUMP:
900 case LOOP:
901 if (!strncmp (opcode->name, "bl", 2)
902 || !strncmp (opcode->name, "jl", 2))
904 if (opcode->subclass == COND)
905 insn_type = dis_condjsr;
906 else
907 insn_type = dis_jsr;
909 else
911 if (opcode->subclass == COND)
912 insn_type = dis_condbranch;
913 else
914 insn_type = dis_branch;
916 break;
917 case LOAD:
918 case STORE:
919 case MEMORY:
920 case ENTER:
921 case PUSH:
922 case POP:
923 insn_type = dis_dref;
924 break;
925 case LEAVE:
926 insn_type = dis_branch;
927 break;
928 default:
929 insn_type = dis_nonbranch;
930 break;
933 return insn_type;
936 /* Disassemble ARC instructions. */
938 static int
939 print_insn_arc (bfd_vma memaddr,
940 struct disassemble_info *info)
942 bfd_byte buffer[8];
943 unsigned int highbyte, lowbyte;
944 int status;
945 unsigned int insn_len;
946 unsigned long long insn = 0;
947 unsigned isa_mask = ARC_OPCODE_NONE;
948 const struct arc_opcode *opcode;
949 bool need_comma;
950 bool open_braket;
951 int size;
952 const struct arc_operand *operand;
953 int value, vpcl;
954 struct arc_operand_iterator iter;
955 struct arc_disassemble_info *arc_infop;
956 bool rpcl = false, rset = false;
958 if (info->disassembler_options)
960 parse_disassembler_options (info->disassembler_options);
962 /* Avoid repeated parsing of the options. */
963 info->disassembler_options = NULL;
966 if (info->private_data == NULL && !init_arc_disasm_info (info))
967 return -1;
969 memset (&iter, 0, sizeof (iter));
970 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
971 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
973 /* Figure out CPU type, unless it was enforced via disassembler options. */
974 if (enforced_isa_mask == ARC_OPCODE_NONE)
976 Elf_Internal_Ehdr *header = NULL;
978 if (info->section && info->section->owner)
979 header = elf_elfheader (info->section->owner);
981 switch (info->mach)
983 case bfd_mach_arc_arc700:
984 isa_mask = ARC_OPCODE_ARC700;
985 break;
987 case bfd_mach_arc_arc600:
988 isa_mask = ARC_OPCODE_ARC600;
989 break;
991 case bfd_mach_arc_arcv2:
992 default:
993 isa_mask = ARC_OPCODE_ARCv2EM;
994 /* TODO: Perhaps remove definition of header since it is only used at
995 this location. */
996 if (header != NULL
997 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
998 isa_mask = ARC_OPCODE_ARCv2HS;
999 break;
1002 else
1003 isa_mask = enforced_isa_mask;
1005 if (isa_mask == ARC_OPCODE_ARCv2HS)
1007 /* FPU instructions are not extensions for HS. */
1008 add_to_decodelist (FLOAT, SP);
1009 add_to_decodelist (FLOAT, DP);
1010 add_to_decodelist (FLOAT, CVT);
1013 /* This variable may be set by the instruction decoder. It suggests
1014 the number of bytes objdump should display on a single line. If
1015 the instruction decoder sets this, it should always set it to
1016 the same value in order to get reasonable looking output. */
1017 info->bytes_per_line = 8;
1019 /* In the next lines, we set two info variables control the way
1020 objdump displays the raw data. For example, if bytes_per_line is
1021 8 and bytes_per_chunk is 4, the output will look like this:
1022 00: 00000000 00000000
1023 with the chunks displayed according to "display_endian". */
1024 if (info->section
1025 && !(info->section->flags & SEC_CODE))
1027 /* This is not a CODE section. */
1028 switch (info->section->size)
1030 case 1:
1031 case 2:
1032 case 4:
1033 size = info->section->size;
1034 break;
1035 default:
1036 size = (info->section->size & 0x01) ? 1 : 4;
1037 break;
1039 info->bytes_per_chunk = 1;
1040 info->display_endian = info->endian;
1042 else
1044 size = 2;
1045 info->bytes_per_chunk = 2;
1046 info->display_endian = info->endian;
1049 /* Read the insn into a host word. */
1050 status = (*info->read_memory_func) (memaddr, buffer, size, info);
1052 if (status != 0)
1054 (*info->memory_error_func) (status, memaddr, info);
1055 return -1;
1058 if (info->section
1059 && !(info->section->flags & SEC_CODE))
1061 /* Data section. */
1062 unsigned long data;
1064 data = bfd_get_bits (buffer, size * 8,
1065 info->display_endian == BFD_ENDIAN_BIG);
1066 switch (size)
1068 case 1:
1069 (*info->fprintf_styled_func) (info->stream,
1070 dis_style_assembler_directive,
1071 ".byte");
1072 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1073 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1074 "0x%02lx", data);
1075 break;
1076 case 2:
1077 (*info->fprintf_styled_func) (info->stream,
1078 dis_style_assembler_directive,
1079 ".short");
1080 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1081 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1082 "0x%04lx", data);
1083 break;
1084 case 4:
1085 (*info->fprintf_styled_func) (info->stream,
1086 dis_style_assembler_directive,
1087 ".word");
1088 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1089 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1090 "0x%08lx", data);
1091 break;
1092 default:
1093 return -1;
1095 return size;
1098 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1099 pr_debug ("instruction length = %d bytes\n", insn_len);
1100 if (insn_len == 0)
1101 return -1;
1103 arc_infop = info->private_data;
1104 arc_infop->insn_len = insn_len;
1106 switch (insn_len)
1108 case 2:
1109 insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1110 break;
1112 case 4:
1114 /* This is a long instruction: Read the remaning 2 bytes. */
1115 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1116 if (status != 0)
1118 (*info->memory_error_func) (status, memaddr + 2, info);
1119 return -1;
1121 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1123 break;
1125 case 6:
1127 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1128 if (status != 0)
1130 (*info->memory_error_func) (status, memaddr + 2, info);
1131 return -1;
1133 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1134 insn |= ((unsigned long long) buffer[highbyte] << 40)
1135 | ((unsigned long long) buffer[lowbyte] << 32);
1137 break;
1139 case 8:
1141 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1142 if (status != 0)
1144 (*info->memory_error_func) (status, memaddr + 2, info);
1145 return -1;
1147 insn =
1148 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1149 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1151 break;
1153 default:
1154 /* There is no instruction whose length is not 2, 4, 6, or 8. */
1155 return -1;
1158 pr_debug ("instruction value = %llx\n", insn);
1160 /* Set some defaults for the insn info. */
1161 info->insn_info_valid = 1;
1162 info->branch_delay_insns = 0;
1163 info->data_size = 4;
1164 info->insn_type = dis_nonbranch;
1165 info->target = 0;
1166 info->target2 = 0;
1168 /* FIXME to be moved in dissasemble_init_for_target. */
1169 info->disassembler_needs_relocs = true;
1171 /* Find the first match in the opcode table. */
1172 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1173 return -1;
1175 if (!opcode)
1177 switch (insn_len)
1179 case 2:
1180 (*info->fprintf_styled_func) (info->stream,
1181 dis_style_assembler_directive,
1182 ".short");
1183 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1184 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1185 "0x%04llx", insn & 0xffff);
1186 break;
1188 case 4:
1189 (*info->fprintf_styled_func) (info->stream,
1190 dis_style_assembler_directive,
1191 ".word");
1192 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1193 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1194 "0x%08llx", insn & 0xffffffff);
1195 break;
1197 case 6:
1198 (*info->fprintf_styled_func) (info->stream,
1199 dis_style_assembler_directive,
1200 ".long");
1201 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1202 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1203 "0x%08llx", insn & 0xffffffff);
1204 (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1205 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1206 "0x%04llx", (insn >> 32) & 0xffff);
1207 break;
1209 case 8:
1210 (*info->fprintf_styled_func) (info->stream,
1211 dis_style_assembler_directive,
1212 ".long");
1213 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1214 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1215 "0x%08llx", insn & 0xffffffff);
1216 (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1217 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1218 "0x%08llx", (insn >> 32));
1219 break;
1221 default:
1222 return -1;
1225 info->insn_type = dis_noninsn;
1226 return insn_len;
1229 /* Print the mnemonic. */
1230 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1231 "%s", opcode->name);
1233 /* Preselect the insn class. */
1234 info->insn_type = arc_opcode_to_insn_type (opcode);
1236 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1238 print_flags (opcode, &insn, info);
1240 if (opcode->operands[0] != 0)
1241 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1243 need_comma = false;
1244 open_braket = false;
1245 arc_infop->operands_count = 0;
1247 /* Now extract and print the operands. */
1248 operand = NULL;
1249 vpcl = 0;
1250 while (operand_iterator_next (&iter, &operand, &value))
1252 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1254 (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
1255 open_braket = false;
1256 continue;
1259 /* Only take input from real operands. */
1260 if (ARC_OPERAND_IS_FAKE (operand))
1261 continue;
1263 if ((operand->flags & ARC_OPERAND_IGNORE)
1264 && (operand->flags & ARC_OPERAND_IR)
1265 && value == -1)
1266 continue;
1268 if (operand->flags & ARC_OPERAND_COLON)
1270 (*info->fprintf_styled_func) (info->stream, dis_style_text, ":");
1271 continue;
1274 if (need_comma)
1275 (*info->fprintf_styled_func) (info->stream, dis_style_text,",");
1277 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1279 (*info->fprintf_styled_func) (info->stream, dis_style_text, "[");
1280 open_braket = true;
1281 need_comma = false;
1282 continue;
1285 need_comma = true;
1287 if (operand->flags & ARC_OPERAND_PCREL)
1289 rpcl = true;
1290 vpcl = value;
1291 rset = true;
1293 info->target = (bfd_vma) (memaddr & ~3) + value;
1295 else if (!(operand->flags & ARC_OPERAND_IR))
1297 vpcl = value;
1298 rset = true;
1301 /* Print the operand as directed by the flags. */
1302 if (operand->flags & ARC_OPERAND_IR)
1304 const char *rname;
1306 assert (value >=0 && value < 64);
1307 rname = arcExtMap_coreRegName (value);
1308 if (!rname)
1309 rname = regnames[value];
1310 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1311 "%s", rname);
1313 /* Check if we have a double register to print. */
1314 if (operand->flags & ARC_OPERAND_TRUNCATE)
1316 if ((value & 0x01) == 0)
1318 rname = arcExtMap_coreRegName (value + 1);
1319 if (!rname)
1320 rname = regnames[value + 1];
1322 else
1323 rname = _("\nWarning: illegal use of double register "
1324 "pair.\n");
1325 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1326 "%s", rname);
1328 if (value == 63)
1329 rpcl = true;
1330 else
1331 rpcl = false;
1333 else if (operand->flags & ARC_OPERAND_LIMM)
1335 const char *rname = get_auxreg (opcode, value, isa_mask);
1337 if (rname && open_braket)
1338 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1339 "%s", rname);
1340 else
1342 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1343 "%#x", value);
1344 if (info->insn_type == dis_branch
1345 || info->insn_type == dis_jsr)
1346 info->target = (bfd_vma) value;
1349 else if (operand->flags & ARC_OPERAND_SIGNED)
1351 const char *rname = get_auxreg (opcode, value, isa_mask);
1352 if (rname && open_braket)
1353 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1354 "%s", rname);
1355 else
1357 if (print_hex)
1358 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1359 "%#x", value);
1360 else
1361 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1362 "%d", value);
1365 else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1367 const char *addrtype = get_addrtype (value);
1368 (*info->fprintf_styled_func) (info->stream, dis_style_address,
1369 "%s", addrtype);
1370 /* A colon follow an address type. */
1371 need_comma = false;
1373 else
1375 if (operand->flags & ARC_OPERAND_TRUNCATE
1376 && !(operand->flags & ARC_OPERAND_ALIGNED32)
1377 && !(operand->flags & ARC_OPERAND_ALIGNED16)
1378 && value >= 0 && value <= 14)
1380 /* Leave/Enter mnemonics. */
1381 switch (value)
1383 case 0:
1384 need_comma = false;
1385 break;
1386 case 1:
1387 (*info->fprintf_styled_func) (info->stream,
1388 dis_style_register, "r13");
1389 break;
1390 default:
1391 (*info->fprintf_styled_func) (info->stream,
1392 dis_style_register, "r13");
1393 (*info->fprintf_styled_func) (info->stream,
1394 dis_style_text, "-");
1395 (*info->fprintf_styled_func) (info->stream,
1396 dis_style_register, "%s",
1397 regnames[13 + value - 1]);
1398 break;
1400 rpcl = false;
1401 rset = false;
1403 else
1405 const char *rname = get_auxreg (opcode, value, isa_mask);
1406 if (rname && open_braket)
1407 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1408 "%s", rname);
1409 else
1410 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1411 "%#x", value);
1415 if (operand->flags & ARC_OPERAND_LIMM)
1417 arc_infop->operands[arc_infop->operands_count].kind
1418 = ARC_OPERAND_KIND_LIMM;
1419 /* It is not important to have exactly the LIMM indicator
1420 here. */
1421 arc_infop->operands[arc_infop->operands_count].value = 63;
1423 else
1425 arc_infop->operands[arc_infop->operands_count].value = value;
1426 arc_infop->operands[arc_infop->operands_count].kind
1427 = (operand->flags & ARC_OPERAND_IR
1428 ? ARC_OPERAND_KIND_REG
1429 : ARC_OPERAND_KIND_SHIMM);
1431 arc_infop->operands_count ++;
1434 /* Pretty print extra info for pc-relative operands. */
1435 if (rpcl && rset)
1437 if (info->flags & INSN_HAS_RELOC)
1438 /* If the instruction has a reloc associated with it, then the
1439 offset field in the instruction will actually be the addend
1440 for the reloc. (We are using REL type relocs). In such
1441 cases, we can ignore the pc when computing addresses, since
1442 the addend is not currently pc-relative. */
1443 memaddr = 0;
1445 (*info->fprintf_styled_func) (info->stream,
1446 dis_style_comment_start, "\t;");
1447 (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1450 return insn_len;
1454 disassembler_ftype
1455 arc_get_disassembler (bfd *abfd)
1457 /* BFD my be absent, if opcodes is invoked from the debugger that
1458 has connected to remote target and doesn't have an ELF file. */
1459 if (abfd != NULL)
1461 /* Read the extension insns and registers, if any. */
1462 build_ARC_extmap (abfd);
1463 #ifdef DEBUG
1464 dump_ARC_extmap ();
1465 #endif
1468 return print_insn_arc;
1471 /* Indices into option argument vector for options that do require
1472 an argument. Use ARC_OPTION_ARG_NONE for options that don't
1473 expect an argument. */
1474 typedef enum
1476 ARC_OPTION_ARG_NONE = -1,
1477 ARC_OPTION_ARG_ARCH,
1478 ARC_OPTION_ARG_SIZE
1479 } arc_option_arg_t;
1481 /* Valid ARC disassembler options. */
1482 static struct
1484 const char *name;
1485 const char *description;
1486 arc_option_arg_t arg;
1487 } arc_options[] =
1489 { "cpu=", N_("Enforce the designated architecture while decoding."),
1490 ARC_OPTION_ARG_ARCH },
1491 { "dsp", N_("Recognize DSP instructions."),
1492 ARC_OPTION_ARG_NONE },
1493 { "spfp", N_("Recognize FPX SP instructions."),
1494 ARC_OPTION_ARG_NONE },
1495 { "dpfp", N_("Recognize FPX DP instructions."),
1496 ARC_OPTION_ARG_NONE },
1497 { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."),
1498 ARC_OPTION_ARG_NONE },
1499 { "fpuda", N_("Recognize double assist FPU instructions."),
1500 ARC_OPTION_ARG_NONE },
1501 { "fpus", N_("Recognize single precision FPU instructions."),
1502 ARC_OPTION_ARG_NONE },
1503 { "fpud", N_("Recognize double precision FPU instructions."),
1504 ARC_OPTION_ARG_NONE },
1505 { "nps400", N_("Recognize NPS400 instructions."),
1506 ARC_OPTION_ARG_NONE },
1507 { "hex", N_("Use only hexadecimal number to print immediates."),
1508 ARC_OPTION_ARG_NONE }
1511 /* Populate the structure for representing ARC's disassembly options.
1512 Such a dynamic initialization is desired, because it makes the maintenance
1513 easier and also gdb uses this to enable the "disassembler-option". */
1515 const disasm_options_and_args_t *
1516 disassembler_options_arc (void)
1518 static disasm_options_and_args_t *opts_and_args;
1520 if (opts_and_args == NULL)
1522 disasm_option_arg_t *args;
1523 disasm_options_t *opts;
1524 size_t i;
1525 const size_t nr_of_options = ARRAY_SIZE (arc_options);
1526 /* There is a null element at the end of CPU_TYPES, therefore
1527 NR_OF_CPUS is actually 1 more and that is desired here too. */
1528 const size_t nr_of_cpus = ARRAY_SIZE (cpu_types);
1530 opts_and_args = XNEW (disasm_options_and_args_t);
1531 opts_and_args->args
1532 = XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1);
1533 opts_and_args->options.name
1534 = XNEWVEC (const char *, nr_of_options + 1);
1535 opts_and_args->options.description
1536 = XNEWVEC (const char *, nr_of_options + 1);
1537 opts_and_args->options.arg
1538 = XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1);
1540 /* Populate the arguments for "cpu=" option. */
1541 args = opts_and_args->args;
1542 args[ARC_OPTION_ARG_ARCH].name = "ARCH";
1543 args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus);
1544 for (i = 0; i < nr_of_cpus; ++i)
1545 args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name;
1546 args[ARC_OPTION_ARG_SIZE].name = NULL;
1547 args[ARC_OPTION_ARG_SIZE].values = NULL;
1549 /* Populate the options. */
1550 opts = &opts_and_args->options;
1551 for (i = 0; i < nr_of_options; ++i)
1553 opts->name[i] = arc_options[i].name;
1554 opts->description[i] = arc_options[i].description;
1555 if (arc_options[i].arg != ARC_OPTION_ARG_NONE)
1556 opts->arg[i] = &args[arc_options[i].arg];
1557 else
1558 opts->arg[i] = NULL;
1560 opts->name[nr_of_options] = NULL;
1561 opts->description[nr_of_options] = NULL;
1562 opts->arg[nr_of_options] = NULL;
1565 return opts_and_args;
1569 void
1570 print_arc_disassembler_options (FILE *stream)
1572 const disasm_options_and_args_t *opts_and_args;
1573 const disasm_option_arg_t *args;
1574 const disasm_options_t *opts;
1575 size_t i, j;
1576 size_t max_len = 0;
1578 opts_and_args = disassembler_options_arc ();
1579 opts = &opts_and_args->options;
1580 args = opts_and_args->args;
1582 fprintf (stream, _("\nThe following ARC specific disassembler options are"
1583 " supported for use \nwith the -M switch (multiple"
1584 " options should be separated by commas):\n"));
1586 /* Find the maximum length for printing options (and their arg name). */
1587 for (i = 0; opts->name[i] != NULL; ++i)
1589 size_t len = strlen (opts->name[i]);
1590 len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
1591 max_len = (len > max_len) ? len : max_len;
1594 /* Print the options, their arg and description, if any. */
1595 for (i = 0, ++max_len; opts->name[i] != NULL; ++i)
1597 fprintf (stream, " %s", opts->name[i]);
1598 if (opts->arg[i] != NULL)
1599 fprintf (stream, "%s", opts->arg[i]->name);
1600 if (opts->description[i] != NULL)
1602 size_t len = strlen (opts->name[i]);
1603 len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
1604 fprintf (stream,
1605 "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
1607 fprintf (stream, _("\n"));
1610 /* Print the possible values of an argument. */
1611 for (i = 0; args[i].name != NULL; ++i)
1613 size_t len = 3;
1614 if (args[i].values == NULL)
1615 continue;
1616 fprintf (stream, _("\n\
1617 For the options above, the following values are supported for \"%s\":\n "),
1618 args[i].name);
1619 for (j = 0; args[i].values[j] != NULL; ++j)
1621 fprintf (stream, " %s", args[i].values[j]);
1622 len += strlen (args[i].values[j]) + 1;
1623 /* reset line if printed too long. */
1624 if (len >= 78)
1626 fprintf (stream, _("\n "));
1627 len = 3;
1630 fprintf (stream, _("\n"));
1633 fprintf (stream, _("\n"));
1636 void arc_insn_decode (bfd_vma addr,
1637 struct disassemble_info *info,
1638 disassembler_ftype disasm_func,
1639 struct arc_instruction *insn)
1641 const struct arc_opcode *opcode;
1642 struct arc_disassemble_info *arc_infop;
1644 /* Ensure that insn would be in the reset state. */
1645 memset (insn, 0, sizeof (struct arc_instruction));
1647 /* There was an error when disassembling, for example memory read error. */
1648 if (disasm_func (addr, info) < 0)
1650 insn->valid = false;
1651 return;
1654 assert (info->private_data != NULL);
1655 arc_infop = info->private_data;
1657 insn->length = arc_infop->insn_len;;
1658 insn->address = addr;
1660 /* Quick exit if memory at this address is not an instruction. */
1661 if (info->insn_type == dis_noninsn)
1663 insn->valid = false;
1664 return;
1667 insn->valid = true;
1669 opcode = (const struct arc_opcode *) arc_infop->opcode;
1670 insn->insn_class = opcode->insn_class;
1671 insn->limm_value = arc_infop->limm;
1672 insn->limm_p = arc_infop->limm_p;
1674 insn->is_control_flow = (info->insn_type == dis_branch
1675 || info->insn_type == dis_condbranch
1676 || info->insn_type == dis_jsr
1677 || info->insn_type == dis_condjsr);
1679 insn->has_delay_slot = info->branch_delay_insns;
1680 insn->writeback_mode
1681 = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1682 insn->data_size_mode = info->data_size;
1683 insn->condition_code = arc_infop->condition_code;
1684 memcpy (insn->operands, arc_infop->operands,
1685 sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1686 insn->operands_count = arc_infop->operands_count;
1689 /* Local variables:
1690 eval: (c-set-style "gnu")
1691 indent-tabs-mode: t
1692 End: */