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

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)