aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog8
-rw-r--r--gdb/rs6000-tdep.c140
2 files changed, 128 insertions, 20 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index af8bb5e..40fdcc7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2002-03-27 Elena Zannoni <ezannoni@redhat.com>
+
+ * rs6000-tdep.c (struct rs6000_framedata): Add fields for AltiVec
+ vector registers handling.
+ (skip_prologue): Handle new AltiVec instructions. Fill in new
+ fields of frame data.
+ (frame_get_saved_regs): Fill in information for AltiVec registers.
+
2002-03-27 Jim Blandy <jimb@redhat.com>
* symtab.h (SYMBOL_INIT_MANGLED_NAME): Turn this macro's body into
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 9e4d668..e21fdad 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -64,13 +64,16 @@ struct rs6000_framedata
the frame */
int saved_gpr; /* smallest # of saved gpr */
int saved_fpr; /* smallest # of saved fpr */
+ int saved_vr; /* smallest # of saved vr */
int alloca_reg; /* alloca register number (frame ptr) */
char frameless; /* true if frameless functions. */
char nosavedpc; /* true if pc not saved. */
int gpr_offset; /* offset of saved gprs from prev sp */
int fpr_offset; /* offset of saved fprs from prev sp */
+ int vr_offset; /* offset of saved vrs from prev sp */
int lr_offset; /* offset of saved lr */
int cr_offset; /* offset of saved cr */
+ int vrsave_offset; /* offset of saved vrsave register */
};
/* Description of a single register. */
@@ -362,12 +365,15 @@ rs6000_software_single_step (enum target_signal signal,
which we decrement the sp to allocate the frame.
- saved_gpr is the number of the first saved gpr.
- saved_fpr is the number of the first saved fpr.
+ - saved_vr is the number of the first saved vr.
- alloca_reg is the number of the register used for alloca() handling.
Otherwise -1.
- gpr_offset is the offset of the first saved gpr from the previous frame.
- fpr_offset is the offset of the first saved fpr from the previous frame.
+ - vr_offset is the offset of the first saved vr from the previous frame.
- lr_offset is the offset of the saved lr
- cr_offset is the offset of the saved cr
+ - vrsave_offset is the offset of the saved vrsave register
*/
#define SIGNED_SHORT(x) \
@@ -434,11 +440,15 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
{
CORE_ADDR orig_pc = pc;
CORE_ADDR last_prologue_pc = pc;
+ CORE_ADDR li_found_pc = 0;
char buf[4];
unsigned long op;
long offset = 0;
+ long vr_saved_offset = 0;
int lr_reg = -1;
int cr_reg = -1;
+ int vr_reg = -1;
+ int vrsave_reg = -1;
int reg;
int framep = 0;
int minimal_toc_loaded = 0;
@@ -463,6 +473,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
memset (fdata, 0, sizeof (struct rs6000_framedata));
fdata->saved_gpr = -1;
fdata->saved_fpr = -1;
+ fdata->saved_vr = -1;
fdata->alloca_reg = -1;
fdata->frameless = 1;
fdata->nosavedpc = 1;
@@ -581,8 +592,8 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
break;
}
- else if (((op & 0xffff0000) == 0x801e0000 || /* lwz 0,NUM(r30), used
- in V.4 -mrelocatable */
+ else if (((op & 0xffff0000) == 0x801e0000 || /* lwz 0,NUM(r30), used
+ in V.4 -mrelocatable */
op == 0x7fc0f214) && /* add r30,r0,r30, used
in V.4 -mrelocatable */
lr_reg == 0x901e0000)
@@ -590,8 +601,8 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
continue;
}
- else if ((op & 0xffff0000) == 0x3fc00000 || /* addis 30,0,foo@ha, used
- in V.4 -mminimal-toc */
+ else if ((op & 0xffff0000) == 0x3fc00000 || /* addis 30,0,foo@ha, used
+ in V.4 -mminimal-toc */
(op & 0xffff0000) == 0x3bde0000)
{ /* addi 30,30,foo@l */
continue;
@@ -602,17 +613,17 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
to save fprs??? */
fdata->frameless = 0;
- /* Don't skip over the subroutine call if it is not within the first
- three instructions of the prologue. */
+ /* Don't skip over the subroutine call if it is not within
+ the first three instructions of the prologue. */
if ((pc - orig_pc) > 8)
break;
op = read_memory_integer (pc + 4, 4);
- /* At this point, make sure this is not a trampoline function
- (a function that simply calls another functions, and nothing else).
- If the next is not a nop, this branch was part of the function
- prologue. */
+ /* At this point, make sure this is not a trampoline
+ function (a function that simply calls another functions,
+ and nothing else). If the next is not a nop, this branch
+ was part of the function prologue. */
if (op == 0x4def7b82 || op == 0) /* crorc 15, 15, 15 */
break; /* don't skip over
@@ -658,8 +669,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
/* store parameters in stack */
}
- else if ((op & 0xfc1f0000) == 0x90010000 || /* st rx,NUM(r1) */
- (op & 0xfc1f0003) == 0xf8010000 || /* std rx,NUM(r1) */
+ else if ((op & 0xfc1f0003) == 0xf8010000 || /* std rx,NUM(r1) */
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0xfc010000) /* frsp, fp?,NUM(r1) */
{
@@ -692,8 +702,74 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
framep = 1;
fdata->alloca_reg = (op & ~0x38010000) >> 21;
continue;
-
}
+ /* AltiVec related instructions. */
+ /* Store the vrsave register (spr 256) in another register for
+ later manipulation, or load a register into the vrsave
+ register. 2 instructions are used: mfvrsave and
+ mtvrsave. They are shorthand notation for mfspr Rn, SPR256
+ and mtspr SPR256, Rn. */
+ /* mfspr Rn SPR256 == 011111 nnnnn 0000001000 01010100110
+ mtspr SPR256 Rn == 011111 nnnnn 0000001000 01110100110 */
+ else if ((op & 0xfc1fffff) == 0x7c0042a6) /* mfvrsave Rn */
+ {
+ vrsave_reg = GET_SRC_REG (op);
+ continue;
+ }
+ else if ((op & 0xfc1fffff) == 0x7c0043a6) /* mtvrsave Rn */
+ {
+ continue;
+ }
+ /* Store the register where vrsave was saved to onto the stack:
+ rS is the register where vrsave was stored in a previous
+ instruction. */
+ /* 100100 sssss 00001 dddddddd dddddddd */
+ else if ((op & 0xfc1f0000) == 0x90010000) /* stw rS, d(r1) */
+ {
+ if (vrsave_reg == GET_SRC_REG (op))
+ {
+ fdata->vrsave_offset = SIGNED_SHORT (op) + offset;
+ vrsave_reg = -1;
+ }
+ continue;
+ }
+ /* Compute the new value of vrsave, by modifying the register
+ where vrsave was saved to. */
+ else if (((op & 0xfc000000) == 0x64000000) /* oris Ra, Rs, UIMM */
+ || ((op & 0xfc000000) == 0x60000000))/* ori Ra, Rs, UIMM */
+ {
+ continue;
+ }
+ /* li r0, SIMM (short for addi r0, 0, SIMM). This is the first
+ in a pair of insns to save the vector registers on the
+ stack. */
+ /* 001110 00000 00000 iiii iiii iiii iiii */
+ else if ((op & 0xffff0000) == 0x38000000) /* li r0, SIMM */
+ {
+ li_found_pc = pc;
+ vr_saved_offset = SIGNED_SHORT (op);
+ }
+ /* Store vector register S at (r31+r0) aligned to 16 bytes. */
+ /* 011111 sssss 11111 00000 00111001110 */
+ else if ((op & 0xfc1fffff) == 0x7c1f01ce) /* stvx Vs, R31, R0 */
+ {
+ if (pc == (li_found_pc + 4))
+ {
+ vr_reg = GET_SRC_REG (op);
+ /* If this is the first vector reg to be saved, or if
+ it has a lower number than others previously seen,
+ reupdate the frame info. */
+ if (fdata->saved_vr == -1 || fdata->saved_vr > vr_reg)
+ {
+ fdata->saved_vr = vr_reg;
+ fdata->vr_offset = vr_saved_offset + offset;
+ }
+ vr_saved_offset = -1;
+ vr_reg = -1;
+ li_found_pc = 0;
+ }
+ }
+ /* End AltiVec related instructions. */
else
{
/* Not a recognized prologue instruction.
@@ -1304,7 +1380,8 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
{
CORE_ADDR frame_addr;
struct rs6000_framedata work_fdata;
- int wordsize = TDEP->wordsize;
+ struct gdbarch_tdep * tdep = gdbarch_tdep (current_gdbarch);
+ int wordsize = tdep->wordsize;
if (fi->saved_regs)
return;
@@ -1322,8 +1399,12 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
/* The following is true only if the frame doesn't have a call to
alloca(), FIXME. */
- if (fdatap->saved_fpr == 0 && fdatap->saved_gpr == 0
- && fdatap->lr_offset == 0 && fdatap->cr_offset == 0)
+ if (fdatap->saved_fpr == 0
+ && fdatap->saved_gpr == 0
+ && fdatap->saved_vr == 0
+ && fdatap->lr_offset == 0
+ && fdatap->cr_offset == 0
+ && fdatap->vr_offset == 0)
frame_addr = 0;
else if (fi->prev && fi->prev->frame)
frame_addr = fi->prev->frame;
@@ -1358,17 +1439,36 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
}
}
+ /* if != -1, fdatap->saved_vr is the smallest number of saved_vr.
+ All vr's from saved_vr to vr31 are saved. */
+ if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
+ {
+ if (fdatap->saved_vr >= 0)
+ {
+ int i;
+ CORE_ADDR vr_addr = frame_addr + fdatap->vr_offset;
+ for (i = fdatap->saved_vr; i < 32; i++)
+ {
+ fi->saved_regs[tdep->ppc_vr0_regnum + i] = vr_addr;
+ vr_addr += REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum);
+ }
+ }
+ }
+
/* If != 0, fdatap->cr_offset is the offset from the frame that holds
the CR. */
if (fdatap->cr_offset != 0)
- fi->saved_regs[gdbarch_tdep (current_gdbarch)->ppc_cr_regnum] =
- frame_addr + fdatap->cr_offset;
+ fi->saved_regs[tdep->ppc_cr_regnum] = frame_addr + fdatap->cr_offset;
/* If != 0, fdatap->lr_offset is the offset from the frame that holds
the LR. */
if (fdatap->lr_offset != 0)
- fi->saved_regs[gdbarch_tdep (current_gdbarch)->ppc_lr_regnum] =
- frame_addr + fdatap->lr_offset;
+ fi->saved_regs[tdep->ppc_lr_regnum] = frame_addr + fdatap->lr_offset;
+
+ /* If != 0, fdatap->vrsave_offset is the offset from the frame that holds
+ the VRSAVE. */
+ if (fdatap->vrsave_offset != 0)
+ fi->saved_regs[tdep->ppc_vrsave_regnum] = frame_addr + fdatap->vrsave_offset;
}
/* Return the address of a frame. This is the inital %sp value when the frame