X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Frl78-dis.c;h=ef7d9490169e23d3673f5af99714014048488c43;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=3c365adc82af0284ee784d3ff64b33a8c6874c7b;hpb=5eb3690ee9d6bf3a5d60d2853bc6c1be8c251f06;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/rl78-dis.c b/opcodes/rl78-dis.c index 3c365adc82..ef7d949016 100644 --- a/opcodes/rl78-dis.c +++ b/opcodes/rl78-dis.c @@ -1,5 +1,5 @@ /* Disassembler code for Renesas RL78. - Copyright 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 2011-2020 Free Software Foundation, Inc. Contributed by Red Hat. Written by DJ Delorie. @@ -24,8 +24,12 @@ #include #include "bfd.h" -#include "dis-asm.h" +#include "elf-bfd.h" +#include "disassemble.h" #include "opcode/rl78.h" +#include "elf/rl78.h" + +#include #define DEBUG_SEMANTICS 0 @@ -35,16 +39,30 @@ typedef struct disassemble_info * dis; } RL78_Data; +struct private +{ + OPCODES_SIGJMP_BUF bailout; +}; + static int rl78_get_byte (void * vdata) { bfd_byte buf[1]; RL78_Data *rl78_data = (RL78_Data *) vdata; + int status; - rl78_data->dis->read_memory_func (rl78_data->pc, - buf, - 1, - rl78_data->dis); + status = rl78_data->dis->read_memory_func (rl78_data->pc, + buf, + 1, + rl78_data->dis); + if (status != 0) + { + struct private *priv = (struct private *) rl78_data->dis->private_data; + + rl78_data->dis->memory_error_func (status, rl78_data->pc, + rl78_data->dis); + OPCODES_SIGLONGJMP (priv->bailout, 1); + } rl78_data->pc ++; return buf[0]; @@ -80,8 +98,8 @@ indirect_type (int t) } } -int -print_insn_rl78 (bfd_vma addr, disassemble_info * dis) +static int +print_insn_rl78_common (bfd_vma addr, disassemble_info * dis, RL78_Dis_Isa isa) { int rv; RL78_Data rl78_data; @@ -90,11 +108,19 @@ print_insn_rl78 (bfd_vma addr, disassemble_info * dis) #if DEBUG_SEMANTICS static char buf[200]; #endif + struct private priv; + dis->private_data = (PTR) &priv; rl78_data.pc = addr; rl78_data.dis = dis; - rv = rl78_decode_opcode (addr, &opcode, rl78_get_byte, &rl78_data); + if (OPCODES_SIGSETJMP (priv.bailout) != 0) + { + /* Error return. */ + return -1; + } + + rv = rl78_decode_opcode (addr, &opcode, rl78_get_byte, &rl78_data, isa); dis->bytes_per_line = 10; @@ -155,38 +181,34 @@ print_insn_rl78 (bfd_vma addr, disassemble_info * dis) int do_cond = 0; int do_bang = 0; - s ++; - - if (*s == 'x') - { - do_hex = 1; - s++; - } - if (*s == '!') - { - do_bang = 1; - s++; - } - if (*s == 'e') + while (1) { - do_es = 1; - s++; - } - if (*s == 'a') - { - do_addr = 1; - s++; - } - if (*s == 's') - { - do_sfr = 1; - s++; - } - if (*s == 'c') - { - do_cond = 1; - s++; + s ++; + switch (*s) + { + case 'x': + do_hex = 1; + break; + case '!': + do_bang = 1; + break; + case 'e': + do_es = 1; + break; + case 'a': + do_addr = 1; + break; + case 's': + do_sfr = 1; + break; + case 'c': + do_cond = 1; + break; + default: + goto no_more_modifiers; + } } + no_more_modifiers:; switch (*s) { @@ -206,7 +228,7 @@ print_insn_rl78 (bfd_vma addr, disassemble_info * dis) { char *comma = ""; PR (PS, " \033[35m"); - + if (opcode.flags & RL78_PSW_Z) { PR (PS, "Z"); comma = ","; } if (opcode.flags & RL78_PSW_AC) @@ -221,99 +243,129 @@ print_insn_rl78 (bfd_vma addr, disassemble_info * dis) case '0': case '1': - oper = opcode.op + *s - '0'; - if (do_bang) - PC ('!'); - - if (do_es) - { - if (oper->use_es && indirect_type (oper->type)) - PR (PS, "es:"); - } - - else if (do_cond) - { - PR (PS, "%s", condition_names[oper->condition]); - } - - else - switch (oper->type) + oper = *s == '0' ? &opcode.op[0] : &opcode.op[1]; + if (do_es) + { + if (oper->use_es && indirect_type (oper->type)) + PR (PS, "es:"); + } + + if (do_bang) + { + /* If we are going to display SP by name, we must omit the bang. */ + if ((oper->type == RL78_Operand_Indirect + || oper->type == RL78_Operand_BitIndirect) + && oper->reg == RL78_Reg_None + && do_sfr + && ((oper->addend == 0xffff8 && opcode.size == RL78_Word) + || (oper->addend == 0x0fff8 && do_es && opcode.size == RL78_Word))) + ; + else + PC ('!'); + } + + if (do_cond) + { + PR (PS, "%s", condition_names[oper->condition]); + break; + } + + switch (oper->type) + { + case RL78_Operand_Immediate: + if (do_addr) + dis->print_address_func (oper->addend, dis); + else if (do_hex + || oper->addend > 999 + || oper->addend < -999) + PR (PS, "%#x", oper->addend); + else + PR (PS, "%d", oper->addend); + break; + + case RL78_Operand_Register: + PR (PS, "%s", register_names[oper->reg]); + break; + + case RL78_Operand_Bit: + PR (PS, "%s.%d", register_names[oper->reg], oper->bit_number); + break; + + case RL78_Operand_Indirect: + case RL78_Operand_BitIndirect: + switch (oper->reg) { - case RL78_Operand_Immediate: - if (do_addr) - dis->print_address_func (oper->addend, dis); - else if (do_hex - || oper->addend > 999 - || oper->addend < -999) + case RL78_Reg_None: + if (oper->addend == 0xffffa && do_sfr && opcode.size == RL78_Byte) + PR (PS, "psw"); + else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Word) + PR (PS, "sp"); + else if (oper->addend == 0x0fff8 && do_sfr && do_es && opcode.size == RL78_Word) + PR (PS, "sp"); + else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Byte) + PR (PS, "spl"); + else if (oper->addend == 0xffff9 && do_sfr && opcode.size == RL78_Byte) + PR (PS, "sph"); + else if (oper->addend == 0xffffc && do_sfr && opcode.size == RL78_Byte) + PR (PS, "cs"); + else if (oper->addend == 0xffffd && do_sfr && opcode.size == RL78_Byte) + PR (PS, "es"); + else if (oper->addend == 0xffffe && do_sfr && opcode.size == RL78_Byte) + PR (PS, "pmc"); + else if (oper->addend == 0xfffff && do_sfr && opcode.size == RL78_Byte) + PR (PS, "mem"); + else if (oper->addend >= 0xffe20) PR (PS, "%#x", oper->addend); else - PR (PS, "%d", oper->addend); + { + int faddr = oper->addend; + if (do_es && ! oper->use_es) + faddr += 0xf0000; + dis->print_address_func (faddr, dis); + } break; - case RL78_Operand_Register: - PR (PS, "%s", register_names[oper->reg]); + case RL78_Reg_B: + case RL78_Reg_C: + case RL78_Reg_BC: + PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]); break; - case RL78_Operand_Bit: - PR (PS, "%s.%d", register_names[oper->reg], oper->bit_number); + default: + PR (PS, "[%s", register_names[oper->reg]); + if (oper->reg2 != RL78_Reg_None) + PR (PS, "+%s", register_names[oper->reg2]); + if (oper->addend || do_addr) + PR (PS, "+%d", oper->addend); + PC (']'); break; - case RL78_Operand_Indirect: - case RL78_Operand_BitIndirect: - switch (oper->reg) - { - case RL78_Reg_None: - if (oper->addend == 0xffffa && do_sfr && opcode.size == RL78_Byte) - PR (PS, "psw"); - else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Word) - PR (PS, "sp"); - else if (oper->addend >= 0xffe20) - PR (PS, "%#x", oper->addend); - else - dis->print_address_func (oper->addend, dis); - break; - - case RL78_Reg_B: - case RL78_Reg_C: - case RL78_Reg_BC: - PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]); - break; - - default: - PR (PS, "[%s", register_names[oper->reg]); - if (oper->reg2 != RL78_Reg_None) - PR (PS, "+%s", register_names[oper->reg2]); - if (oper->addend) - PR (PS, "+%d", oper->addend); - PC (']'); - break; - - } - if (oper->type == RL78_Operand_BitIndirect) - PR (PS, ".%d", oper->bit_number); - break; + } + if (oper->type == RL78_Operand_BitIndirect) + PR (PS, ".%d", oper->bit_number); + break; #if DEBUG_SEMANTICS - /* Shouldn't happen - push and pop don't print - [SP] directly. But we *do* use them for - semantic debugging. */ - case RL78_Operand_PostInc: - PR (PS, "[%s++]", register_names[oper->reg]); - break; - case RL78_Operand_PreDec: - PR (PS, "[--%s]", register_names[oper->reg]); - break; + /* Shouldn't happen - push and pop don't print + [SP] directly. But we *do* use them for + semantic debugging. */ + case RL78_Operand_PostInc: + PR (PS, "[%s++]", register_names[oper->reg]); + break; + case RL78_Operand_PreDec: + PR (PS, "[--%s]", register_names[oper->reg]); + break; #endif - default: - /* If we ever print this, that means the - programmer tried to print an operand with a - type we don't expect. Print the line and - operand number from rl78-decode.opc for - them. */ - PR (PS, "???%d.%d", opcode.lineno, *s - '0'); - break; - } + default: + /* If we ever print this, that means the + programmer tried to print an operand with a + type we don't expect. Print the line and + operand number from rl78-decode.opc for + them. */ + PR (PS, "???%d.%d", opcode.lineno, *s - '0'); + break; + } } } } @@ -326,3 +378,48 @@ print_insn_rl78 (bfd_vma addr, disassemble_info * dis) return rv; } + +int +print_insn_rl78 (bfd_vma addr, disassemble_info * dis) +{ + return print_insn_rl78_common (addr, dis, RL78_ISA_DEFAULT); +} + +int +print_insn_rl78_g10 (bfd_vma addr, disassemble_info * dis) +{ + return print_insn_rl78_common (addr, dis, RL78_ISA_G10); +} + +int +print_insn_rl78_g13 (bfd_vma addr, disassemble_info * dis) +{ + return print_insn_rl78_common (addr, dis, RL78_ISA_G13); +} + +int +print_insn_rl78_g14 (bfd_vma addr, disassemble_info * dis) +{ + return print_insn_rl78_common (addr, dis, RL78_ISA_G14); +} + +disassembler_ftype +rl78_get_disassembler (bfd *abfd) +{ + int cpu = E_FLAG_RL78_ANY_CPU; + + if (abfd != NULL) + cpu = abfd->tdata.elf_obj_data->elf_header->e_flags & E_FLAG_RL78_CPU_MASK; + + switch (cpu) + { + case E_FLAG_RL78_G10: + return print_insn_rl78_g10; + case E_FLAG_RL78_G13: + return print_insn_rl78_g13; + case E_FLAG_RL78_G14: + return print_insn_rl78_g14; + default: + return print_insn_rl78; + } +}