diff options
Diffstat (limited to 'gdb/m32r-linux-tdep.c')
-rw-r--r-- | gdb/m32r-linux-tdep.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c index d2ca1a9..d60d8fa 100644 --- a/gdb/m32r-linux-tdep.c +++ b/gdb/m32r-linux-tdep.c @@ -27,6 +27,7 @@ #include "inferior.h" #include "osabi.h" #include "reggroups.h" +#include "regset.h" #include "gdb_string.h" @@ -309,6 +310,97 @@ m32r_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) return NULL; } +/* Mapping between the registers in `struct pt_regs' + format and GDB's register array layout. */ + +static int m32r_pt_regs_offset[] = { + 4 * 4, /* r0 */ + 4 * 5, /* r1 */ + 4 * 6, /* r2 */ + 4 * 7, /* r3 */ + 4 * 0, /* r4 */ + 4 * 1, /* r5 */ + 4 * 2, /* r6 */ + 4 * 8, /* r7 */ + 4 * 9, /* r8 */ + 4 * 10, /* r9 */ + 4 * 11, /* r10 */ + 4 * 12, /* r11 */ + 4 * 13, /* r12 */ + 4 * 24, /* fp */ + 4 * 25, /* lr */ + 4 * 23, /* sp */ + 4 * 19, /* psw */ + 4 * 19, /* cbr */ + 4 * 26, /* spi */ + 4 * 23, /* spu */ + 4 * 22, /* bpc */ + 4 * 20, /* pc */ + 4 * 16, /* accl */ + 4 * 15 /* acch */ +}; + +#define PSW_OFFSET (4 * 19) +#define BBPSW_OFFSET (4 * 21) +#define SPU_OFFSET (4 * 23) +#define SPI_OFFSET (4 * 26) + +static void +m32r_linux_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t size) +{ + const char *regs = gregs; + unsigned long psw, bbpsw; + int i; + + psw = *((unsigned long *) (regs + PSW_OFFSET)); + bbpsw = *((unsigned long *) (regs + BBPSW_OFFSET)); + + for (i = 0; i < sizeof (m32r_pt_regs_offset) / 4; i++) + { + if (regnum != -1 && regnum != i) + continue; + + switch (i) + { + case PSW_REGNUM: + *((unsigned long *) (regs + m32r_pt_regs_offset[i])) = + ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8); + break; + case CBR_REGNUM: + *((unsigned long *) (regs + m32r_pt_regs_offset[i])) = + ((psw >> 8) & 1); + break; + case M32R_SP_REGNUM: + if (psw & 0x8000) + *((unsigned long *) (regs + m32r_pt_regs_offset[i])) = + *((unsigned long *) (regs + SPU_OFFSET)); + else + *((unsigned long *) (regs + m32r_pt_regs_offset[i])) = + *((unsigned long *) (regs + SPI_OFFSET)); + break; + } + + regcache_raw_supply (current_regcache, i, + regs + m32r_pt_regs_offset[i]); + } +} + +static struct regset m32r_linux_gregset = { + NULL, m32r_linux_supply_gregset +}; + +static const struct regset * +m32r_linux_regset_from_core_section (struct gdbarch *core_arch, + const char *sect_name, size_t sect_size) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (core_arch); + if (strcmp (sect_name, ".reg") == 0) + return &m32r_linux_gregset; + return NULL; +} + static void m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -323,6 +415,10 @@ m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* GNU/Linux uses SVR4-style shared libraries. */ set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + /* Core file support. */ + set_gdbarch_regset_from_core_section + (gdbarch, m32r_linux_regset_from_core_section); } /* Provide a prototype to silence -Wmissing-prototypes. */ |