summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2002-09-17 03:51:50 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2002-09-17 03:51:50 +0000
commit0af5f7d7e417327f279b2e0c39805df2245cb728 (patch)
treec484672697515b8c7087c7e26a0b0a7fac0e0510
parent5ca251874f77e1a0a603d0d99e23ac447553efe6 (diff)
handle fpu exceptions properly, might use a regress, i guess
-rw-r--r--sys/arch/hppa/hppa/machdep.c10
-rw-r--r--sys/arch/hppa/hppa/trap.c51
-rw-r--r--sys/arch/hppa/include/cpu.h15
3 files changed, 67 insertions, 9 deletions
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c
index a99b3e167f8..938e1a57eee 100644
--- a/sys/arch/hppa/hppa/machdep.c
+++ b/sys/arch/hppa/hppa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.79 2002/09/11 16:01:37 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.80 2002/09/17 03:51:49 mickey Exp $ */
/*
* Copyright (c) 1999-2002 Michael Shalayeff
@@ -1156,7 +1156,7 @@ setregs(p, pack, stack, retval)
register_t *retval;
{
register struct trapframe *tf = p->p_md.md_regs;
- /* register struct pcb *pcb = &p->p_addr->u_pcb; */
+ register struct pcb *pcb = &p->p_addr->u_pcb;
#ifdef DEBUG
/*extern int pmapdebug;*/
/*pmapdebug = 13;
@@ -1172,6 +1172,12 @@ setregs(p, pack, stack, retval)
tf->tf_arg0 = (u_long)PS_STRINGS;
tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */
+ /* reset any of the pending FPU exceptions */
+ pcb->pcb_fpregs[0] = HPPA_FPU_INIT;
+ pcb->pcb_fpregs[1] = 0;
+ pcb->pcb_fpregs[2] = 0;
+ pcb->pcb_fpregs[3] = 0;
+
/* setup terminal stack frame */
stack = hppa_round_page(stack);
tf->tf_r3 = stack;
diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c
index 7d0f96e3fb6..effbc7f7fb4 100644
--- a/sys/arch/hppa/hppa/trap.c
+++ b/sys/arch/hppa/hppa/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.49 2002/09/12 04:36:19 mickey Exp $ */
+/* $OpenBSD: trap.c,v 1.50 2002/09/17 03:51:49 mickey Exp $ */
/*
* Copyright (c) 1998-2001 Michael Shalayeff
@@ -131,7 +131,6 @@ trap(type, frame)
{
extern u_int32_t sir;
struct proc *p = curproc;
- struct pcb *pcbp;
vaddr_t va;
struct vm_map *map;
struct vmspace *vm;
@@ -211,7 +210,7 @@ trap(type, frame)
case T_PRIV_REG:
/* these just can't make it to the trap() ever */
case T_HPMC: case T_HPMC | T_USER:
- case T_EMULATION: case T_EMULATION | T_USER:
+ case T_EMULATION:
#endif
case T_IBREAK:
case T_DATALIGN:
@@ -239,7 +238,48 @@ trap(type, frame)
/* pass to user debugger */
break;
- case T_EXCEPTION | T_USER: /* co-proc assist trap */
+ case T_EXCEPTION | T_USER: {
+ extern u_int32_t fpu_enable; /* from machdep */
+ extern paddr_t fpu_curpcb;
+ u_int32_t stat, *pex;
+ int i, flt;
+
+#ifdef DIAGNOSTIC
+ if (fpu_curpcb != frame->tf_cr30)
+ panic("trap: FPU is not owned");
+#endif
+ mfctl(CR_CCR, stat);
+ if (stat & fpu_enable) /* net quite there yet */
+ fpu_save((vaddr_t)p->p_addr->u_pcb.pcb_fpregs);
+ /* nobody owns it anymore */
+ fpu_curpcb = 0;
+ mtctl(stat & ~fpu_enable, CR_CCR);
+
+ /* get the exceptions and mask by the enabled mask */
+ pex = (u_int32_t *)&p->p_addr->u_pcb.pcb_fpregs[0];
+ for (i = 0, pex++; i < 7 && !*pex; i++, pex++);
+ stat = HPPA_FPU_OP(*pex);
+ if (stat & HPPA_FPU_V)
+ flt = FPE_FLTINV;
+ else if (stat & HPPA_FPU_Z)
+ flt = FPE_FLTDIV;
+ else if (stat & HPPA_FPU_O)
+ flt = FPE_FLTOVF;
+ else if (stat & HPPA_FPU_U)
+ flt = FPE_FLTUND;
+ else if (stat & HPPA_FPU_I)
+ flt = FPE_FLTRES;
+ else
+ flt = 0;
+ /* still left: under/over-flow and inexact */
+ *pex = 0;
+
+ sv.sival_int = va;
+ trapsignal(p, SIGFPE, type &~ T_USER, flt, sv);
+ }
+ break;
+
+ case T_EMULATION | T_USER: /* co-proc assist trap */
sv.sival_int = va;
trapsignal(p, SIGFPE, type &~ T_USER, FPE_FLTINV, sv);
break;
@@ -362,10 +402,9 @@ if (kdb_trap (type, va, frame))
if (kdb_trap (type, va, frame))
return;
#endif
- pcbp = &p->p_addr->u_pcb;
frame->tf_iioq_tail = 4 +
(frame->tf_iioq_head =
- pcbp->pcb_onfault);
+ p->p_addr->u_pcb.pcb_onfault);
#ifdef DDB
frame->tf_iir = 0;
#endif
diff --git a/sys/arch/hppa/include/cpu.h b/sys/arch/hppa/include/cpu.h
index 9c037f18be1..7de30854e37 100644
--- a/sys/arch/hppa/include/cpu.h
+++ b/sys/arch/hppa/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.31 2002/08/03 20:56:42 mickey Exp $ */
+/* $OpenBSD: cpu.h,v 1.32 2002/09/17 03:51:49 mickey Exp $ */
/*
* Copyright (c) 2000-2001 Michael Shalayeff
@@ -81,6 +81,19 @@ extern const char *cpu_typename;
*/
#define HPPA_FPUS 0xc0
#define HPPA_FPUVER(w) (((w) & 0x003ff800) >> 11)
+#define HPPA_FPU_OP(w) ((w) >> 26)
+#define HPPA_FPU_I 0x01
+#define HPPA_FPU_U 0x02
+#define HPPA_FPU_O 0x04
+#define HPPA_FPU_Z 0x08
+#define HPPA_FPU_V 0x10
+#define HPPA_FPU_D 0x20
+#define HPPA_FPU_T 0x40
+#define HPPA_FPU_RM 0x00000600
+#define HPPA_FPU_CQ 0x00fff800
+#define HPPA_FPU_C 0x04000000
+#define HPPA_FPU_FLSH 27
+#define HPPA_FPU_INIT (HPPA_FPU_I | HPPA_FPU_U | HPPA_FPU_O | HPPA_FPU_Z | HPPA_FPU_V)
#define HPPA_PMSFUS 0x20 /* ??? */
/*