diff --git a/gdb/ChangeLog b/gdb/ChangeLog index af8bb5e071..40fdcc7d6b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2002-03-27 Elena Zannoni + + * 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 * 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 9e4d668ca4..e21fdad512 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