aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/nwfpe/fpa11_cprt.c
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@rpsys.net>2005-08-03 19:49:17 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-08-03 19:49:17 +0100
commitf148af2593ef76ac705d1cc6abe48f455c9912cc (patch)
treecd1e0b0959624234ca3489df8888434ffea5050e /arch/arm/nwfpe/fpa11_cprt.c
parent1fcf844861eb08ee05e05dba13b5436f2f2e29ed (diff)
downloadkernel_samsung_smdk4412-f148af2593ef76ac705d1cc6abe48f455c9912cc.zip
kernel_samsung_smdk4412-f148af2593ef76ac705d1cc6abe48f455c9912cc.tar.gz
kernel_samsung_smdk4412-f148af2593ef76ac705d1cc6abe48f455c9912cc.tar.bz2
[PATCH] ARM: 2837/2: Re: ARM: Make NWFPE preempt safe
Patch from Richard Purdie NWFPE used global variables which meant it wasn't safe for use with preemptive kernels. This patch removes them and communicates the information between functions in a preempt safe manner. Generation of some exceptions was broken and this has also been corrected. Tests with glibc's maths test suite show no change in the results before/after this patch. Signed-off-by: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/nwfpe/fpa11_cprt.c')
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c
index db01fbc..adf8d30 100644
--- a/arch/arm/nwfpe/fpa11_cprt.c
+++ b/arch/arm/nwfpe/fpa11_cprt.c
@@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80);
extern flag float64_is_nan(float64);
extern flag float32_is_nan(float32);
-void SetRoundingMode(const unsigned int opcode);
-
unsigned int PerformFLT(const unsigned int opcode);
unsigned int PerformFIX(const unsigned int opcode);
@@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode)
unsigned int PerformFLT(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
- SetRoundingMode(opcode);
- SetRoundingPrecision(opcode);
+ struct roundingData roundData;
+
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
{
fpa11->fType[getFn(opcode)] = typeSingle;
- fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
+ fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
}
break;
@@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode)
return 0;
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
return 1;
}
@@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int Fn = getFm(opcode);
+ struct roundingData roundData;
- SetRoundingMode(opcode);
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
switch (fpa11->fType[Fn]) {
case typeSingle:
{
- writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
+ writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
}
break;
case typeDouble:
{
- writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
+ writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
}
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
{
- writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
+ writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
}
break;
#endif
@@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode)
return 0;
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
return 1;
}