diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-27 23:54:12 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-27 23:54:12 +0000 |
commit | d3e71cb08747743fce908122bab08b479eb403a5 (patch) | |
tree | cbec6948fdbdee9af81cf3ecfb504070d2745d7b /arch/alpha/math-emu | |
parent | fe7ff1706e323d0e5ed83972960a1ecc1ee538b3 (diff) |
Merge with Linux 2.3.99-pre3.
Diffstat (limited to 'arch/alpha/math-emu')
-rw-r--r-- | arch/alpha/math-emu/math.c | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/arch/alpha/math-emu/math.c b/arch/alpha/math-emu/math.c index c0ece7bcb..ed2efe087 100644 --- a/arch/alpha/math-emu/math.c +++ b/arch/alpha/math-emu/math.c @@ -160,8 +160,7 @@ alpha_fp_emul (unsigned long pc) FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); unsigned long fa, fb, fc, func, mode, src; - unsigned long fpcw = current->thread.flags; - unsigned long res, va, vb, vc, fpcr; + unsigned long res, va, vb, vc, swcr, fpcr; __u32 insn; MOD_INC_USE_COUNT; @@ -175,10 +174,11 @@ alpha_fp_emul (unsigned long pc) mode = (insn >> 11) & 0x3; fpcr = rdfpcr(); + swcr = swcr_update_status(current->thread.flags, fpcr); if (mode == 3) { - /* Dynamic -- get rounding mode from fpcr. */ - mode = (fpcr >> FPCR_DYN_SHIFT) & 3; + /* Dynamic -- get rounding mode from fpcr. */ + mode = (fpcr >> FPCR_DYN_SHIFT) & 3; } switch (src) { @@ -231,9 +231,14 @@ alpha_fp_emul (unsigned long pc) } FP_CMP_D(res, DA, DB, 3); vc = 0x4000000000000000; - /* CMPTEQ, CMPTUN don't trap on QNaN, while CMPTLT and CMPTLE do */ - if (res == 3 && ((func & 3) >= 2 || FP_ISSIGNAN_D(DA) || FP_ISSIGNAN_D(DB))) + /* CMPTEQ, CMPTUN don't trap on QNaN, + while CMPTLT and CMPTLE do */ + if (res == 3 + && ((func & 3) >= 2 + || FP_ISSIGNAN_D(DA) + || FP_ISSIGNAN_D(DB))) { FP_SET_EXCEPTION(FP_EX_INVALID); + } switch (func) { case FOP_FNC_CMPxUN: if (res != 3) vc = 0; break; case FOP_FNC_CMPxEQ: if (res) vc = 0; break; @@ -285,9 +290,11 @@ alpha_fp_emul (unsigned long pc) } case FOP_FNC_CVTxQ: - if (DB_c == FP_CLS_NAN && (_FP_FRAC_HIGH_RAW_D(DB) & _FP_QNANBIT_D)) - vc = 0; /* AAHB Table B-2 sais QNaN should not trigger INV */ - else + if (DB_c == FP_CLS_NAN + && (_FP_FRAC_HIGH_RAW_D(DB) & _FP_QNANBIT_D)) { + /* AAHB Table B-2 says QNaN should not trigger INV */ + vc = 0; + } else FP_TO_INT_ROUND_D(vc, DB, 64, 2); goto done_d; } @@ -321,11 +328,15 @@ alpha_fp_emul (unsigned long pc) pack_s: FP_PACK_SP(&vc, SR); + if ((_fex & FP_EX_UNDERFLOW) && (swcr & IEEE_MAP_UMZ)) + vc = 0; alpha_write_fp_reg_s(fc, vc); goto done; pack_d: FP_PACK_DP(&vc, DR); + if ((_fex & FP_EX_UNDERFLOW) && (swcr & IEEE_MAP_UMZ)) + vc = 0; done_d: alpha_write_fp_reg(fc, vc); goto done; @@ -345,16 +356,16 @@ done_d: done: if (_fex) { /* Record exceptions in software control word. */ - current->thread.flags - = fpcw |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + current->thread.flags |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); - /* Update hardware control register */ + /* Update hardware control register. */ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); - fpcr |= ieee_swcr_to_fpcr(fpcw); + fpcr |= ieee_swcr_to_fpcr(swcr); wrfpcr(fpcr); /* Do we generate a signal? */ - if (_fex & fpcw & IEEE_TRAP_ENABLE_MASK) { + if (_fex & swcr & IEEE_TRAP_ENABLE_MASK) { MOD_DEC_USE_COUNT; return 0; } @@ -378,7 +389,7 @@ long alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask) { unsigned long trigger_pc = regs->pc - 4; - unsigned long insn, opcode, rc; + unsigned long insn, opcode, rc, no_signal = 0; MOD_INC_USE_COUNT; @@ -402,15 +413,13 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask) case OPC_PAL: case OPC_JSR: case 0x30 ... 0x3f: /* branches */ - MOD_DEC_USE_COUNT; - return 0; + goto egress; case OPC_MISC: switch (insn & 0xffff) { case MISC_TRAPB: case MISC_EXCB: - MOD_DEC_USE_COUNT; - return 0; + goto egress; default: break; @@ -432,16 +441,15 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask) break; } if (!write_mask) { - if (alpha_fp_emul(trigger_pc)) { - /* re-execute insns in trap-shadow: */ - regs->pc = trigger_pc + 4; - MOD_DEC_USE_COUNT; - return 1; - } - break; + /* Re-execute insns in the trap-shadow. */ + regs->pc = trigger_pc + 4; + no_signal = alpha_fp_emul(trigger_pc); + goto egress; } trigger_pc -= 4; } + +egress: MOD_DEC_USE_COUNT; - return 0; + return no_signal; } |