X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=opcodes%2Farc-dis.c;h=59b668ff64e0df65d38979ec29beb573ee7b5c11;hb=2bced1684b3636d4c7607b7ec57e34d2d71b74cb;hp=7541b74d23034a10fa79bc00925a0d022d805323;hpb=fdddd2900f39584e7d6cee27127593fba2cb0cf2;p=binutils-gdb.git diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c index 7541b74d230..59b668ff64e 100644 --- a/opcodes/arc-dis.c +++ b/opcodes/arc-dis.c @@ -1,5 +1,5 @@ /* Instruction printing code for the ARC. - Copyright (C) 1994-2017 Free Software Foundation, Inc. + Copyright (C) 1994-2023 Free Software Foundation, Inc. Contributed by Claudiu Zissulescu (claziss@synopsys.com) @@ -61,7 +61,7 @@ struct arc_disassemble_info unsigned insn_len; /* TRUE if we have limm. */ - bfd_boolean limm_p; + bool limm_p; /* LIMM value, if exists. */ unsigned limm; @@ -90,7 +90,7 @@ static const char * const regnames[64] = "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", - "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl" + "r56", "r57", "r58", "r59", "lp_count", "reserved", "LIMM", "pcl" }; static const char * const addrtypenames[ARC_NUM_ADDRTYPES] = @@ -123,7 +123,7 @@ static linkclass decodelist = NULL; static unsigned enforced_isa_mask = ARC_OPCODE_NONE; /* True if we want to print using only hex numbers. */ -static bfd_boolean print_hex = FALSE; +static bool print_hex = false; /* Macros section. */ @@ -137,24 +137,23 @@ static bfd_boolean print_hex = FALSE; (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \ : bfd_getb32 (buf)) -#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \ - (s + (sizeof (word) * 8 - 1 - e))) +#define BITS(word,s,e) (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1)) #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31)) /* Functions implementation. */ /* Initialize private data. */ -static bfd_boolean +static bool init_arc_disasm_info (struct disassemble_info *info) { struct arc_disassemble_info *arc_infop = calloc (sizeof (*arc_infop), 1); if (arc_infop == NULL) - return FALSE; + return false; info->private_data = arc_infop; - return TRUE; + return true; } /* Add a new element to the decode list. */ @@ -174,15 +173,17 @@ add_to_decodelist (insn_class_t insn_class, /* Return TRUE if we need to skip the opcode from being disassembled. */ -static bfd_boolean +static bool skip_this_opcode (const struct arc_opcode *opcode) { linkclass t = decodelist; /* Check opcode for major 0x06, return if it is not in. */ if (arc_opcode_len (opcode) == 4 - && OPCODE_32BIT_INSN (opcode->opcode) != 0x06) - return FALSE; + && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06 + /* Can be an APEX extensions. */ + && OPCODE_32BIT_INSN (opcode->opcode) != 0x07)) + return false; /* or not a known truble class. */ switch (opcode->insn_class) @@ -190,20 +191,21 @@ skip_this_opcode (const struct arc_opcode *opcode) case FLOAT: case DSP: case ARITH: + case MPY: break; default: - return FALSE; + return false; } while (t != NULL) { if ((t->insn_class == opcode->insn_class) && (t->subclass == opcode->subclass)) - return FALSE; + return false; t = t->nxt; } - return TRUE; + return true; } static bfd_vma @@ -216,7 +218,7 @@ bfd_getm32 (unsigned int data) return value; } -static bfd_boolean +static bool special_flag_p (const char *opname, const char *flgname) { @@ -238,10 +240,10 @@ special_flag_p (const char *opname, break; /* End of the array. */ if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0) - return TRUE; + return true; } } - return FALSE; + return false; } /* Find opcode from ARC_TABLE given the instruction described by INSN and @@ -253,19 +255,19 @@ find_format_from_table (struct disassemble_info *info, unsigned long long insn, unsigned int insn_len, unsigned isa_mask, - bfd_boolean *has_limm, - bfd_boolean overlaps) + bool *has_limm, + bool overlaps) { unsigned int i = 0; const struct arc_opcode *opcode = NULL; const struct arc_opcode *t_op = NULL; const unsigned char *opidx; const unsigned char *flgidx; - bfd_boolean warn_p = FALSE; + bool warn_p = false; do { - bfd_boolean invalid = FALSE; + bool invalid = false; opcode = &arc_table[i++]; @@ -278,7 +280,7 @@ find_format_from_table (struct disassemble_info *info, if ((insn & opcode->mask) != opcode->opcode) continue; - *has_limm = FALSE; + *has_limm = false; /* Possible candidate, check the operands. */ for (opidx = opcode->operands; *opidx; opidx++) @@ -292,7 +294,7 @@ find_format_from_table (struct disassemble_info *info, if (operand->extract) value = (*operand->extract) (insn, &invalid); else - value = (insn >> operand->shift) & ((1 << operand->bits) - 1); + value = (insn >> operand->shift) & ((1ull << operand->bits) - 1); /* Check for LIMM indicator. If it is there, then make sure we pick the right format. */ @@ -303,14 +305,14 @@ find_format_from_table (struct disassemble_info *info, if ((value == 0x3E && insn_len == 4) || (value == limmind && insn_len == 2)) { - invalid = TRUE; + invalid = true; break; } } if (operand->flags & ARC_OPERAND_LIMM && !(operand->flags & ARC_OPERAND_DUPLICATE)) - *has_limm = TRUE; + *has_limm = true; } /* Check the flags. */ @@ -349,7 +351,7 @@ find_format_from_table (struct disassemble_info *info, if (!foundA && foundB) { - invalid = TRUE; + invalid = true; break; } } @@ -360,7 +362,7 @@ find_format_from_table (struct disassemble_info *info, if (insn_len == 4 && overlaps) { - warn_p = TRUE; + warn_p = true; t_op = opcode; if (skip_this_opcode (opcode)) continue; @@ -373,11 +375,12 @@ find_format_from_table (struct disassemble_info *info, if (warn_p) { - info->fprintf_func (info->stream, - _("\nWarning: disassembly may be wrong due to " - "guessed opcode class choice.\n" - "Use -M to select the correct " - "opcode class(es).\n\t\t\t\t")); + info->fprintf_styled_func + (info->stream, dis_style_text, + _("\nWarning: disassembly may be wrong due to " + "guessed opcode class choice.\n" + "Use -M to select the correct " + "opcode class(es).\n\t\t\t\t")); return t_op; } @@ -408,7 +411,7 @@ find_format_from_table (struct disassemble_info *info, that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's operands. */ -static bfd_boolean +static bool find_format (bfd_vma memaddr, unsigned long long insn, unsigned int * insn_len, @@ -418,7 +421,7 @@ find_format (bfd_vma memaddr, struct arc_operand_iterator * iter) { const struct arc_opcode *opcode = NULL; - bfd_boolean needs_limm; + bool needs_limm = false; const extInstruction_t *einsn, *i; unsigned limm = 0; struct arc_disassemble_info *arc_infop = info->private_data; @@ -434,23 +437,25 @@ find_format (bfd_vma memaddr, opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg); if (opcode == NULL) { - (*info->fprintf_func) (info->stream, "\ -An error occured while generating the extension instruction operations"); + (*info->fprintf_styled_func) + (info->stream, dis_style_text, + _("An error occurred while generating " + "the extension instruction operations")); *opcode_result = NULL; - return FALSE; + return false; } opcode = find_format_from_table (info, opcode, insn, *insn_len, - isa_mask, &needs_limm, FALSE); + isa_mask, &needs_limm, false); } } /* Then, try finding the first match in the opcode table. */ if (opcode == NULL) opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len, - isa_mask, &needs_limm, TRUE); + isa_mask, &needs_limm, true); - if (needs_limm && opcode != NULL) + if (opcode != NULL && needs_limm) { bfd_byte buffer[4]; int status; @@ -480,10 +485,10 @@ An error occured while generating the extension instruction operations"); /* Update private data. */ arc_infop->opcode = opcode; - arc_infop->limm = (needs_limm) ? limm : 0; + arc_infop->limm = limm; arc_infop->limm_p = needs_limm; - return TRUE; + return true; } static void @@ -511,7 +516,8 @@ print_flags (const struct arc_opcode *opcode, name = arcExtMap_condCodeName (value); if (name) { - (*info->fprintf_func) (info->stream, ".%s", name); + (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, + ".%s", name); continue; } } @@ -542,7 +548,8 @@ print_flags (const struct arc_opcode *opcode, { /* FIXME!: print correctly nt/t flag. */ if (!special_flag_p (opcode->name, flg_operand->name)) - (*info->fprintf_func) (info->stream, "."); + (*info->fprintf_styled_func) (info->stream, + dis_style_mnemonic, "."); else if (info->insn_type == dis_dref) { switch (flg_operand->name[0]) @@ -577,7 +584,8 @@ print_flags (const struct arc_opcode *opcode, if (cl_flags->flag_class & F_CLASS_WB) arc_infop->writeback_mode = flg_operand->code; - (*info->fprintf_func) (info->stream, "%s", flg_operand->name); + (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, + "%s", flg_operand->name); } } } @@ -669,7 +677,7 @@ arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info) break; default: - abort (); + return 0; } } @@ -691,7 +699,7 @@ extract_operand_value (const struct arc_operand *operand, else { if (operand->extract) - value = (*operand->extract) (insn, (int *) NULL); + value = (*operand->extract) (insn, (bool *) NULL); else { if (operand->flags & ARC_OPERAND_ALIGNED32) @@ -721,7 +729,7 @@ extract_operand_value (const struct arc_operand *operand, into VALUE. If there is no operand returned then OPERAND and VALUE are unchanged. */ -static bfd_boolean +static bool operand_iterator_next (struct arc_operand_iterator *iter, const struct arc_operand **operand, int *value) @@ -729,14 +737,14 @@ operand_iterator_next (struct arc_operand_iterator *iter, if (*iter->opidx == 0) { *operand = NULL; - return FALSE; + return false; } *operand = &arc_operands[*iter->opidx]; *value = extract_operand_value (*operand, iter->insn, iter->limm); iter->opidx++; - return TRUE; + return true; } /* Helper for parsing the options. */ @@ -764,6 +772,23 @@ parse_option (const char *option) else if (disassembler_options_cmp (option, "fpuda") == 0) add_to_decodelist (FLOAT, DPA); + else if (disassembler_options_cmp (option, "nps400") == 0) + { + add_to_decodelist (ACL, NPS400); + add_to_decodelist (ARITH, NPS400); + add_to_decodelist (BITOP, NPS400); + add_to_decodelist (BMU, NPS400); + add_to_decodelist (CONTROL, NPS400); + add_to_decodelist (DMA, NPS400); + add_to_decodelist (DPI, NPS400); + add_to_decodelist (MEMORY, NPS400); + add_to_decodelist (MISC, NPS400); + add_to_decodelist (NET, NPS400); + add_to_decodelist (PMU, NPS400); + add_to_decodelist (PROTOCOL_DECODE, NPS400); + add_to_decodelist (ULTRAIP, NPS400); + } + else if (disassembler_options_cmp (option, "fpus") == 0) { add_to_decodelist (FLOAT, SP); @@ -775,10 +800,11 @@ parse_option (const char *option) add_to_decodelist (FLOAT, DP); add_to_decodelist (FLOAT, CVT); } - else if (CONST_STRNEQ (option, "hex")) - print_hex = TRUE; + else if (startswith (option, "hex")) + print_hex = true; else - fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option); + /* xgettext:c-format */ + opcodes_error_handler (_("unrecognised disassembler option: %s"), option); } #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \ @@ -820,7 +846,8 @@ parse_cpu_option (const char *option) } } - fprintf (stderr, _("Unrecognised disassembler CPU option: %s\n"), option); + /* xgettext:c-format */ + opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option); return ARC_OPCODE_NONE; } @@ -919,13 +946,14 @@ print_insn_arc (bfd_vma memaddr, unsigned long long insn = 0; unsigned isa_mask = ARC_OPCODE_NONE; const struct arc_opcode *opcode; - bfd_boolean need_comma; - bfd_boolean open_braket; + bool need_comma; + bool open_braket; int size; const struct arc_operand *operand; - int value; + int value, vpcl; struct arc_operand_iterator iter; struct arc_disassemble_info *arc_infop; + bool rpcl = false, rset = false; if (info->disassembler_options) { @@ -986,7 +1014,6 @@ print_insn_arc (bfd_vma memaddr, the number of bytes objdump should display on a single line. If the instruction decoder sets this, it should always set it to the same value in order to get reasonable looking output. */ - info->bytes_per_line = 8; /* In the next lines, we set two info variables control the way @@ -994,7 +1021,6 @@ print_insn_arc (bfd_vma memaddr, 8 and bytes_per_chunk is 4, the output will look like this: 00: 00000000 00000000 with the chunks displayed according to "display_endian". */ - if (info->section && !(info->section->flags & SEC_CODE)) { @@ -1022,6 +1048,7 @@ print_insn_arc (bfd_vma memaddr, /* Read the insn into a host word. */ status = (*info->read_memory_func) (memaddr, buffer, size, info); + if (status != 0) { (*info->memory_error_func) (status, memaddr, info); @@ -1039,22 +1066,40 @@ print_insn_arc (bfd_vma memaddr, switch (size) { case 1: - (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".byte"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%02lx", data); break; case 2: - (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".short"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%04lx", data); break; case 4: - (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".word"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%08lx", data); break; default: - abort (); + return -1; } return size; } insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info); pr_debug ("instruction length = %d bytes\n", insn_len); + if (insn_len == 0) + return -1; + arc_infop = info->private_data; arc_infop->insn_len = insn_len; @@ -1107,7 +1152,7 @@ print_insn_arc (bfd_vma memaddr, default: /* There is no instruction whose length is not 2, 4, 6, or 8. */ - abort (); + return -1; } pr_debug ("instruction value = %llx\n", insn); @@ -1121,7 +1166,7 @@ print_insn_arc (bfd_vma memaddr, info->target2 = 0; /* FIXME to be moved in dissasemble_init_for_target. */ - info->disassembler_needs_relocs = TRUE; + info->disassembler_needs_relocs = true; /* Find the first match in the opcode table. */ if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter)) @@ -1132,27 +1177,49 @@ print_insn_arc (bfd_vma memaddr, switch (insn_len) { case 2: - (*info->fprintf_func) (info->stream, ".long %#04llx", - insn & 0xffff); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".short"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%04llx", insn & 0xffff); break; + case 4: - (*info->fprintf_func) (info->stream, ".long %#08llx", - insn & 0xffffffff); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".word"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%08llx", insn & 0xffffffff); break; + case 6: - (*info->fprintf_func) (info->stream, ".long %#08llx", - insn & 0xffffffff); - (*info->fprintf_func) (info->stream, ".long %#04llx", - (insn >> 32) & 0xffff); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".long"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%08llx", insn & 0xffffffff); + (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%04llx", (insn >> 32) & 0xffff); break; + case 8: - (*info->fprintf_func) (info->stream, ".long %#08llx", - insn & 0xffffffff); - (*info->fprintf_func) (info->stream, ".long %#08llx", - insn >> 32); + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, + ".long"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%08llx", insn & 0xffffffff); + (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "0x%08llx", (insn >> 32)); break; + default: - abort (); + return -1; } info->insn_type = dis_noninsn; @@ -1160,7 +1227,8 @@ print_insn_arc (bfd_vma memaddr, } /* Print the mnemonic. */ - (*info->fprintf_func) (info->stream, "%s", opcode->name); + (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, + "%s", opcode->name); /* Preselect the insn class. */ info->insn_type = arc_opcode_to_insn_type (opcode); @@ -1170,20 +1238,21 @@ print_insn_arc (bfd_vma memaddr, print_flags (opcode, &insn, info); if (opcode->operands[0] != 0) - (*info->fprintf_func) (info->stream, "\t"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); - need_comma = FALSE; - open_braket = FALSE; + need_comma = false; + open_braket = false; arc_infop->operands_count = 0; /* Now extract and print the operands. */ operand = NULL; + vpcl = 0; while (operand_iterator_next (&iter, &operand, &value)) { if (open_braket && (operand->flags & ARC_OPERAND_BRAKET)) { - (*info->fprintf_func) (info->stream, "]"); - open_braket = FALSE; + (*info->fprintf_styled_func) (info->stream, dis_style_text, "]"); + open_braket = false; continue; } @@ -1198,22 +1267,36 @@ print_insn_arc (bfd_vma memaddr, if (operand->flags & ARC_OPERAND_COLON) { - (*info->fprintf_func) (info->stream, ":"); + (*info->fprintf_styled_func) (info->stream, dis_style_text, ":"); continue; } if (need_comma) - (*info->fprintf_func) (info->stream, ","); + (*info->fprintf_styled_func) (info->stream, dis_style_text,","); if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET)) { - (*info->fprintf_func) (info->stream, "["); - open_braket = TRUE; - need_comma = FALSE; + (*info->fprintf_styled_func) (info->stream, dis_style_text, "["); + open_braket = true; + need_comma = false; continue; } - need_comma = TRUE; + need_comma = true; + + if (operand->flags & ARC_OPERAND_PCREL) + { + rpcl = true; + vpcl = value; + rset = true; + + info->target = (bfd_vma) (memaddr & ~3) + value; + } + else if (!(operand->flags & ARC_OPERAND_IR)) + { + vpcl = value; + rset = true; + } /* Print the operand as directed by the flags. */ if (operand->flags & ARC_OPERAND_IR) @@ -1224,57 +1307,68 @@ print_insn_arc (bfd_vma memaddr, rname = arcExtMap_coreRegName (value); if (!rname) rname = regnames[value]; - (*info->fprintf_func) (info->stream, "%s", rname); + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "%s", rname); + + /* Check if we have a double register to print. */ if (operand->flags & ARC_OPERAND_TRUNCATE) { - rname = arcExtMap_coreRegName (value + 1); - if (!rname) - rname = regnames[value + 1]; - (*info->fprintf_func) (info->stream, "%s", rname); + if ((value & 0x01) == 0) + { + rname = arcExtMap_coreRegName (value + 1); + if (!rname) + rname = regnames[value + 1]; + } + else + rname = _("\nWarning: illegal use of double register " + "pair.\n"); + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "%s", rname); } + if (value == 63) + rpcl = true; + else + rpcl = false; } else if (operand->flags & ARC_OPERAND_LIMM) { const char *rname = get_auxreg (opcode, value, isa_mask); if (rname && open_braket) - (*info->fprintf_func) (info->stream, "%s", rname); + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "%s", rname); else { - (*info->fprintf_func) (info->stream, "%#x", value); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "%#x", value); if (info->insn_type == dis_branch || info->insn_type == dis_jsr) info->target = (bfd_vma) value; } } - else if (operand->flags & ARC_OPERAND_PCREL) - { - /* PCL relative. */ - if (info->flags & INSN_HAS_RELOC) - memaddr = 0; - (*info->print_address_func) ((memaddr & ~3) + value, info); - - info->target = (bfd_vma) (memaddr & ~3) + value; - } else if (operand->flags & ARC_OPERAND_SIGNED) { const char *rname = get_auxreg (opcode, value, isa_mask); if (rname && open_braket) - (*info->fprintf_func) (info->stream, "%s", rname); + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "%s", rname); else { if (print_hex) - (*info->fprintf_func) (info->stream, "%#x", value); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "%#x", value); else - (*info->fprintf_func) (info->stream, "%d", value); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "%d", value); } } else if (operand->flags & ARC_OPERAND_ADDRTYPE) { const char *addrtype = get_addrtype (value); - (*info->fprintf_func) (info->stream, "%s", addrtype); + (*info->fprintf_styled_func) (info->stream, dis_style_address, + "%s", addrtype); /* A colon follow an address type. */ - need_comma = FALSE; + need_comma = false; } else { @@ -1283,27 +1377,38 @@ print_insn_arc (bfd_vma memaddr, && !(operand->flags & ARC_OPERAND_ALIGNED16) && value >= 0 && value <= 14) { + /* Leave/Enter mnemonics. */ switch (value) { case 0: - need_comma = FALSE; + need_comma = false; break; case 1: - (*info->fprintf_func) (info->stream, "r13"); + (*info->fprintf_styled_func) (info->stream, + dis_style_register, "r13"); break; default: - (*info->fprintf_func) (info->stream, "r13-%s", - regnames[13 + value - 1]); + (*info->fprintf_styled_func) (info->stream, + dis_style_register, "r13"); + (*info->fprintf_styled_func) (info->stream, + dis_style_text, "-"); + (*info->fprintf_styled_func) (info->stream, + dis_style_register, "%s", + regnames[13 + value - 1]); break; } + rpcl = false; + rset = false; } else { const char *rname = get_auxreg (opcode, value, isa_mask); if (rname && open_braket) - (*info->fprintf_func) (info->stream, "%s", rname); + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "%s", rname); else - (*info->fprintf_func) (info->stream, "%#x", value); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, + "%#x", value); } } @@ -1326,6 +1431,22 @@ print_insn_arc (bfd_vma memaddr, arc_infop->operands_count ++; } + /* Pretty print extra info for pc-relative operands. */ + if (rpcl && rset) + { + if (info->flags & INSN_HAS_RELOC) + /* If the instruction has a reloc associated with it, then the + offset field in the instruction will actually be the addend + for the reloc. (We are using REL type relocs). In such + cases, we can ignore the pc when computing addresses, since + the addend is not currently pc-relative. */ + memaddr = 0; + + (*info->fprintf_styled_func) (info->stream, + dis_style_comment_start, "\t;"); + (*info->print_address_func) ((memaddr & ~3) + vpcl, info); + } + return insn_len; } @@ -1347,39 +1468,169 @@ arc_get_disassembler (bfd *abfd) return print_insn_arc; } +/* Indices into option argument vector for options that do require + an argument. Use ARC_OPTION_ARG_NONE for options that don't + expect an argument. */ +typedef enum +{ + ARC_OPTION_ARG_NONE = -1, + ARC_OPTION_ARG_ARCH, + ARC_OPTION_ARG_SIZE +} arc_option_arg_t; + +/* Valid ARC disassembler options. */ +static struct +{ + const char *name; + const char *description; + arc_option_arg_t arg; +} arc_options[] = +{ + { "cpu=", N_("Enforce the designated architecture while decoding."), + ARC_OPTION_ARG_ARCH }, + { "dsp", N_("Recognize DSP instructions."), + ARC_OPTION_ARG_NONE }, + { "spfp", N_("Recognize FPX SP instructions."), + ARC_OPTION_ARG_NONE }, + { "dpfp", N_("Recognize FPX DP instructions."), + ARC_OPTION_ARG_NONE }, + { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."), + ARC_OPTION_ARG_NONE }, + { "fpuda", N_("Recognize double assist FPU instructions."), + ARC_OPTION_ARG_NONE }, + { "fpus", N_("Recognize single precision FPU instructions."), + ARC_OPTION_ARG_NONE }, + { "fpud", N_("Recognize double precision FPU instructions."), + ARC_OPTION_ARG_NONE }, + { "nps400", N_("Recognize NPS400 instructions."), + ARC_OPTION_ARG_NONE }, + { "hex", N_("Use only hexadecimal number to print immediates."), + ARC_OPTION_ARG_NONE } +}; + +/* Populate the structure for representing ARC's disassembly options. + Such a dynamic initialization is desired, because it makes the maintenance + easier and also gdb uses this to enable the "disassembler-option". */ + +const disasm_options_and_args_t * +disassembler_options_arc (void) +{ + static disasm_options_and_args_t *opts_and_args; + + if (opts_and_args == NULL) + { + disasm_option_arg_t *args; + disasm_options_t *opts; + size_t i; + const size_t nr_of_options = ARRAY_SIZE (arc_options); + /* There is a null element at the end of CPU_TYPES, therefore + NR_OF_CPUS is actually 1 more and that is desired here too. */ + const size_t nr_of_cpus = ARRAY_SIZE (cpu_types); + + opts_and_args = XNEW (disasm_options_and_args_t); + opts_and_args->args + = XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1); + opts_and_args->options.name + = XNEWVEC (const char *, nr_of_options + 1); + opts_and_args->options.description + = XNEWVEC (const char *, nr_of_options + 1); + opts_and_args->options.arg + = XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1); + + /* Populate the arguments for "cpu=" option. */ + args = opts_and_args->args; + args[ARC_OPTION_ARG_ARCH].name = "ARCH"; + args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus); + for (i = 0; i < nr_of_cpus; ++i) + args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name; + args[ARC_OPTION_ARG_SIZE].name = NULL; + args[ARC_OPTION_ARG_SIZE].values = NULL; + + /* Populate the options. */ + opts = &opts_and_args->options; + for (i = 0; i < nr_of_options; ++i) + { + opts->name[i] = arc_options[i].name; + opts->description[i] = arc_options[i].description; + if (arc_options[i].arg != ARC_OPTION_ARG_NONE) + opts->arg[i] = &args[arc_options[i].arg]; + else + opts->arg[i] = NULL; + } + opts->name[nr_of_options] = NULL; + opts->description[nr_of_options] = NULL; + opts->arg[nr_of_options] = NULL; + } + + return opts_and_args; +} + + void print_arc_disassembler_options (FILE *stream) { - int i; + const disasm_options_and_args_t *opts_and_args; + const disasm_option_arg_t *args; + const disasm_options_t *opts; + size_t i, j; + size_t max_len = 0; + + opts_and_args = disassembler_options_arc (); + opts = &opts_and_args->options; + args = opts_and_args->args; + + fprintf (stream, _("\nThe following ARC specific disassembler options are" + " supported for use \nwith the -M switch (multiple" + " options should be separated by commas):\n")); + + /* Find the maximum length for printing options (and their arg name). */ + for (i = 0; opts->name[i] != NULL; ++i) + { + size_t len = strlen (opts->name[i]); + len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0; + max_len = (len > max_len) ? len : max_len; + } - fprintf (stream, _("\n\ -The following ARC specific disassembler options are supported for use \n\ -with -M switch (multiple options should be separated by commas):\n")); + /* Print the options, their arg and description, if any. */ + for (i = 0, ++max_len; opts->name[i] != NULL; ++i) + { + fprintf (stream, " %s", opts->name[i]); + if (opts->arg[i] != NULL) + fprintf (stream, "%s", opts->arg[i]->name); + if (opts->description[i] != NULL) + { + size_t len = strlen (opts->name[i]); + len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0; + fprintf (stream, + "%*c %s", (int) (max_len - len), ' ', opts->description[i]); + } + fprintf (stream, _("\n")); + } - /* cpu=... options. */ - for (i = 0; cpu_types[i].name; ++i) + /* Print the possible values of an argument. */ + for (i = 0; args[i].name != NULL; ++i) { - /* As of now all value CPU values are less than 16 characters. */ - fprintf (stream, " cpu=%-16s\tEnforce %s ISA.\n", - cpu_types[i].name, cpu_types[i].isa); + size_t len = 3; + if (args[i].values == NULL) + continue; + fprintf (stream, _("\n\ + For the options above, the following values are supported for \"%s\":\n "), + args[i].name); + for (j = 0; args[i].values[j] != NULL; ++j) + { + fprintf (stream, " %s", args[i].values[j]); + len += strlen (args[i].values[j]) + 1; + /* reset line if printed too long. */ + if (len >= 78) + { + fprintf (stream, _("\n ")); + len = 3; + } + } + fprintf (stream, _("\n")); } - fprintf (stream, _("\ - dsp Recognize DSP instructions.\n")); - fprintf (stream, _("\ - spfp Recognize FPX SP instructions.\n")); - fprintf (stream, _("\ - dpfp Recognize FPX DP instructions.\n")); - fprintf (stream, _("\ - quarkse_em Recognize FPU QuarkSE-EM instructions.\n")); - fprintf (stream, _("\ - fpuda Recognize double assist FPU instructions.\n")); - fprintf (stream, _("\ - fpus Recognize single precision FPU instructions.\n")); - fprintf (stream, _("\ - fpud Recognize double precision FPU instructions.\n")); - fprintf (stream, _("\ - hex Use only hexadecimal number to print immediates.\n")); + fprintf (stream, _("\n")); } void arc_insn_decode (bfd_vma addr, @@ -1396,7 +1647,7 @@ void arc_insn_decode (bfd_vma addr, /* There was an error when disassembling, for example memory read error. */ if (disasm_func (addr, info) < 0) { - insn->valid = FALSE; + insn->valid = false; return; } @@ -1409,11 +1660,11 @@ void arc_insn_decode (bfd_vma addr, /* Quick exit if memory at this address is not an instruction. */ if (info->insn_type == dis_noninsn) { - insn->valid = FALSE; + insn->valid = false; return; } - insn->valid = TRUE; + insn->valid = true; opcode = (const struct arc_opcode *) arc_infop->opcode; insn->insn_class = opcode->insn_class;