static int printed;
/* clear pending exceptions; no traps in vfp3; all v7 ops are scalar */
- m->fpscr = Dn | Fz | FPRNR | (FPINVAL | FPZDIV | FPOVFL) & ~Alltraps;
+ m->fpscr = Dn | FPRNR | (FPINVAL | FPZDIV | FPOVFL) & ~Alltraps;
+ /* VFPv2 needs software support for underflows, so force them to zero */
+ if(m->havefp == VFPv2)
+ m->fpscr |= Fz;
fpwr(Fpscr, m->fpscr);
m->fpconfiged = 1;
fpunotify(Ureg*)
{
if(up->fpstate == FPactive){
- fpsave(&up->fpsave);
+ fpsave(up->fpsave);
up->fpstate = FPinactive;
}
up->fpstate |= FPillegal;
up->fpstate &= ~FPillegal;
}
-/*
- * Called early in the non-interruptible path of
- * sysrfork() via the machine-dependent syscall() routine.
- * Save the state so that it can be easily copied
- * to the child process later.
- */
-void
-fpusysrfork(Ureg*)
-{
- if(up->fpstate == FPactive){
- fpsave(&up->fpsave);
- up->fpstate = FPinactive;
- }
-}
-
-/*
- * Called later in sysrfork() via the machine-dependent
- * sysrforkchild() routine.
- * Copy the parent FPU state to the child.
- */
-void
-fpusysrforkchild(Proc *p, Ureg *, Proc *up)
-{
- /* don't penalize the child, it hasn't done FP in a note handler. */
- p->fpstate = up->fpstate & ~FPillegal;
-}
-
/* should only be called if p->fpstate == FPactive */
void
fpsave(FPsave *fps)
int n;
fpon();
- fpwr(Fpscr, p->fpsave.control);
+ fpwr(Fpscr, p->fpsave->control);
m->fpscr = fprd(Fpscr) & ~Allcc;
assert(m->fpnregs);
for (n = 0; n < m->fpnregs; n++)
- fprestreg(n, *(uvlong *)p->fpsave.regs[n]);
+ fprestreg(n, *(uvlong *)p->fpsave->regs[n]);
}
/*
{
if(p->fpstate == FPactive){
if(p->state == Moribund)
- fpclear();
+ fpoff();
else{
/*
* Fpsave() stores without handling pending
* until the process runs again and generates an
* emulation fault to activate the FPU.
*/
- fpsave(&p->fpsave);
+ fpsave(p->fpsave);
}
p->fpstate = FPinactive;
}
{
}
+/*
+ * The current process has been forked,
+ * save and copy neccesary state to child.
+ */
+void
+fpuprocfork(Proc *p)
+{
+ int s;
+
+ s = splhi();
+ switch(up->fpstate & ~FPillegal){
+ case FPactive:
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ /* no break */
+ case FPinactive:
+ memmove(p->fpsave, up->fpsave, sizeof(FPsave));
+ p->fpstate = FPinactive;
+ }
+ splx(s);
+}
+
/*
* Disable the FPU.
* Called from sysexec() via sysprocsetup() to
void
fpusysprocsetup(Proc *p)
{
+ int s;
+
+ s = splhi();
p->fpstate = FPinit;
fpoff();
+ splx(s);
}
static void
ulong status;
char *msg, note[ERRMAX];
- status = up->fpsave.status;
+ status = up->fpsave->status;
/*
* Some attention should probably be paid here to the
else
msg = "spurious";
snprint(note, sizeof note, "sys: fp: %s fppc=%#p status=%#lux",
- msg, up->fpsave.pc, status);
+ msg, up->fpsave->pc, status);
postnote(up, 1, note, NDebug);
}
static void
mathemu(Ureg *)
{
- if(m->havefp == VFPv3 && !(fprd(Fpexc) & (Fpex|Fpdex)))
- iprint("mathemu: not an FP exception but an unknown FP opcode\n");
switch(up->fpstate){
case FPemu:
error("illegal instruction: VFP opcode in emulated mode");
* More attention should probably be paid here to the
* exception masks and error summary.
*/
- if(up->fpsave.status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){
+ if(up->fpsave->status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){
mathnote();
break;
}
{
int s, nfp, cop, op;
uintptr pc;
+ static int already;
if(waserror()){
postnote(up, 1, up->errstr, NDebug);
nfp = 0;
pc = ureg->pc;
validaddr(pc, 4, 0);
- if(!condok(ureg->psr, *(ulong*)pc >> 28))
- iprint("fpuemu: conditional instr shouldn't have got here\n");
op = (*(ulong *)pc >> 24) & MASK(4);
cop = (*(ulong *)pc >> 8) & MASK(4);
if(m->fpon)
fpstuck(pc); /* debugging; could move down 1 line */
if (ISFPAOP(cop, op)) { /* old arm 7500 fpa opcode? */
-// iprint("fpuemu: fpa instr %#8.8lux at %#p\n", *(ulong *)pc, pc);
-// error("illegal instruction: old arm 7500 fpa opcode");
s = spllo();
+ if(!already++)
+ pprint("warning: emulated arm7500 fpa instr %#8.8lux at %#p\n", *(ulong *)pc, pc);
if(waserror()){
splx(s);
nexterror();
m->fppc = m->fpcnt = 0;
splx(s);
poperror();
- } else if (ISVFPOP(cop, op)) { /* if vfp, fpu must be off */
+ } else if (ISVFPOP(cop, op)) { /* if vfp, fpu off or unsupported instruction */
mathemu(ureg); /* enable fpu & retry */
nfp = 1;
}