diff options
author | Stan Shebs <shebs@codesourcery.com> | 2008-08-11 19:00:25 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 2008-08-11 19:00:25 +0000 |
commit | 9d4fde7506bd543f837946511c7adf055148ff23 (patch) | |
tree | aadbf5e5a3f675f7d25a6ff8ac9ce7e08c9deb13 /gdb/arm-tdep.c | |
parent | 90aecf7a80c1cefeb45fc10a6cd02c8338e34b4c (diff) | |
download | gdb-9d4fde7506bd543f837946511c7adf055148ff23.zip gdb-9d4fde7506bd543f837946511c7adf055148ff23.tar.gz gdb-9d4fde7506bd543f837946511c7adf055148ff23.tar.bz2 |
ARM BE8 support.
* disasm.c (gdb_disassemble_info): Set endian_code.
* gdbarch.sh (gdbarch_info): New field byte_order_for_code.
* gdbarch.h, gdbarch.c: Regenerate.
* arch-utils.c (initialize_current_architecture): Set the
default byte_order_for_code.
(gdbarch_info_init): Ditto.
(gdbarch_info_fill): Ditto.
* arm-tdep.c (SWAP_INT, SWAP_SHORT): New macros.
(thumb_analyze_prologue): Swap halfword if code endianness is
different from general endianness.
(arm_skip_prologue): Similarly.
(arm_scan_prologue): Ditto.
(thumb_get_next_pc): Ditto.
(arm_get_next_pc): Ditto.
(arm_gdbarch_init): Set byte_order_for_code from BE8 flag,
choose correct endianness for breakpoints.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r-- | gdb/arm-tdep.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index fd732a8..66add04 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -69,6 +69,19 @@ static int arm_debug; #define MSYMBOL_IS_SPECIAL(msym) \ (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0) +/* Macros for swapping shorts and ints. In the unlikely case that anybody else needs these, + move to a general header. (A better solution might be to define memory read routines that + know whether they are reading code or data.) */ + +#define SWAP_SHORT(x) \ + ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)); + +#define SWAP_INT(x) \ + ( ((x & 0xff000000) >> 24) \ + | ((x & 0x00ff0000) >> 8) \ + | ((x & 0x0000ff00) << 8) \ + | ((x & 0x000000ff) << 24)) + /* Per-objfile data used for mapping symbols. */ static const struct objfile_data *arm_objfile_data_key; @@ -391,6 +404,9 @@ thumb_analyze_prologue (struct gdbarch *gdbarch, insn = read_memory_unsigned_integer (start, 2); + if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch)) + insn = SWAP_SHORT (insn); + if ((insn & 0xfe00) == 0xb400) /* push { rlist } */ { int regno; @@ -559,6 +575,9 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { inst = read_memory_unsigned_integer (skip_pc, 4); + if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch)) + inst = SWAP_INT (inst); + /* "mov ip, sp" is no longer a required part of the prologue. */ if (inst == 0xe1a0c00d) /* mov ip, sp */ continue; @@ -855,6 +874,9 @@ arm_scan_prologue (struct frame_info *this_frame, { unsigned int insn = read_memory_unsigned_integer (current_pc, 4); + if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch)) + insn = SWAP_INT (insn); + if (insn == 0xe1a0c00d) /* mov ip, sp */ { regs[ARM_IP_REGNUM] = regs[ARM_SP_REGNUM]; @@ -1812,6 +1834,9 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc) CORE_ADDR nextpc = pc + 2; /* default is next instruction */ unsigned long offset; + if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch)) + inst1 = SWAP_SHORT (inst1); + if ((inst1 & 0xff00) == 0xbd00) /* pop {rlist, pc} */ { CORE_ADDR sp; @@ -1839,6 +1864,8 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc) else if ((inst1 & 0xf800) == 0xf000) /* long branch with link, and blx */ { unsigned short inst2 = read_memory_unsigned_integer (pc + 2, 2); + if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch)) + inst2 = SWAP_SHORT (inst2); offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1); nextpc = pc_val + offset; /* For BLX make sure to clear the low bits. */ @@ -1874,6 +1901,10 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc) pc_val = (unsigned long) pc; this_instr = read_memory_unsigned_integer (pc, 4); + + if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch)) + this_instr = SWAP_INT (this_instr); + status = get_frame_register_unsigned (frame, ARM_PS_REGNUM); nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */ @@ -3150,6 +3181,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) break; } } + + if (e_flags & EF_ARM_BE8) + info.byte_order_for_code = BFD_ENDIAN_LITTLE; + break; default: @@ -3192,7 +3227,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->have_fpa_registers = have_fpa_registers; /* Breakpoints. */ - switch (info.byte_order) + switch (info.byte_order_for_code) { case BFD_ENDIAN_BIG: tdep->arm_breakpoint = arm_default_arm_be_breakpoint; |