]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/bcm/vfp3.c
merge
[plan9front.git] / sys / src / 9 / bcm / vfp3.c
index e87cf1d321a96857bf4d4628023c210bf2fcea8c..cefeda2618ca51751f101685da8330ed7ab4128c 100644 (file)
@@ -163,7 +163,10 @@ fpcfg(void)
        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;
 
@@ -222,7 +225,7 @@ void
 fpunotify(Ureg*)
 {
        if(up->fpstate == FPactive){
-               fpsave(&up->fpsave);
+               fpsave(up->fpsave);
                up->fpstate = FPinactive;
        }
        up->fpstate |= FPillegal;
@@ -239,33 +242,6 @@ fpunoted(void)
        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)
@@ -286,11 +262,11 @@ fprestore(Proc *p)
        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]);
 }
 
 /*
@@ -305,7 +281,7 @@ fpuprocsave(Proc *p)
 {
        if(p->fpstate == FPactive){
                if(p->state == Moribund)
-                       fpclear();
+                       fpoff();
                else{
                        /*
                         * Fpsave() stores without handling pending
@@ -315,7 +291,7 @@ fpuprocsave(Proc *p)
                         * until the process runs again and generates an
                         * emulation fault to activate the FPU.
                         */
-                       fpsave(&p->fpsave);
+                       fpsave(p->fpsave);
                }
                p->fpstate = FPinactive;
        }
@@ -332,6 +308,28 @@ fpuprocrestore(Proc *)
 {
 }
 
+/*
+ * 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
@@ -340,8 +338,12 @@ fpuprocrestore(Proc *)
 void
 fpusysprocsetup(Proc *p)
 {
+       int s;
+
+       s = splhi();
        p->fpstate = FPinit;
        fpoff();
+       splx(s);
 }
 
 static void
@@ -350,7 +352,7 @@ mathnote(void)
        ulong status;
        char *msg, note[ERRMAX];
 
-       status = up->fpsave.status;
+       status = up->fpsave->status;
 
        /*
         * Some attention should probably be paid here to the
@@ -369,15 +371,13 @@ mathnote(void)
        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");
@@ -393,7 +393,7 @@ mathemu(Ureg *)
                 * 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;
                }
@@ -477,6 +477,7 @@ fpuemu(Ureg* ureg)
 {
        int s, nfp, cop, op;
        uintptr pc;
+       static int already;
 
        if(waserror()){
                postnote(up, 1, up->errstr, NDebug);
@@ -489,16 +490,14 @@ fpuemu(Ureg* ureg)
        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();
@@ -508,7 +507,7 @@ fpuemu(Ureg* ureg)
                        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;
        }