Restore the ABI of 'struct fpreg' on powerpc.

The PT_{GET,SET}FPREGS requests use 'struct fpreg' and the NT_FPREGSET
core note stores a copy of 'struct fpreg'.  As with x86 and the floating
point state there compared to the extended state in XSAVE, struct fpreg
on powerpc now only holds the 'base' FP state, and setting it via
PT_SETFPREGS leaves the extended vector state in a thread unchanged.

Reviewed by:	jhibbits
Differential Revision:	https://reviews.freebsd.org/D5004
This commit is contained in:
John Baldwin 2016-02-01 23:12:04 +00:00
parent d713568142
commit 93312a9143
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=295132
5 changed files with 19 additions and 13 deletions

View file

@ -183,7 +183,7 @@ fpu_dumpfpn(struct fpn *fp)
* (Typically: zero, SIGFPE, SIGILL, SIGSEGV)
*/
int
fpu_emulate(struct trapframe *frame, struct fpreg *fpf)
fpu_emulate(struct trapframe *frame, struct fpu *fpf)
{
static union instr insn;
static struct fpemu fe;

View file

@ -138,7 +138,7 @@ struct fpn {
* Emulator state.
*/
struct fpemu {
struct fpreg *fe_fpstate; /* registers, etc */
struct fpu *fe_fpstate; /* registers, etc */
int fe_fpscr; /* fpscr copy (modified during op) */
int fe_cx; /* keep track of exceptions */
struct fpn fe_f1; /* operand 1 */

View file

@ -31,14 +31,14 @@
*/
struct proc;
struct fpreg;
struct fpu;
struct trapframe;
union instr;
struct fpemu;
struct fpn;
/* fpu.c */
int fpu_emulate(struct trapframe *, struct fpreg *);
int fpu_emulate(struct trapframe *, struct fpu *);
int fpu_execute(struct trapframe *, struct fpemu *, union instr *);
/* fpu_explode.c */

View file

@ -18,12 +18,8 @@ struct reg {
register_t pc;
};
/* Must match pcb.pcb_fpu */
struct fpreg {
union {
double fpr;
uint64_t vsr[2];
} fpreg[32];
double fpreg[32];
double fpscr;
};

View file

@ -608,13 +608,18 @@ int
fill_fpregs(struct thread *td, struct fpreg *fpregs)
{
struct pcb *pcb;
int i;
pcb = td->td_pcb;
if ((pcb->pcb_flags & PCB_FPREGS) == 0)
memset(fpregs, 0, sizeof(struct fpreg));
else
memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
else {
memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
for (i = 0; i < 32; i++)
memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
sizeof(double));
}
return (0);
}
@ -641,10 +646,15 @@ int
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
struct pcb *pcb;
int i;
pcb = td->td_pcb;
pcb->pcb_flags |= PCB_FPREGS;
memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double));
for (i = 0; i < 32; i++) {
memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i],
sizeof(double));
}
return (0);
}
@ -1060,7 +1070,7 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
pcb->pcb_flags |= PCB_FPREGS;
}
sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu);
sig = fpu_emulate(frame, &pcb->pcb_fpu);
#endif
return (sig);