diff options
Diffstat (limited to 'gdb/rs6000-tdep.c')
-rw-r--r-- | gdb/rs6000-tdep.c | 132 |
1 files changed, 128 insertions, 4 deletions
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 82dfbd3..864ac64 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1624,7 +1624,10 @@ rs6000_register_virtual_type (int n) switch (size) { case 8: - return builtin_type_int64; + if (tdep->ppc_ev0_regnum <= n && n <= tdep->ppc_ev31_regnum) + return builtin_type_vec64; + else + return builtin_type_int64; break; case 16: return builtin_type_vec128; @@ -1692,6 +1695,68 @@ rs6000_register_convert_to_raw (struct type *type, int n, memcpy (to, from, REGISTER_RAW_SIZE (n)); } +static void +e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int reg_nr, void *buffer) +{ + int base_regnum; + int offset = 0; + char *temp_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (reg_nr >= tdep->ppc_gp0_regnum + && reg_nr <= tdep->ppc_gplast_regnum) + { + base_regnum = reg_nr - tdep->ppc_gp0_regnum + tdep->ppc_ev0_regnum; + + /* Build the value in the provided buffer. */ + /* Read the raw register of which this one is the lower portion. */ + regcache_raw_read (regcache, base_regnum, temp_buffer); + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + offset = 4; + memcpy ((char *) buffer, temp_buffer + offset, 4); + } +} + +static void +e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int reg_nr, const void *buffer) +{ + int base_regnum; + int offset = 0; + char *temp_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (reg_nr >= tdep->ppc_gp0_regnum + && reg_nr <= tdep->ppc_gplast_regnum) + { + base_regnum = reg_nr - tdep->ppc_gp0_regnum + tdep->ppc_ev0_regnum; + /* reg_nr is 32 bit here, and base_regnum is 64 bits. */ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + offset = 4; + + /* Let's read the value of the base register into a temporary + buffer, so that overwriting the last four bytes with the new + value of the pseudo will leave the upper 4 bytes unchanged. */ + regcache_raw_read (regcache, base_regnum, temp_buffer); + + /* Write as an 8 byte quantity. */ + memcpy (temp_buffer + offset, (char *) buffer, 4); + regcache_raw_write (regcache, base_regnum, temp_buffer); + } +} + +/* Convert a dwarf2 register number to a gdb REGNUM. */ +static int +e500_dwarf2_reg_to_regnum (int num) +{ + int regnum; + if (0 <= num && num <= 31) + return num + gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum; + else + return num; +} + /* Convert a dbx stab register number (from `r' declaration) to a gdb REGNUM. */ static int @@ -1930,6 +1995,10 @@ rs6000_convert_from_func_ptr_addr (CORE_ADDR addr) #define PPC_UISA_SPRS \ /* 66 */ R4(cr), R(lr), R(ctr), R4(xer), R4(fpscr) +/* UISA-level SPRs for PowerPC without floating point support. */ +#define PPC_UISA_NOFP_SPRS \ + /* 66 */ R4(cr), R(lr), R(ctr), R4(xer), R0 + /* Segment registers, for PowerPC. */ #define PPC_SEGMENT_REGS \ /* 71 */ R32(sr0), R32(sr1), R32(sr2), R32(sr3), \ @@ -1957,6 +2026,20 @@ rs6000_convert_from_func_ptr_addr (CORE_ADDR addr) /*143*/R16(vr24),R16(vr25),R16(vr26),R16(vr27),R16(vr28),R16(vr29),R16(vr30),R16(vr31), \ /*151*/R4(vscr), R4(vrsave) +/* Vectors of hi-lo general purpose registers. */ +#define PPC_EV_REGS \ + /* 0*/R8(ev0), R8(ev1), R8(ev2), R8(ev3), R8(ev4), R8(ev5), R8(ev6), R8(ev7), \ + /* 8*/R8(ev8), R8(ev9), R8(ev10),R8(ev11),R8(ev12),R8(ev13),R8(ev14),R8(ev15), \ + /*16*/R8(ev16),R8(ev17),R8(ev18),R8(ev19),R8(ev20),R8(ev21),R8(ev22),R8(ev23), \ + /*24*/R8(ev24),R8(ev25),R8(ev26),R8(ev27),R8(ev28),R8(ev29),R8(ev30),R8(ev31) + +/* Lower half of the EV registers. */ +#define PPC_GPRS_PSEUDO_REGS \ + /* 0 */ P(r0), P(r1), P(r2), P(r3), P(r4), P(r5), P(r6), P(r7), \ + /* 8 */ P(r8), P(r9), P(r10),P(r11),P(r12),P(r13),P(r14),P(r15), \ + /* 16 */ P(r16),P(r17),P(r18),P(r19),P(r20),P(r21),P(r22),P(r23), \ + /* 24 */ P(r24),P(r25),P(r26),P(r27),P(r28),P(r29),P(r30),P(r31), \ + /* IBM POWER (pre-PowerPC) architecture, user-level view. We only cover user-level SPR's. */ static const struct reg registers_power[] = @@ -2126,6 +2209,18 @@ static const struct reg registers_7400[] = /* FIXME? Add more registers? */ }; +/* Motorola e500. */ +static const struct reg registers_e500[] = +{ + R(pc), R(ps), + /* cr, lr, ctr, xer, "" */ + PPC_UISA_NOFP_SPRS, + /* 7...38 */ + PPC_EV_REGS, + /* 39...70 */ + PPC_GPRS_PSEUDO_REGS +}; + /* Information about a particular processor variant. */ struct variant @@ -2233,6 +2328,9 @@ static struct variant variants[] = {"7400", "Motorola/IBM PowerPC 7400 (G4)", bfd_arch_powerpc, bfd_mach_ppc_7400, -1, -1, tot_num_registers (registers_7400), registers_7400}, + {"e500", "Motorola PowerPC e500", bfd_arch_powerpc, + bfd_mach_ppc_e500, -1, -1, tot_num_registers (registers_e500), + registers_e500}, /* 64-bit */ {"powerpc64", "PowerPC 64-bit user-level", bfd_arch_powerpc, @@ -2430,20 +2528,48 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->ppc_mq_regnum = -1; tdep->ppc_fpscr_regnum = power ? 71 : 70; + set_gdbarch_pc_regnum (gdbarch, 64); + set_gdbarch_sp_regnum (gdbarch, 1); + set_gdbarch_fp_regnum (gdbarch, 1); + if (v->arch == bfd_arch_powerpc) switch (v->mach) { case bfd_mach_ppc: tdep->ppc_vr0_regnum = 71; tdep->ppc_vrsave_regnum = 104; + tdep->ppc_ev0_regnum = -1; + tdep->ppc_ev31_regnum = -1; break; case bfd_mach_ppc_7400: tdep->ppc_vr0_regnum = 119; tdep->ppc_vrsave_regnum = 153; + tdep->ppc_ev0_regnum = -1; + tdep->ppc_ev31_regnum = -1; + break; + case bfd_mach_ppc_e500: + tdep->ppc_gp0_regnum = 39; + tdep->ppc_gplast_regnum = 70; + tdep->ppc_toc_regnum = -1; + tdep->ppc_ps_regnum = 1; + tdep->ppc_cr_regnum = 2; + tdep->ppc_lr_regnum = 3; + tdep->ppc_ctr_regnum = 4; + tdep->ppc_xer_regnum = 5; + tdep->ppc_ev0_regnum = 7; + tdep->ppc_ev31_regnum = 38; + set_gdbarch_pc_regnum (gdbarch, 0); + set_gdbarch_sp_regnum (gdbarch, 40); + set_gdbarch_fp_regnum (gdbarch, 40); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum); + set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write); break; default: tdep->ppc_vr0_regnum = -1; tdep->ppc_vrsave_regnum = -1; + tdep->ppc_ev0_regnum = -1; + tdep->ppc_ev31_regnum = -1; break; } @@ -2476,9 +2602,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_write_sp (gdbarch, generic_target_write_sp); set_gdbarch_num_regs (gdbarch, v->nregs); - set_gdbarch_sp_regnum (gdbarch, 1); - set_gdbarch_fp_regnum (gdbarch, 1); - set_gdbarch_pc_regnum (gdbarch, 64); + set_gdbarch_num_pseudo_regs (gdbarch, v->npregs); set_gdbarch_register_name (gdbarch, rs6000_register_name); set_gdbarch_register_size (gdbarch, wordsize); set_gdbarch_register_bytes (gdbarch, off); |