Module Name: src Committed By: thorpej Date: Thu Jul 22 01:39:18 UTC 2021
Modified Files: src/sys/arch/alpha/alpha: fp_complete.c machdep.c src/sys/arch/alpha/include: cpu.h fpu.h Log Message: Various minor cleanups and bug fixes to the FP software completion code: - Use __CTASSERT() instead of rolling our own compile-time assertion using cpp. - Use __BIT() &c instead of rolling our own. - Improve some comments. - Define a default FP_C and FPCR value that is self-consistent, and initialize it properly at process creation time. - Fix signal information when the trap shadow cannot be resolved. - Use defined constants rather than magic numbers for the exception summary bits. - Add a machdep sysctl to enable FP software-completion debugging. To generate a diff of this commit: cvs rdiff -u -r1.24 -r1.25 src/sys/arch/alpha/alpha/fp_complete.c cvs rdiff -u -r1.374 -r1.375 src/sys/arch/alpha/alpha/machdep.c cvs rdiff -u -r1.102 -r1.103 src/sys/arch/alpha/include/cpu.h cvs rdiff -u -r1.7 -r1.8 src/sys/arch/alpha/include/fpu.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/alpha/alpha/fp_complete.c diff -u src/sys/arch/alpha/alpha/fp_complete.c:1.24 src/sys/arch/alpha/alpha/fp_complete.c:1.25 --- src/sys/arch/alpha/alpha/fp_complete.c:1.24 Tue Sep 1 08:22:36 2020 +++ src/sys/arch/alpha/alpha/fp_complete.c Thu Jul 22 01:39:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: fp_complete.c,v 1.24 2020/09/01 08:22:36 thorpej Exp $ */ +/* $NetBSD: fp_complete.c,v 1.25 2021/07/22 01:39:18 thorpej Exp $ */ /*- * Copyright (c) 2001 Ross Harvey @@ -33,9 +33,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_ddb.h" + #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.24 2020/09/01 08:22:36 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.25 2021/07/22 01:39:18 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -51,6 +53,30 @@ __KERNEL_RCSID(0, "$NetBSD: fp_complete. #include <lib/libkern/softfloat.h> +/* + * Validate our assumptions about bit positions. + */ +__CTASSERT(ALPHA_AESR_INV == (FP_X_INV << 1)); +__CTASSERT(ALPHA_AESR_DZE == (FP_X_DZ << 1)); +__CTASSERT(ALPHA_AESR_OVF == (FP_X_OFL << 1)); +__CTASSERT(ALPHA_AESR_UNF == (FP_X_UFL << 1)); +__CTASSERT(ALPHA_AESR_INE == (FP_X_IMP << 1)); +__CTASSERT(ALPHA_AESR_IOV == (FP_X_IOV << 1)); + +__CTASSERT(IEEE_TRAP_ENABLE_INV == (FP_X_INV << 1)); +__CTASSERT(IEEE_TRAP_ENABLE_DZE == (FP_X_DZ << 1)); +__CTASSERT(IEEE_TRAP_ENABLE_OVF == (FP_X_OFL << 1)); +__CTASSERT(IEEE_TRAP_ENABLE_UNF == (FP_X_UFL << 1)); +__CTASSERT(IEEE_TRAP_ENABLE_INE == (FP_X_IMP << 1)); + +__CTASSERT((uint64_t)FP_X_IMP << (61 - 3) == FPCR_INED); +__CTASSERT((uint64_t)FP_X_UFL << (61 - 3) == FPCR_UNFD); +__CTASSERT((uint64_t)FP_X_OFL << (49 - 0) == FPCR_OVFD); +__CTASSERT((uint64_t)FP_X_DZ << (49 - 0) == FPCR_DZED); +__CTASSERT((uint64_t)FP_X_INV << (49 - 0) == FPCR_INVD); + +__CTASSERT(FP_C_ALLBITS == MDLWP_FP_C); + #define TSWINSIZE 4 /* size of trap shadow window in uint32_t units */ /* Set Name Opcodes AARM C.* Symbols */ @@ -351,11 +377,12 @@ fp_c_to_fpcr_1(uint64_t fpcr, uint64_t f * it is necessary to initially set a sticky bit. */ - fpcr &= FPCR_DYN(3); + fpcr &= FPCR_DYN_RM; /* - * enable traps = case where flag bit is clear OR program wants a trap - * enables = ~flags | mask + * enable traps = case where flag bit is clear AND program wants a trap + * + * enables = ~flags & mask * disables = ~(~flags | mask) * disables = flags & ~mask. Thank you, Augustus De Morgan (1806-1871) */ @@ -364,18 +391,6 @@ fp_c_to_fpcr_1(uint64_t fpcr, uint64_t f fpcr |= (disables & (FP_X_IMP | FP_X_UFL)) << (61 - 3); fpcr |= (disables & (FP_X_OFL | FP_X_DZ | FP_X_INV)) << (49 - 0); -# if !(FP_X_INV == 1 && FP_X_DZ == 2 && FP_X_OFL == 4 && \ - FP_X_UFL == 8 && FP_X_IMP == 16 && FP_X_IOV == 32 && \ - FP_X_UFL << (61 - 3) == FPCR_UNFD && \ - FP_X_IMP << (61 - 3) == FPCR_INED && \ - FP_X_OFL << (49 - 0) == FPCR_OVFD) -# error "Assertion failed" - /* - * We don't care about the other built-in bit numbers because they - * have been architecturally specified. - */ -# endif - fpcr |= fp_c & FP_C_MIRRORED << (FPCR_MIR_START - FP_C_MIR_START); fpcr |= (fp_c & IEEE_MAP_DMZ) << 36; if (fp_c & FP_C_MIRRORED) @@ -407,6 +422,11 @@ alpha_write_fp_c(struct lwp *l, uint64_t alpha_pal_wrfen(1); fp_c_to_fpcr(l); alpha_pal_wrfen(0); + } else { + struct pcb *pcb = l->l_addr; + + pcb->pcb_fp.fpr_cr = + fp_c_to_fpcr_1(pcb->pcb_fp.fpr_cr, l->l_md.md_flags); } kpreempt_enable(); } @@ -502,12 +522,47 @@ float64_unk(float64 a, float64 b) */ static void +print_fp_instruction(alpha_instruction *pc, struct lwp *l, uint32_t bits) +{ +#if defined(DDB) + char buf[32]; + struct alpha_print_instruction_context ctx = { + .insn.bits = bits, + .pc = (unsigned long)pc, + .buf = buf, + .bufsize = sizeof(buf), + }; + + (void) alpha_print_instruction(&ctx); + + printf("INSN [%s:%d] @0x%lx -> %s\n", + l->l_proc->p_comm, l->l_proc->p_pid, ctx.pc, ctx.buf); +#else + alpha_instruction insn = { + .bits = bits, + }; + printf("INSN [%s:%d] @0x%lx -> opc=0x%x func=0x%x fa=%d fb=%d fc=%d\n", + l->l_proc->p_comm, l->l_proc->p_pid, (unsigned long)pc, + insn.float_format.opcode, insn.float_format.function, + insn.float_format.fa, insn.float_format.fb, insn.float_format.fc); + printf("INSN [%s:%d] @0x%lx -> trp=0x%x rnd=0x%x src=0x%x fn=0x%x\n", + l->l_proc->p_comm, l->l_proc->p_pid, (unsigned long)pc, + insn.float_detail.trp, insn.float_detail.rnd, + insn.float_detail.src, insn.float_detail.opclass); +#endif /* DDB */ +} + +static void alpha_fp_interpret(alpha_instruction *pc, struct lwp *l, uint32_t bits) { s_float sfa, sfb, sfc; t_float tfa, tfb, tfc; alpha_instruction inst; + if (alpha_fp_complete_debug) { + print_fp_instruction(pc, l, bits); + } + inst.bits = bits; switch(inst.generic_format.opcode) { default: @@ -588,15 +643,21 @@ alpha_fp_complete_at(alpha_instruction * } alpha_pal_wrfen(1); /* - * If necessary, lie about the dynamic rounding mode so emulation - * software need go to only one place for it, and so we don't have to - * lock any memory locations or pass a third parameter to every - * SoftFloat entry point. + * Alpha FLOAT instructions can override the rounding mode on a + * per-instruction basis. If necessary, lie about the dynamic + * rounding mode so emulation software need go to only one place + * for it, and so we don't have to lock any memory locations or + * pass a third parameter to every SoftFloat entry point. + * + * N.B. the rounding mode field of the the FLOAT format instructions + * matches that of the FPCR *except* for the value 3, which means + * "dynamic" rounding mode (i.e. what is programmed into the FPCR). */ orig_fpcr = fpcr = alpha_read_fpcr(); rm = inst.float_detail.rnd; - if (__predict_false(rm != 3 /* dynamic */ && rm != (fpcr >> 58 & 3))) { - fpcr = (fpcr & ~FPCR_DYN(3)) | FPCR_DYN(rm); + if (__predict_false(rm != 3 /* dynamic */ && + rm != __SHIFTOUT(fpcr, FPCR_DYN_RM))) { + fpcr = (fpcr & ~FPCR_DYN_RM) | __SHIFTIN(rm, FPCR_DYN_RM); alpha_write_fpcr(fpcr); } orig_flags = FP_C_TO_NETBSD_FLAG(l->l_md.md_flags); @@ -630,20 +691,33 @@ alpha_fp_complete(u_long a0, u_long a1, alpha_instruction *trigger_pc, *usertrap_pc; alpha_instruction *pc, *win_begin, tsw[TSWINSIZE]; - sig = SIGFPE; + if (alpha_fp_complete_debug) { + printf("%s: [%s:%d] a0[AESR]=0x%lx a1[regmask]=0x%lx " + "FPCR=0x%lx FP_C=0x%lx\n", + __func__, l->l_proc->p_comm, l->l_proc->p_pid, + a0, a1, alpha_read_fpcr(), + l->l_md.md_flags & (MDLWP_FP_C|MDLWP_FPACTIVE)); + } + pc = (alpha_instruction *)l->l_md.md_tf->tf_regs[FRAME_PC]; trigger_pc = pc - 1; /* for ALPHA_AMASK_PAT case */ + + /* + * Start out with the code mirroring the exception flags + * (FP_X_*). Shift right 1 bit to discard SWC to achive + * this. + */ + *ucode = a0 >> 1; + if (cpu_amask & ALPHA_AMASK_PAT) { - /* SWC | INV */ - if (a0 & 3 || alpha_fp_sync_complete) { + if ((a0 & (ALPHA_AESR_SWC | ALPHA_AESR_INV)) != 0 || + alpha_fp_sync_complete) { sig = alpha_fp_complete_at(trigger_pc, l, ucode); - goto done; + goto resolved; } } - *ucode = a0; - /* SWC | INV */ - if (!(a0 & 3)) - return sig; + if ((a0 & (ALPHA_AESR_SWC | ALPHA_AESR_INV)) == 0) + goto unresolved; /* * At this point we are somewhere in the trap shadow of one or more instruc- * tions that have trapped with software completion specified. We have a mask @@ -666,8 +740,13 @@ alpha_fp_complete(u_long a0, u_long a1, if (copyin(win_begin, tsw, sizeof tsw)) { /* sigh, try to get just one */ win_begin = pc; - if (copyin(win_begin, tsw, 4)) + if (copyin(win_begin, tsw, 4)) { + /* + * We're off the rails here; don't + * bother updating the FP_C. + */ return SIGSEGV; + } } } assert(win_begin <= pc && !((long)pc & 3)); @@ -695,17 +774,48 @@ alpha_fp_complete(u_long a0, u_long a1, if (__predict_true(trigger_pc != 0 && a1 == 0)) { ++alpha_shadow.resolved; sig = alpha_fp_complete_at(trigger_pc, l, ucode); + goto resolved; } else { ++alpha_shadow.unresolved; - return sig; } -done: + + unresolved: /* obligatory statement */; + /* + * *ucode contains the exception bits (FP_X_*). We need to + * update the FP_C and FPCR, and send a signal for any new + * trap that is enabled. + */ + uint64_t orig_flags = FP_C_TO_NETBSD_FLAG(l->l_md.md_flags); + uint64_t new_flags = orig_flags | *ucode; + uint64_t changed_flags = orig_flags ^ new_flags; + KASSERT((orig_flags | changed_flags) == new_flags); /* panic on 1->0 */ + + l->l_md.md_flags |= NETBSD_FLAG_TO_FP_C(new_flags); + + kpreempt_disable(); + if ((curlwp->l_md.md_flags & MDLWP_FPACTIVE) == 0) { + fpu_load(); + } + alpha_pal_wrfen(1); + uint64_t orig_fpcr = alpha_read_fpcr(); + alpha_write_fpcr(fp_c_to_fpcr_1(orig_fpcr, l->l_md.md_flags)); + uint64_t needsig = + changed_flags & FP_C_TO_NETBSD_MASK(l->l_md.md_flags); + alpha_pal_wrfen(0); + kpreempt_enable(); + + if (__predict_false(needsig)) { + *ucode = needsig; + return SIGFPE; + } + return 0; + + resolved: if (sig) { usertrap_pc = trigger_pc + 1; l->l_md.md_tf->tf_regs[FRAME_PC] = (unsigned long)usertrap_pc; - return sig; } - return 0; + return sig; } /* @@ -746,6 +856,11 @@ fpu_state_load(struct lwp *l, u_int flag atomic_inc_ulong(&fpevent_reuse.ev_count); } + if (alpha_fp_complete_debug) { + printf("%s: [%s:%d] loading FPCR=0x%lx\n", + __func__, l->l_proc->p_comm, l->l_proc->p_pid, + pcb->pcb_fp.fpr_cr); + } alpha_pal_wrfen(1); restorefpstate(&pcb->pcb_fp); alpha_pal_wrfen(0); @@ -765,6 +880,11 @@ fpu_state_save(struct lwp *l) alpha_pal_wrfen(1); savefpstate(&pcb->pcb_fp); alpha_pal_wrfen(0); + if (alpha_fp_complete_debug) { + printf("%s: [%s:%d] saved FPCR=0x%lx\n", + __func__, l->l_proc->p_comm, l->l_proc->p_pid, + pcb->pcb_fp.fpr_cr); + } } /* Index: src/sys/arch/alpha/alpha/machdep.c diff -u src/sys/arch/alpha/alpha/machdep.c:1.374 src/sys/arch/alpha/alpha/machdep.c:1.375 --- src/sys/arch/alpha/alpha/machdep.c:1.374 Sun Jul 11 01:58:41 2021 +++ src/sys/arch/alpha/alpha/machdep.c Thu Jul 22 01:39:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.374 2021/07/11 01:58:41 thorpej Exp $ */ +/* $NetBSD: machdep.c,v 1.375 2021/07/22 01:39:18 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2019, 2020 The NetBSD Foundation, Inc. @@ -65,11 +65,11 @@ #include "opt_dec_3000_500.h" #include "opt_execfmt.h" -#define __RWLOCK_PRIVATE +#define __RWLOCK_PRIVATE #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.374 2021/07/11 01:58:41 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.375 2021/07/22 01:39:18 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -195,6 +195,7 @@ int alpha_unaligned_print = 1; /* warn a int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ int alpha_fp_sync_complete = 0; /* fp fixup if sync even without /s */ +int alpha_fp_complete_debug = 0; /* fp completion debug enabled */ /* * XXX This should be dynamically sized, but we have the chicken-egg problem! @@ -1646,6 +1647,11 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc CTLTYPE_BOOL, "is_qemu", NULL, NULL, 0, &alpha_is_qemu, 0, CTL_MACHDEP, CPU_IS_QEMU, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "fp_complete_debug", NULL, + NULL, 0, &alpha_fp_complete_debug, 0, + CTL_MACHDEP, CPU_FP_COMPLETE_DEBUG, CTL_EOL); } /* @@ -1687,8 +1693,10 @@ setregs(register struct lwp *l, struct e tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ if (__predict_true((l->l_md.md_flags & IEEE_INHERIT) == 0)) { - l->l_md.md_flags &= ~MDLWP_FP_C; - pcb->pcb_fp.fpr_cr = FPCR_DYN(FP_RN); + l->l_md.md_flags = + (l->l_md.md_flags & ~(MDLWP_FP_C | MDLWP_FPACTIVE)) | + FP_C_DEFAULT; + pcb->pcb_fp.fpr_cr = FPCR_DEFAULT; } } Index: src/sys/arch/alpha/include/cpu.h diff -u src/sys/arch/alpha/include/cpu.h:1.102 src/sys/arch/alpha/include/cpu.h:1.103 --- src/sys/arch/alpha/include/cpu.h:1.102 Sat Jun 26 15:02:19 2021 +++ src/sys/arch/alpha/include/cpu.h Thu Jul 22 01:39:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.102 2021/06/26 15:02:19 skrll Exp $ */ +/* $NetBSD: cpu.h,v 1.103 2021/07/22 01:39:18 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -232,6 +232,7 @@ void cpu_signotify(struct lwp *); #define CPU_FP_SYNC_COMPLETE 7 /* int: always fixup sync fp traps */ #define CPU_CCTR 8 /* int: using CC timecounter */ #define CPU_IS_QEMU 9 /* int: running under Qemu */ +#define CPU_FP_COMPLETE_DEBUG 10 /* int: enable FP completion debug */ #ifdef _KERNEL Index: src/sys/arch/alpha/include/fpu.h diff -u src/sys/arch/alpha/include/fpu.h:1.7 src/sys/arch/alpha/include/fpu.h:1.8 --- src/sys/arch/alpha/include/fpu.h:1.7 Tue Oct 17 00:26:35 2017 +++ src/sys/arch/alpha/include/fpu.h Thu Jul 22 01:39:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.h,v 1.7 2017/10/17 00:26:35 maya Exp $ */ +/* $NetBSD: fpu.h,v 1.8 2021/07/22 01:39:18 thorpej Exp $ */ /*- * Copyright (c) 2001 Ross Harvey @@ -38,35 +38,50 @@ #ifndef _ALPHA_FPU_H_ #define _ALPHA_FPU_H_ -#define _FP_C_DEF(n) (1UL << (n)) - /* * Most of these next definitions were moved from <ieeefp.h>. Apparently the * names happen to match those exported by Compaq and Linux from their fpu.h * files. */ -#define FPCR_SUM _FP_C_DEF(63) -#define FPCR_INED _FP_C_DEF(62) -#define FPCR_UNFD _FP_C_DEF(61) -#define FPCR_UNDZ _FP_C_DEF(60) -#define FPCR_DYN(rm) ((unsigned long)(rm) << 58) -#define FPCR_IOV _FP_C_DEF(57) -#define FPCR_INE _FP_C_DEF(56) -#define FPCR_UNF _FP_C_DEF(55) -#define FPCR_OVF _FP_C_DEF(54) -#define FPCR_DZE _FP_C_DEF(53) -#define FPCR_INV _FP_C_DEF(52) -#define FPCR_OVFD _FP_C_DEF(51) -#define FPCR_DZED _FP_C_DEF(50) -#define FPCR_INVD _FP_C_DEF(49) -#define FPCR_DNZ _FP_C_DEF(48) -#define FPCR_DNOD _FP_C_DEF(47) +/* + * Bits in the Alpha Floating Point Control register. This is the hardware + * register, and should not be directly manipulated by application software. + */ +#define FPCR_SUM __BIT(63) /* Summary (OR of all exception bits) */ +#define FPCR_INED __BIT(62) /* Inexact trap Disable */ +#define FPCR_UNFD __BIT(61) /* Underflow trap Disable */ +#define FPCR_UNDZ __BIT(60) /* Underflow to Zero */ +#define FPCR_DYN_RM __BITS(58,59) /* Dynamic Rounding Mode */ + /* 00 Chopped */ + /* 01 Minus Infinity */ + /* 10 Normal (round nearest) */ + /* 11 Plus Infinity */ +#define FPCR_IOV __BIT(57) /* Integer Overflow */ +#define FPCR_INE __BIT(56) /* Inexact Result */ +#define FPCR_UNF __BIT(55) /* Underflow */ +#define FPCR_OVF __BIT(54) /* Overflow */ +#define FPCR_DZE __BIT(53) /* Division By Zero */ +#define FPCR_INV __BIT(52) /* Invalid Operation */ +#define FPCR_OVFD __BIT(51) /* Overflow trap Disable */ +#define FPCR_DZED __BIT(50) /* Division By Zero trap Disable */ +#define FPCR_INVD __BIT(49) /* Invalid Operation trap Disable */ +#define FPCR_DNZ __BIT(48) /* Denormal Operands to Zero */ +#define FPCR_DNOD __BIT(47) /* Denormal Operation tap Disable */ #define FPCR_MIRRORED (FPCR_INE | FPCR_UNF | FPCR_OVF | FPCR_DZE | FPCR_INV) #define FPCR_MIR_START 52 +/* NetBSD default - no traps enabled, round-to-nearest */ +#define FPCR_DEFAULT (__SHIFTIN(FP_RN, FPCR_DYN_RM) | \ + FPCR_INED | FPCR_UNFD | FPCR_OVFD | \ + FPCR_DZED | FPCR_INVD | FPCR_DNOD) + /* + * IEEE Floating Point Control (FP_C) Quadword. This is a software + * virtual register that abstracts the FPCR and software complation + * performed by the kernel. + * * The AARM specifies the bit positions of the software word used for * user mode interface to the control and status of the kernel completion * routines. Although it largely just redefines the FPCR, it shuffles @@ -74,30 +89,41 @@ * the definition prefix can easily be determined from public domain * programs written to either the Compaq or Linux interfaces, which * appear to be identical. + * + * Bits 63-48 are reserved for implementation software. + * Bits 47-23 are reserved for future archiecture definition. + * Bits 16-12 are reserved for implementation software. + * Bits 11-7 are reserved for future architecture definition. + * Bit 0 is reserved for implementation software. */ -#define IEEE_STATUS_DNO _FP_C_DEF(22) -#define IEEE_STATUS_INE _FP_C_DEF(21) -#define IEEE_STATUS_UNF _FP_C_DEF(20) -#define IEEE_STATUS_OVF _FP_C_DEF(19) -#define IEEE_STATUS_DZE _FP_C_DEF(18) -#define IEEE_STATUS_INV _FP_C_DEF(17) - -#define IEEE_TRAP_ENABLE_DNO _FP_C_DEF(6) -#define IEEE_TRAP_ENABLE_INE _FP_C_DEF(5) -#define IEEE_TRAP_ENABLE_UNF _FP_C_DEF(4) -#define IEEE_TRAP_ENABLE_OVF _FP_C_DEF(3) -#define IEEE_TRAP_ENABLE_DZE _FP_C_DEF(2) -#define IEEE_TRAP_ENABLE_INV _FP_C_DEF(1) - -#define IEEE_INHERIT _FP_C_DEF(14) -#define IEEE_MAP_UMZ _FP_C_DEF(13) /* Map underflowed outputs to zero */ -#define IEEE_MAP_DMZ _FP_C_DEF(12) /* Map denormal inputs to zero */ +#define IEEE_STATUS_DNO __BIT(22) /* Denormal Operand */ +#define IEEE_STATUS_INE __BIT(21) /* Inexact Result */ +#define IEEE_STATUS_UNF __BIT(20) /* Underflow */ +#define IEEE_STATUS_OVF __BIT(19) /* Overflow */ +#define IEEE_STATUS_DZE __BIT(18) /* Division By Zero */ +#define IEEE_STATUS_INV __BIT(17) /* Invalid Operation */ + +#define IEEE_TRAP_ENABLE_DNO __BIT(6) /* Denormal Operation trap */ +#define IEEE_TRAP_ENABLE_INE __BIT(5) /* Inexact Result trap */ +#define IEEE_TRAP_ENABLE_UNF __BIT(4) /* Underflow trap */ +#define IEEE_TRAP_ENABLE_OVF __BIT(3) /* Overflow trap */ +#define IEEE_TRAP_ENABLE_DZE __BIT(2) /* Division By Zero trap */ +#define IEEE_TRAP_ENABLE_INV __BIT(1) /* Invalid Operation trap */ + +#define IEEE_INHERIT __BIT(14) +#define IEEE_MAP_UMZ __BIT(13) /* Map underflowed outputs to zero */ +#define IEEE_MAP_DMZ __BIT(12) /* Map denormal inputs to zero */ -#define FP_C_MIRRORED (IEEE_STATUS_INE | IEEE_STATUS_UNF | IEEE_STATUS_OVF\ - | IEEE_STATUS_DZE | IEEE_STATUS_INV) +#define FP_C_ALLBITS __BITS(1,22) + +#define FP_C_MIRRORED (IEEE_STATUS_INE | IEEE_STATUS_UNF | IEEE_STATUS_OVF \ + | IEEE_STATUS_DZE | IEEE_STATUS_INV) #define FP_C_MIR_START 17 +/* NetBSD default - no traps enabled (see FPCR default) */ +#define FP_C_DEFAULT 0 + #ifdef _KERNEL #define FLD_MASK(len) ((1UL << (len)) - 1) @@ -115,6 +141,6 @@ #define SET_FP_C_MASK(fp_c, m) (CLEAR_FP_C_MASK(fp_c) | NETBSD_MASK_TO_FP_C(m)) #define SET_FP_C_FLAG(fp_c, m) (CLEAR_FP_C_FLAG(fp_c) | NETBSD_FLAG_TO_FP_C(m)) -#endif +#endif /* _KERNEL */ -#endif +#endif /* _ALPHA_FPU_H_ */