X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Farc-dis.c;h=dc9e490ce8aed8fcafdd1b0f76182b1667c92a27;hb=884287754e8da49581b4873b936d8eba7b1f052e;hp=edd0c0735a2510c7eeb6673161c2716592c01076;hpb=10045478d984f9924cb945423388ba25b7dd3ffe;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c index edd0c0735a..dc9e490ce8 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-2020 Free Software Foundation, Inc. Contributed by Claudiu Zissulescu (claziss@synopsys.com) @@ -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] = @@ -122,6 +122,9 @@ 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; + /* Macros section. */ #ifdef DEBUG @@ -134,8 +137,7 @@ static unsigned enforced_isa_mask = ARC_OPCODE_NONE; (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. */ @@ -178,7 +180,9 @@ skip_this_opcode (const struct arc_opcode *opcode) /* Check opcode for major 0x06, return if it is not in. */ if (arc_opcode_len (opcode) == 4 - && OPCODE_32BIT_INSN (opcode->opcode) != 0x06) + && (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. */ @@ -186,6 +190,8 @@ skip_this_opcode (const struct arc_opcode *opcode) { case FLOAT: case DSP: + case ARITH: + case MPY: break; default: return FALSE; @@ -288,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. */ @@ -414,7 +420,7 @@ find_format (bfd_vma memaddr, struct arc_operand_iterator * iter) { const struct arc_opcode *opcode = NULL; - bfd_boolean needs_limm; + bfd_boolean needs_limm = FALSE; const extInstruction_t *einsn, *i; unsigned limm = 0; struct arc_disassemble_info *arc_infop = info->private_data; @@ -430,8 +436,9 @@ 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_func) (info->stream, + _("An error occured while generating the " + "extension instruction operations")); *opcode_result = NULL; return FALSE; } @@ -446,7 +453,7 @@ An error occured while generating the extension instruction operations"); opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len, isa_mask, &needs_limm, TRUE); - if (needs_limm && opcode != NULL) + if (opcode != NULL && needs_limm) { bfd_byte buffer[4]; int status; @@ -476,7 +483,7 @@ 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; @@ -665,7 +672,7 @@ arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info) break; default: - abort (); + return 0; } } @@ -740,16 +747,16 @@ operand_iterator_next (struct arc_operand_iterator *iter, static void parse_option (const char *option) { - if (CONST_STRNEQ (option, "dsp")) + if (disassembler_options_cmp (option, "dsp") == 0) add_to_decodelist (DSP, NONE); - else if (CONST_STRNEQ (option, "spfp")) + else if (disassembler_options_cmp (option, "spfp") == 0) add_to_decodelist (FLOAT, SPX); - else if (CONST_STRNEQ (option, "dpfp")) + else if (disassembler_options_cmp (option, "dpfp") == 0) add_to_decodelist (FLOAT, DPX); - else if (CONST_STRNEQ (option, "quarkse_em")) + else if (disassembler_options_cmp (option, "quarkse_em") == 0) { add_to_decodelist (FLOAT, DPX); add_to_decodelist (FLOAT, SPX); @@ -757,22 +764,42 @@ parse_option (const char *option) add_to_decodelist (FLOAT, QUARKSE2); } - else if (CONST_STRNEQ (option, "fpuda")) + else if (disassembler_options_cmp (option, "fpuda") == 0) add_to_decodelist (FLOAT, DPA); - else if (CONST_STRNEQ (option, "fpus")) + 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); add_to_decodelist (FLOAT, CVT); } - else if (CONST_STRNEQ (option, "fpud")) + else if (disassembler_options_cmp (option, "fpud") == 0) { add_to_decodelist (FLOAT, DP); add_to_decodelist (FLOAT, CVT); } + else if (CONST_STRNEQ (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) \ @@ -808,13 +835,14 @@ parse_cpu_option (const char *option) for (i = 0; cpu_types[i].name; ++i) { - if (!strcasecmp (cpu_types[i].name, option)) + if (!disassembler_options_cmp (cpu_types[i].name, option)) { return cpu_types[i].flags; } } - 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; } @@ -823,6 +851,8 @@ parse_cpu_option (const char *option) static void parse_disassembler_options (const char *options) { + const char *option; + if (options == NULL) return; @@ -832,25 +862,15 @@ parse_disassembler_options (const char *options) CPU when new options are being parsed. */ enforced_isa_mask = ARC_OPCODE_NONE; - while (*options) + FOR_EACH_DISASSEMBLER_OPTION (option, options) { - /* Skip empty options. */ - if (*options == ',') - { - ++ options; - continue; - } - /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a preprocessor macro. */ - if (strncmp (options, "cpu=", 4) == 0) + if (strncmp (option, "cpu=", 4) == 0) /* Strip leading `cpu=`. */ - enforced_isa_mask = parse_cpu_option (options + 4); + enforced_isa_mask = parse_cpu_option (option + 4); else - parse_option (options); - - while (*options != ',' && *options != '\0') - ++ options; + parse_option (option); } } @@ -925,9 +945,10 @@ print_insn_arc (bfd_vma memaddr, bfd_boolean 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; + bfd_boolean rpcl = FALSE, rset = FALSE; if (info->disassembler_options) { @@ -988,7 +1009,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 @@ -996,7 +1016,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)) { @@ -1024,6 +1043,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); @@ -1050,13 +1070,16 @@ print_insn_arc (bfd_vma memaddr, (*info->fprintf_func) (info->stream, ".word\t0x%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; @@ -1109,7 +1132,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); @@ -1134,27 +1157,31 @@ print_insn_arc (bfd_vma memaddr, switch (insn_len) { case 2: - (*info->fprintf_func) (info->stream, ".long %#04llx", + (*info->fprintf_func) (info->stream, ".shor\t%#04llx", insn & 0xffff); break; + case 4: - (*info->fprintf_func) (info->stream, ".long %#08llx", + (*info->fprintf_func) (info->stream, ".word\t%#08llx", insn & 0xffffffff); break; + case 6: - (*info->fprintf_func) (info->stream, ".long %#08llx", + (*info->fprintf_func) (info->stream, ".long\t%#08llx", insn & 0xffffffff); - (*info->fprintf_func) (info->stream, ".long %#04llx", + (*info->fprintf_func) (info->stream, ".long\t%#04llx", (insn >> 32) & 0xffff); break; + case 8: - (*info->fprintf_func) (info->stream, ".long %#08llx", + (*info->fprintf_func) (info->stream, ".long\t%#08llx", insn & 0xffffffff); - (*info->fprintf_func) (info->stream, ".long %#08llx", + (*info->fprintf_func) (info->stream, ".long\t%#08llx", insn >> 32); break; + default: - abort (); + return -1; } info->insn_type = dis_noninsn; @@ -1180,6 +1207,7 @@ print_insn_arc (bfd_vma memaddr, /* 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)) @@ -1217,6 +1245,20 @@ print_insn_arc (bfd_vma memaddr, 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) { @@ -1234,6 +1276,10 @@ print_insn_arc (bfd_vma memaddr, rname = regnames[value + 1]; (*info->fprintf_func) (info->stream, "%s", rname); } + if (value == 63) + rpcl = TRUE; + else + rpcl = FALSE; } else if (operand->flags & ARC_OPERAND_LIMM) { @@ -1249,22 +1295,18 @@ print_insn_arc (bfd_vma memaddr, 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); else - (*info->fprintf_func) (info->stream, "%d", value); + { + if (print_hex) + (*info->fprintf_func) (info->stream, "%#x", value); + else + (*info->fprintf_func) (info->stream, "%d", value); + } } else if (operand->flags & ARC_OPERAND_ADDRTYPE) { @@ -1280,6 +1322,7 @@ print_insn_arc (bfd_vma memaddr, && !(operand->flags & ARC_OPERAND_ALIGNED16) && value >= 0 && value <= 14) { + /* Leave/Enter mnemonics. */ switch (value) { case 0: @@ -1293,6 +1336,8 @@ print_insn_arc (bfd_vma memaddr, regnames[13 + value - 1]); break; } + rpcl = FALSE; + rset = FALSE; } else { @@ -1323,6 +1368,21 @@ 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_func) (info->stream, "\t;"); + (*info->print_address_func) ((memaddr & ~3) + vpcl, info); + } + return insn_len; } @@ -1375,6 +1435,10 @@ with -M switch (multiple options should be separated by commas):\n")); fpus Recognize single precision FPU instructions.\n")); fprintf (stream, _("\ fpud Recognize double precision FPU instructions.\n")); + fprintf (stream, _("\ + nps400 Recognize NPS400 instructions.\n")); + fprintf (stream, _("\ + hex Use only hexadecimal number to print immediates.\n")); } void arc_insn_decode (bfd_vma addr,