diff options
Diffstat (limited to 'opcodes/arc-dis.c')
-rw-r--r-- | opcodes/arc-dis.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c index 7541b74..71acc10 100644 --- a/opcodes/arc-dis.c +++ b/opcodes/arc-dis.c @@ -923,9 +923,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) { @@ -1022,6 +1023,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); @@ -1132,23 +1134,23 @@ 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: @@ -1178,6 +1180,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)) @@ -1215,6 +1218,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) { @@ -1232,6 +1249,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) { @@ -1247,15 +1268,6 @@ 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); @@ -1283,6 +1295,7 @@ print_insn_arc (bfd_vma memaddr, && !(operand->flags & ARC_OPERAND_ALIGNED16) && value >= 0 && value <= 14) { + /* Leave/Enter mnemonics. */ switch (value) { case 0: @@ -1296,6 +1309,8 @@ print_insn_arc (bfd_vma memaddr, regnames[13 + value - 1]); break; } + rpcl = FALSE; + rset = FALSE; } else { @@ -1326,6 +1341,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; } |