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.
This commit is contained in:
Elena Zannoni 2002-03-28 00:48:41 +00:00
parent 96b0714f37
commit 6be8bc0c92
2 changed files with 128 additions and 20 deletions

View File

@ -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

View File

@ -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;
@ -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