diff options
author | Andrew Fresh <afresh1@cvs.openbsd.org> | 2016-03-30 15:39:47 +0000 |
---|---|---|
committer | Andrew Fresh <afresh1@cvs.openbsd.org> | 2016-03-30 15:39:47 +0000 |
commit | 628cce6b418a9791aa4990f00511a2f5d4303252 (patch) | |
tree | b2a9b4a79d67bc3aaa8e598341233a992c58f0c0 | |
parent | de1ef868608c897383ae96e1c842e9254fb5ff30 (diff) |
Better support for alphas without all IEEE-mode instructions
From Miod Vallat
I trust miod deraadt@
-rw-r--r-- | sys/arch/alpha/alpha/fp_complete.c | 47 | ||||
-rw-r--r-- | sys/arch/alpha/alpha/trap.c | 20 | ||||
-rw-r--r-- | sys/arch/alpha/include/cpu.h | 3 |
3 files changed, 43 insertions, 27 deletions
diff --git a/sys/arch/alpha/alpha/fp_complete.c b/sys/arch/alpha/alpha/fp_complete.c index 6197664b44d..81b3cbb5941 100644 --- a/sys/arch/alpha/alpha/fp_complete.c +++ b/sys/arch/alpha/alpha/fp_complete.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fp_complete.c,v 1.11 2014/11/18 20:51:00 krw Exp $ */ +/* $OpenBSD: fp_complete.c,v 1.12 2016/03/30 15:39:46 afresh1 Exp $ */ /* $NetBSD: fp_complete.c,v 1.5 2002/01/18 22:15:56 ross Exp $ */ /*- @@ -73,13 +73,17 @@ #define IS_SUBNORMAL(v) ((v)->exp == 0 && (v)->frac != 0) -#define PREFILTER_SUBNORMAL(p,v) if ((p)->p_md.md_flags & IEEE_MAP_DMZ \ - && IS_SUBNORMAL(v)) \ - (v)->frac = 0; else +#define PREFILTER_SUBNORMAL(p,v) \ +do { \ + if ((p)->p_md.md_flags & IEEE_MAP_DMZ && IS_SUBNORMAL(v)) \ + (v)->frac = 0; \ +} while (0) -#define POSTFILTER_SUBNORMAL(p,v) if ((p)->p_md.md_flags & IEEE_MAP_UMZ \ - && IS_SUBNORMAL(v)) \ - (v)->frac = 0; else +#define POSTFILTER_SUBNORMAL(p,v) \ +do { \ + if ((p)->p_md.md_flags & IEEE_MAP_UMZ && IS_SUBNORMAL(v)) \ + (v)->frac = 0; \ +} while (0) /* Alpha returns 2.0 for true, all zeroes for false. */ @@ -493,7 +497,7 @@ float64_unk(float64 a, float64 b) */ static void -alpha_fp_interpret(alpha_instruction *pc, struct proc *p, u_int64_t bits) +alpha_fp_interpret(struct proc *p, u_int64_t bits) { s_float sfa, sfb, sfc; t_float tfa, tfb, tfc; @@ -560,16 +564,15 @@ alpha_fp_interpret(alpha_instruction *pc, struct proc *p, u_int64_t bits) } } -static int -alpha_fp_complete_at(alpha_instruction *trigger_pc, struct proc *p, - u_int64_t *ucode) +int +alpha_fp_complete_at(u_long trigger_pc, struct proc *p, u_int64_t *ucode) { int needsig; alpha_instruction inst; u_int64_t rm, fpcr, orig_fpcr; u_int64_t orig_flags, new_flags, changed_flags, md_flags; - if (__predict_false(copyin(trigger_pc, &inst, sizeof inst))) { + if (__predict_false(copyin((void *)trigger_pc, &inst, sizeof inst))) { this_cannot_happen(6, -1); return SIGSEGV; } @@ -589,7 +592,7 @@ alpha_fp_complete_at(alpha_instruction *trigger_pc, struct proc *p, } orig_flags = FP_C_TO_OPENBSD_FLAG(p->p_md.md_flags); - alpha_fp_interpret(trigger_pc, p, inst.bits); + alpha_fp_interpret(p, inst.bits); md_flags = p->p_md.md_flags; @@ -614,12 +617,12 @@ alpha_fp_complete(u_long a0, u_long a1, struct proc *p, u_int64_t *ucode) u_int64_t op_class; alpha_instruction inst; /* "trigger_pc" is Compaq's term for the earliest faulting op */ - alpha_instruction *trigger_pc, *usertrap_pc; + u_long trigger_pc, usertrap_pc; alpha_instruction *pc, *win_begin, tsw[TSWINSIZE]; sig = SIGFPE; pc = (alpha_instruction *)p->p_md.md_tf->tf_regs[FRAME_PC]; - trigger_pc = pc - 1; /* for ALPHA_AMASK_PAT case */ + trigger_pc = (u_long)pc - 4; /* for ALPHA_AMASK_PAT case */ if (cpu_amask & ALPHA_AMASK_PAT) { if (a0 & 1 || alpha_fp_sync_complete) { sig = alpha_fp_complete_at(trigger_pc, p, ucode); @@ -639,12 +642,6 @@ alpha_fp_complete(u_long a0, u_long a1, struct proc *p, u_int64_t *ucode) * interpret this one instruction in SW. If a SIGFPE is not required, back up * the PC until just after this instruction and restart. This will execute all * trap shadow instructions between the trigger pc and the trap pc twice. - * - * If a SIGFPE is generated from the OSF1 emulation, back up one more - * instruction to the trigger pc itself. Native binaries don't because it - * is non-portable and completely defeats the intended purpose of IEEE - * traps -- for example, to count the number of exponent wraps for a later - * correction. */ trigger_pc = 0; win_begin = pc; @@ -665,10 +662,10 @@ alpha_fp_complete(u_long a0, u_long a1, struct proc *p, u_int64_t *ucode) op_class = 1UL << inst.generic_format.opcode; if (op_class & FPUREG_CLASS) { a1 &= ~(1UL << (inst.operate_generic_format.rc + 32)); - trigger_pc = pc; + trigger_pc = (u_long)pc; } else if (op_class & CPUREG_CLASS) { a1 &= ~(1UL << inst.operate_generic_format.rc); - trigger_pc = pc; + trigger_pc = (u_long)pc; } else if (op_class & TRAPSHADOWBOUNDARY) { if (op_class & CHECKFUNCTIONCODE) { if (inst.mem_format.displacement == op_trapb || @@ -691,8 +688,8 @@ alpha_fp_complete(u_long a0, u_long a1, struct proc *p, u_int64_t *ucode) } done: if (sig) { - usertrap_pc = trigger_pc + 1; - p->p_md.md_tf->tf_regs[FRAME_PC] = (unsigned long)usertrap_pc; + usertrap_pc = trigger_pc + 4; + p->p_md.md_tf->tf_regs[FRAME_PC] = usertrap_pc; return sig; } return 0; diff --git a/sys/arch/alpha/alpha/trap.c b/sys/arch/alpha/alpha/trap.c index ad9373346ec..4475f8a7ff1 100644 --- a/sys/arch/alpha/alpha/trap.c +++ b/sys/arch/alpha/alpha/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.80 2015/06/23 12:29:46 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.81 2016/03/30 15:39:46 afresh1 Exp $ */ /* $NetBSD: trap.c,v 1.52 2000/05/24 16:48:33 thorpej Exp $ */ /*- @@ -1231,6 +1231,24 @@ handle_opdec(p, ucodep) } goto sigill; +#ifndef NO_IEEE + /* case op_fix_float: */ + /* case op_vax_float: */ + case op_ieee_float: + /* case op_any_float: */ + /* + * EV4 processors do not implement dynamic rounding + * instructions at all. + */ + if (cpu_implver <= ALPHA_IMPLVER_EV4) { + sig = alpha_fp_complete_at(inst_pc, p, ucodep); + if (sig) + return sig; + break; + } + goto sigill; +#endif + default: goto sigill; } diff --git a/sys/arch/alpha/include/cpu.h b/sys/arch/alpha/include/cpu.h index 71c9c9cf6a9..fb1dc79e045 100644 --- a/sys/arch/alpha/include/cpu.h +++ b/sys/arch/alpha/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.56 2016/03/01 19:17:37 mmcc Exp $ */ +/* $OpenBSD: cpu.h,v 1.57 2016/03/30 15:39:46 afresh1 Exp $ */ /* $NetBSD: cpu.h,v 1.45 2000/08/21 02:03:12 thorpej Exp $ */ /*- @@ -393,6 +393,7 @@ u_int64_t alpha_read_fp_c(struct proc *); void alpha_write_fp_c(struct proc *, u_int64_t); int alpha_fp_complete(u_long, u_long, struct proc *, u_int64_t *); +int alpha_fp_complete_at(u_long, struct proc *, u_int64_t *); #endif void alpha_enable_fp(struct proc *, int); |