summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/fpu/fpu_emu.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2015-02-22 21:40:27 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2015-02-22 21:40:27 +0000
commit99449144eaa7a166d2b773f5b69a60baf1d9e31c (patch)
treeb937ece7929c309e55f30ba338c3a6e3491c2593 /sys/powerpc/fpu/fpu_emu.c
parentd2889adcc557fdb9d7b6db385ac12ceeafedd6c9 (diff)
downloadFreeBSD-src-99449144eaa7a166d2b773f5b69a60baf1d9e31c.zip
FreeBSD-src-99449144eaa7a166d2b773f5b69a60baf1d9e31c.tar.gz
Kernel support for the Vector-Scalar eXtension (VSX) found on the POWER7
and POWER8. This instruction set unifies the 32 64-bit scalar floating point registers with the 32 128-bit vector registers into a single bank of 64 128-bit registers. Kernel support mostly amounts to saving and restoring the wider version of the floating point registers and making sure that both scalar FP and vector registers are enabled once a VSX instruction is executed. get_mcontext() and friends currently cannot see the high bits, which will require a little more work. As the system compiler (GCC 4.2) does not support VSX, making use of this from userland requires either newer GCC or clang. Relnotes: yes Sponsored by: FreeBSD Foundation
Diffstat (limited to 'sys/powerpc/fpu/fpu_emu.c')
-rw-r--r--sys/powerpc/fpu/fpu_emu.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c
index 610c0ea..82074aa 100644
--- a/sys/powerpc/fpu/fpu_emu.c
+++ b/sys/powerpc/fpu/fpu_emu.c
@@ -335,7 +335,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
if (ra != 0)
addr += tf->fixreg[ra];
rt = instr.i_x.i_rt;
- a = (int *)&fs->fpreg[rt];
+ a = (int *)&fs->fpreg[rt].fpr;
DPRINTF(FPE_INSN,
("fpu_execute: Store INT %x at %p\n",
a[1], (void *)addr));
@@ -402,7 +402,8 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
DPRINTF(FPE_INSN,
("fpu_execute: Store DBL at %p\n",
(void *)addr));
- if (copyout(&fs->fpreg[rt], (void *)addr, size))
+ if (copyout(&fs->fpreg[rt].fpr, (void *)addr,
+ size))
return (FAULT);
}
} else {
@@ -410,12 +411,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
FPU_EMU_EVCNT_INCR(fpload);
DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n",
(void *)addr));
- if (copyin((const void *)addr, &fs->fpreg[rt], size))
+ if (copyin((const void *)addr, &fs->fpreg[rt].fpr,
+ size))
return (FAULT);
if (type != FTYPE_DBL) {
fpu_explode(fe, fp = &fe->fe_f1, type, rt);
fpu_implode(fe, fp, FTYPE_DBL,
- (u_int *)&fs->fpreg[rt]);
+ (u_int *)&fs->fpreg[rt].fpr);
}
}
if (update)
@@ -468,7 +470,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
DPRINTF(FPE_INSN, ("fpu_execute: FRSP\n"));
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rb);
fpu_implode(fe, fp, FTYPE_SNG,
- (u_int *)&fs->fpreg[rt]);
+ (u_int *)&fs->fpreg[rt].fpr);
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
type = FTYPE_DBL;
break;
@@ -501,9 +503,9 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63_FNEG:
FPU_EMU_EVCNT_INCR(fnegabs);
DPRINTF(FPE_INSN, ("fpu_execute: FNEGABS\n"));
- memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+ memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
sizeof(double));
- a = (int *)&fs->fpreg[rt];
+ a = (int *)&fs->fpreg[rt].fpr;
*a ^= (1U << 31);
break;
case OPC63_MCRFS:
@@ -531,7 +533,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63_FMR:
FPU_EMU_EVCNT_INCR(fmr);
DPRINTF(FPE_INSN, ("fpu_execute: FMR\n"));
- memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+ memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
sizeof(double));
break;
case OPC63_MTFSFI:
@@ -548,23 +550,23 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63_FNABS:
FPU_EMU_EVCNT_INCR(fnabs);
DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
- memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+ memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
sizeof(double));
- a = (int *)&fs->fpreg[rt];
+ a = (int *)&fs->fpreg[rt].fpr;
*a |= (1U << 31);
break;
case OPC63_FABS:
FPU_EMU_EVCNT_INCR(fabs);
DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
- memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+ memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
sizeof(double));
- a = (int *)&fs->fpreg[rt];
+ a = (int *)&fs->fpreg[rt].fpr;
*a &= ~(1U << 31);
break;
case OPC63_MFFS:
FPU_EMU_EVCNT_INCR(mffs);
DPRINTF(FPE_INSN, ("fpu_execute: MFFS\n"));
- memcpy(&fs->fpreg[rt], &fs->fpscr,
+ memcpy(&fs->fpreg[rt].fpr, &fs->fpscr,
sizeof(fs->fpscr));
break;
case OPC63_MTFSF:
@@ -579,7 +581,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
if (rt & (1<<ra))
mask |= (0xf<<(4*ra));
}
- a = (int *)&fs->fpreg[rt];
+ a = (int *)&fs->fpreg[rt].fpr;
fe->fe_cx = mask & a[1];
fe->fe_fpscr = (fe->fe_fpscr&~mask) |
(fe->fe_cx);
@@ -646,12 +648,12 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63M_FSEL:
FPU_EMU_EVCNT_INCR(fsel);
DPRINTF(FPE_INSN, ("fpu_execute: FSEL\n"));
- a = (int *)&fe->fe_fpstate->fpreg[ra];
+ a = (int *)&fe->fe_fpstate->fpreg[ra].fpr;
if ((*a & 0x80000000) && (*a & 0x7fffffff))
/* fra < 0 */
rc = rb;
DPRINTF(FPE_INSN, ("f%d => f%d\n", rc, rt));
- memcpy(&fs->fpreg[rt], &fs->fpreg[rc],
+ memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rc].fpr,
sizeof(double));
break;
case OPC59_FRES:
@@ -660,7 +662,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fpu_explode(fe, &fe->fe_f1, type, rb);
fp = fpu_sqrt(fe);
/* now we've gotta overwrite the dest reg */
- *((int *)&fe->fe_fpstate->fpreg[rt]) = 1;
+ *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1;
fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt);
fpu_div(fe);
break;
@@ -679,7 +681,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fp = fpu_sqrt(fe);
fe->fe_f2 = *fp;
/* now we've gotta overwrite the dest reg */
- *((int *)&fe->fe_fpstate->fpreg[rt]) = 1;
+ *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1;
fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt);
fpu_div(fe);
break;
@@ -735,7 +737,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* If the instruction was single precision, round */
if (!(instr.i_any.i_opcd & 0x4)) {
fpu_implode(fe, fp, FTYPE_SNG,
- (u_int *)&fs->fpreg[rt]);
+ (u_int *)&fs->fpreg[rt].fpr);
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
}
}
@@ -750,7 +752,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
* Otherwise set new current exceptions and accrue.
*/
if (fp)
- fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt]);
+ fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt].fpr);
cx = fe->fe_cx;
fsr = fe->fe_fpscr;
if (cx != 0) {
OpenPOWER on IntegriCloud