patch-2.3.99-pre3 linux/arch/alpha/math-emu/math.c
Next file: linux/arch/arm/config.in
Previous file: linux/arch/alpha/kernel/sys_jensen.c
Back to the patch index
Back to the overall index
- Lines: 145
- Date:
Tue Mar 21 10:47:06 2000
- Orig file:
v2.3.99-pre2/linux/arch/alpha/math-emu/math.c
- Orig date:
Tue Dec 7 09:32:40 1999
diff -u --recursive --new-file v2.3.99-pre2/linux/arch/alpha/math-emu/math.c linux/arch/alpha/math-emu/math.c
@@ -160,8 +160,7 @@
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 @@
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 @@
}
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 @@
}
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 @@
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:
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 @@
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 @@
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 @@
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;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)