diff options
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/ChangeLog | 8 | ||||
-rw-r--r-- | opcodes/m68hc11-dis.c | 49 |
2 files changed, 52 insertions, 5 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 643a987..72469fd 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,11 @@ +2002-12-01 Stephane Carrez <stcarrez@nerim.fr> + + * m68hc11-dis.c (PC_REGNUM): Define. + (print_indexed_operand): Need an adjustment for some PC-relative + operand modes; print the final address of PC-relative modes. + (print_insn): Take into account movw/movb to adjust the PC-relative + operand addresses. + 2002-11-30 Alan Modra <amodra@bigpond.net.au> *arm-dis.c, cris-dis.c, h8300-dis.c, mips-dis.c, mmix-dis.c, sh-dis.c, diff --git a/opcodes/m68hc11-dis.c b/opcodes/m68hc11-dis.c index bcd3ee5..33d1f0e 100644 --- a/opcodes/m68hc11-dis.c +++ b/opcodes/m68hc11-dis.c @@ -22,6 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "opcode/m68hc11.h" #include "dis-asm.h" +#define PC_REGNUM 3 + static const char *const reg_name[] = { "X", "Y", "SP", "PC" }; @@ -40,7 +42,7 @@ static const char *const reg_dst_table[] = { static int read_memory PARAMS ((bfd_vma, bfd_byte *, int, struct disassemble_info *)); static int print_indexed_operand - PARAMS ((bfd_vma, struct disassemble_info *, int*, int)); + PARAMS ((bfd_vma, struct disassemble_info *, int*, int, int, bfd_vma)); static int print_insn PARAMS ((bfd_vma, struct disassemble_info *, int)); @@ -68,11 +70,13 @@ read_memory (memaddr, buffer, size, info) /* Read the 68HC12 indexed operand byte and print the corresponding mode. Returns the number of bytes read or -1 if failure. */ static int -print_indexed_operand (memaddr, info, indirect, mov_insn) +print_indexed_operand (memaddr, info, indirect, mov_insn, pc_offset, endaddr) bfd_vma memaddr; struct disassemble_info *info; int *indirect; int mov_insn; + int pc_offset; + bfd_vma endaddr; { bfd_byte buffer[4]; int reg; @@ -96,8 +100,18 @@ print_indexed_operand (memaddr, info, indirect, mov_insn) sval = (buffer[0] & 0x1f); if (sval & 0x10) sval |= 0xfff0; + /* 68HC12 requires an adjustment for movb/movw pc relative modes. */ + if (reg == PC_REGNUM && info->mach == bfd_mach_m6812 && mov_insn) + sval += pc_offset; (*info->fprintf_func) (info->stream, "%d,%s", (int) sval, reg_name[reg]); + + if (reg == PC_REGNUM) + { + (* info->fprintf_func) (info->stream, " {"); + (* info->print_address_func) (endaddr + sval, info); + (* info->fprintf_func) (info->stream, "}"); + } } /* Auto pre/post increment/decrement. */ @@ -147,6 +161,8 @@ print_indexed_operand (memaddr, info, indirect, mov_insn) if (indirect) *indirect = 1; } + + /* n,r with 9 and 16 bit signed constant. */ else if ((buffer[0] & 0x4) == 0) { if (mov_insn) @@ -177,6 +193,12 @@ print_indexed_operand (memaddr, info, indirect, mov_insn) } (*info->fprintf_func) (info->stream, "%d,%s", (int) sval, reg_name[reg]); + if (reg == PC_REGNUM) + { + (* info->fprintf_func) (info->stream, " {"); + (* info->print_address_func) (endaddr + sval, info); + (* info->fprintf_func) (info->stream, "}"); + } } else { @@ -299,6 +321,8 @@ print_insn (memaddr, info, arch) for (i = 0; i < m68hc11_num_opcodes; i++, opcode++) { int offset; + int pc_src_offset; + int pc_dst_offset; if ((opcode->arch & arch) == 0) continue; @@ -420,10 +444,13 @@ print_insn (memaddr, info, arch) /* This movb/movw is special (see above). */ offset = -offset; + pc_dst_offset = 2; if (format & M6811_OP_IMM8) { (*info->fprintf_func) (info->stream, "#%d", (int) buffer[0]); format &= ~M6811_OP_IMM8; + /* Set PC destination offset. */ + pc_dst_offset = 1; } else if (format & M6811_OP_IX) { @@ -444,13 +471,22 @@ print_insn (memaddr, info, arch) } } +#define M6812_DST_MOVE (M6812_OP_IND16_P2 | M6812_OP_IDX_P2) #define M6812_INDEXED_FLAGS (M6812_OP_IDX|M6812_OP_IDX_1|M6812_OP_IDX_2) /* Analyze the 68HC12 indexed byte. */ if (format & M6812_INDEXED_FLAGS) { int indirect; - - status = print_indexed_operand (memaddr + pos, info, &indirect, 0); + bfd_vma endaddr; + + endaddr = memaddr + pos + 1; + if (format & M6811_OP_IND16) + endaddr += 2; + pc_src_offset = -1; + pc_dst_offset = 1; + status = print_indexed_operand (memaddr + pos, info, &indirect, + (format & M6812_DST_MOVE), + pc_src_offset, endaddr); if (status < 0) { return status; @@ -515,6 +551,7 @@ print_insn (memaddr, info, arch) val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); val &= 0x0FFFF; addr = val; + pc_dst_offset = 2; if (format & M6812_OP_PAGE) { status = read_memory (memaddr + pos + offset, buffer, 1, info); @@ -568,7 +605,9 @@ print_insn (memaddr, info, arch) if (format & M6812_OP_IDX_P2) { (*info->fprintf_func) (info->stream, ", "); - status = print_indexed_operand (memaddr + pos + offset, info, 0, 1); + status = print_indexed_operand (memaddr + pos + offset, info, + 0, 1, pc_dst_offset, + memaddr + pos + offset + 1); if (status < 0) return status; pos += status; |