aboutsummaryrefslogtreecommitdiff
path: root/gdb/rs6000-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/rs6000-tdep.c')
-rw-r--r--gdb/rs6000-tdep.c134
1 files changed, 111 insertions, 23 deletions
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 0b239bd..cd59cd4 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -529,13 +529,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
if ((op & 0xfc1fffff) == 0x7c0802a6)
{ /* mflr Rx */
- lr_reg = (op & 0x03e00000) | 0x90010000;
+ lr_reg = (op & 0x03e00000);
continue;
}
else if ((op & 0xfc1fffff) == 0x7c000026)
{ /* mfcr Rx */
- cr_reg = (op & 0x03e00000) | 0x90010000;
+ cr_reg = (op & 0x03e00000);
continue;
}
@@ -561,7 +561,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
{
fdata->saved_gpr = reg;
if ((op & 0xfc1f0003) == 0xf8010000)
- op = (op >> 1) << 1;
+ op &= ~3UL;
fdata->gpr_offset = SIGNED_SHORT (op) + offset;
}
continue;
@@ -593,19 +593,49 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
continue;
}
- else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg)
- { /* st Rx,NUM(r1)
- where Rx == lr */
- fdata->lr_offset = SIGNED_SHORT (op) + offset;
+ else if (lr_reg != -1 &&
+ /* std Rx || stdu Rx */
+ (((op & 0xffff0000) == (lr_reg | 0xf8010000)) ||
+ /* stw Rx */
+ ((op & 0xffff0000) == (lr_reg | 0x90010000)) ||
+ /* stwu Rx */
+ ((op & 0xffff0000) == (lr_reg | 0x94010000))))
+ { /* where Rx == lr */
+ fdata->lr_offset = offset;
fdata->nosavedpc = 0;
lr_reg = 0;
+ if ((op & 0xfc000003) == 0xf8000000 || /* std Rx */
+ (op & 0xfc000000) == 0x90000000) /* stw Rx */
+ {
+ /* does not update r1 add d to lr_offset */
+ fdata->lr_offset = SIGNED_SHORT (op);
+ }
+ continue;
+
+ }
+ else if (cr_reg != -1 &&
+ /* std Rx || stdu Rx */
+ (((op & 0xffff0000) == (cr_reg | 0xf8010000)) ||
+ /* stw Rx */
+ ((op & 0xffff0000) == (cr_reg | 0x90010000)) ||
+ /* stwu Rx */
+ ((op & 0xffff0000) == (cr_reg | 0x94010000))))
+ { /* where Rx == cr */
+ fdata->cr_offset = offset;
+ cr_reg = 0;
+ if ((op & 0xfc000003) == 0xf8000000 ||
+ (op & 0xfc000000) == 0x90000000)
+ {
+ /* does not update r1 add d to cr_offset */
+ fdata->cr_offset += SIGNED_SHORT (op);
+ }
continue;
}
- else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg)
- { /* st Rx,NUM(r1)
+ else if (cr_reg != -1 && (op & 0xffff0003) == cr_reg)
+ { /* std Rx,NUM(r1) || stdu Rx,NUM(r1)
where Rx == cr */
- fdata->cr_offset = SIGNED_SHORT (op) + offset;
+ fdata->cr_offset = SIGNED_SHORT (op & ~3UL) + offset;
cr_reg = 0;
continue;
@@ -650,30 +680,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
this branch */
continue;
- /* update stack pointer */
}
- else if ((op & 0xffff0000) == 0x94210000 || /* stu r1,NUM(r1) */
- (op & 0xffff0003) == 0xf8210001) /* stdu r1,NUM(r1) */
- {
+ /* update stack pointer */
+ else if ((op & 0xfc1f0000) == 0x94010000)
+ { /* stu rX,NUM(r1) || stwu rX,NUM(r1) */
fdata->frameless = 0;
- if ((op & 0xffff0003) == 0xf8210001)
- op = (op >> 1) << 1;
fdata->offset = SIGNED_SHORT (op);
offset = fdata->offset;
continue;
-
}
- else if (op == 0x7c21016e)
- { /* stwux 1,1,0 */
+ else if ((op & 0xfc1f016a) == 0x7c01016e)
+ { /* stwux rX,r1,rY */
+ /* no way to figure out what r1 is going to be */
+ fdata->frameless = 0;
+ offset = fdata->offset;
+ continue;
+ }
+ else if ((op & 0xfc1f0003) == 0xf8010001)
+ { /* stdu rX,NUM(r1) */
+ fdata->frameless = 0;
+ fdata->offset = SIGNED_SHORT (op & ~3UL);
+ offset = fdata->offset;
+ continue;
+ }
+ else if ((op & 0xfc1f016a) == 0x7c01016a)
+ { /* stdux rX,r1,rY */
+ /* no way to figure out what r1 is going to be */
fdata->frameless = 0;
offset = fdata->offset;
continue;
-
- /* Load up minimal toc pointer */
}
- else if ((op >> 22) == 0x20f
+ /* Load up minimal toc pointer */
+ else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */
+ (op >> 22) == 0x3af) /* ld r31,... or ld r30,... */
&& !minimal_toc_loaded)
- { /* l r31,... or l r30,... */
+ {
minimal_toc_loaded = 1;
continue;
@@ -2456,6 +2497,44 @@ static const struct reg registers_7400[] =
/* FIXME? Add more registers? */
};
+
+/* PowerPC UISA - a PPC64 processor as viewed by user-level code. */
+/* Should be able to use the common registers_powerpc[] here, however
+ it does not define an fpscr, though both linux and aix get one from
+ ptrace(). Can only assume that there is a 32-bit core our there
+ that does not have an fpscr. I think we can assert that all 64-bit
+ cores do. */
+static const struct reg registers_powerpc64[] =
+{
+ COMMON_UISA_REGS,
+ /* SPRs */
+ /* 66 */ R4(cr), R(lr), R(ctr), R4(xer),
+ /* 70 */ R4(fpscr), R0 /* mq? */
+};
+
+static const struct reg registers_a35[] =
+{
+ COMMON_UISA_REGS,
+ /* SPRs */
+ /* 66 */ R4(cr), R(lr), R(ctr), R4(xer),
+ /* 70 */ R4(fpscr), R0 /* mq? */,
+ /* 72 */ R(dabr), R(iabr), R4(dsisr),
+ /* 75 */ R(dar), R4(dec), R(sdr1), R(srr0), R(srr1),
+ /* 80 */ R(sprg0), R(sprg1), R(sprg2), R(sprg3),
+ /* 84 */ R64(asr), R4(ear), R4(tbl), R4(tbu),
+ /* 88 */ R(ibat0u), R(ibat0l), R(ibat1u), R(ibat1l),
+ /* 92 */ R(ibat2u), R(ibat2l), R(ibat3u), R(ibat3l),
+ /* 96 */ R(dbat0u), R(dbat0l), R(dbat1u), R(dbat1l),
+ /* 100 */ R(dbat2u), R(dbat2l), R(dbat3u), R(dbat3l),
+ /* 104 */ R(pir), R4(mmcr0),
+ /* 106..121 segment regs 0..15 */
+ /* 106 */ R(sr0), R(sr1), R(sr2), R(sr3),
+ /* 110 */ R(sr4), R(sr5), R(sr6), R(sr7),
+ /* 114 */ R(sr8), R(sr9), R(sr10), R(sr11),
+ /* 118 */ R(sr12), R(sr13), R(sr14), R(sr15),
+ /* 122 */ R4(pvr) /* processor version register */
+};
+
/* Motorola e500. */
static const struct reg registers_e500[] =
{
@@ -2956,6 +3035,15 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
descriptors). */
set_gdbarch_convert_from_func_ptr_addr (gdbarch,
rs6000_convert_from_func_ptr_addr);
+
+ /* wordsize 8, ppc64 linux functions */
+ if (osabi == ELFOSABI_LINUX)
+ {
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, ppc64_linux_svr4_fetch_link_map_offsets);
+ set_gdbarch_convert_from_func_ptr_addr
+ (gdbarch, ppc64_linux_convert_from_func_ptr_addr);
+ }
}
set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address);
set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address);