summaryrefslogtreecommitdiffstats
path: root/arch/i386/math-emu
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-29 01:41:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-29 01:41:54 +0000
commitf969d69ba9f952e5bdd38278e25e26a3e4a61a70 (patch)
treeb3530d803df59d726afaabebc6626987dee1ca05 /arch/i386/math-emu
parenta10ce7ef2066b455d69187643ddf2073bfc4db24 (diff)
Merge with 2.3.27.
Diffstat (limited to 'arch/i386/math-emu')
-rw-r--r--arch/i386/math-emu/README11
-rw-r--r--arch/i386/math-emu/fpu_trig.c35
-rw-r--r--arch/i386/math-emu/poly.h25
-rw-r--r--arch/i386/math-emu/poly_sin.c22
-rw-r--r--arch/i386/math-emu/poly_tan.c16
-rw-r--r--arch/i386/math-emu/reg_round.S2
-rw-r--r--arch/i386/math-emu/version.h6
7 files changed, 73 insertions, 44 deletions
diff --git a/arch/i386/math-emu/README b/arch/i386/math-emu/README
index 04434b618..e6235491d 100644
--- a/arch/i386/math-emu/README
+++ b/arch/i386/math-emu/README
@@ -1,9 +1,9 @@
+---------------------------------------------------------------------------+
| wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. |
| |
- | Copyright (C) 1992,1993,1994,1995,1996,1997 |
+ | Copyright (C) 1992,1993,1994,1995,1996,1997,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
- | Australia. E-mail billm@suburbia.net |
+ | Australia. E-mail billm@melbpc.org.au |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License version 2 as |
@@ -42,14 +42,15 @@ but is very close. See "Limitations" later in this file for a list of
some differences.
Please report bugs, etc to me at:
- billm@suburbia.net
+ billm@melbpc.org.au
+or b.metzenthen@medoto.unimelb.edu.au
For more information on the emulator and on floating point topics, see
my web pages, currently at http://www.suburbia.net/~billm/
--Bill Metzenthen
- December 1997
+ December 1999
----------------------- Internals of wm-FPU-emu -----------------------
@@ -98,7 +99,7 @@ form of re-entrancy which is required by the Linux kernel.
----------------------- Limitations of wm-FPU-emu -----------------------
There are a number of differences between the current wm-FPU-emu
-(version 2.00) and the 80486 FPU (apart from bugs). The differences
+(version 2.01) and the 80486 FPU (apart from bugs). The differences
are fewer than those which applied to the 1.xx series of the emulator.
Some of the more important differences are listed below:
diff --git a/arch/i386/math-emu/fpu_trig.c b/arch/i386/math-emu/fpu_trig.c
index 57a902162..30b72910e 100644
--- a/arch/i386/math-emu/fpu_trig.c
+++ b/arch/i386/math-emu/fpu_trig.c
@@ -3,9 +3,9 @@
| |
| Implementation of the FPU "transcendental" functions. |
| |
- | Copyright (C) 1992,1993,1994,1997 |
+ | Copyright (C) 1992,1993,1994,1997,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
- | Australia. E-mail billm@suburbia.net |
+ | Australia. E-mail billm@melbpc.org.au |
| |
| |
+---------------------------------------------------------------------------*/
@@ -85,7 +85,8 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
FPU_normalize(&tmp);
tmptag =
FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, SIGN_POS,
- exponent16(&CONST_PI2extra) + exponent16(&tmp));
+ exponent(&CONST_PI2extra) + exponent(&tmp));
+ setsign(&tmp, getsign(&CONST_PI2extra));
st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION);
if ( signnegative(st0_ptr) )
{
@@ -117,7 +118,8 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
FPU_normalize(&tmp); /* This must return TAG_Valid */
tmptag = FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION,
SIGN_POS,
- exponent16(&CONST_PI2extra) + exponent16(&tmp));
+ exponent(&CONST_PI2extra) + exponent(&tmp));
+ setsign(&tmp, getsign(&CONST_PI2extra));
st0_tag = FPU_sub(LOADED|(tmptag & 0x0f), (int)&tmp,
FULL_PRECISION);
if ( (exponent(st0_ptr) == exponent(&CONST_PI2)) &&
@@ -827,18 +829,29 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y,
unsigned long long st1,
unsigned long long q, int n)
{
+ int dummy;
unsigned long long x;
x = st0 << n;
/* Do the required multiplication and subtraction in the one operation */
- asm volatile ("movl %2,%%eax; mull %4; subl %%eax,%0; sbbl %%edx,%1;
- movl %3,%%eax; mull %4; subl %%eax,%1;
- movl %2,%%eax; mull %5; subl %%eax,%1;"
- :"=m" (x), "=m" (((unsigned *)&x)[1])
- :"m" (st1),"m" (((unsigned *)&st1)[1]),
- "m" (q),"m" (((unsigned *)&q)[1])
- :"%ax","%dx");
+
+ /* lsw x -= lsw st1 * lsw q */
+ asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1"
+ :"=m" (((unsigned *)&x)[0]), "=m" (((unsigned *)&x)[1]),
+ "=a" (dummy)
+ :"2" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[0])
+ :"%dx");
+ /* msw x -= msw st1 * lsw q */
+ asm volatile ("mull %3; subl %%eax,%0"
+ :"=m" (((unsigned *)&x)[1]), "=a" (dummy)
+ :"1" (((unsigned *)&st1)[1]), "m" (((unsigned *)&q)[0])
+ :"%dx");
+ /* msw x -= lsw st1 * msw q */
+ asm volatile ("mull %3; subl %%eax,%0"
+ :"=m" (((unsigned *)&x)[1]), "=a" (dummy)
+ :"1" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[1])
+ :"%dx");
*y = x;
}
diff --git a/arch/i386/math-emu/poly.h b/arch/i386/math-emu/poly.h
index 37ddfa0ef..5cfce7baf 100644
--- a/arch/i386/math-emu/poly.h
+++ b/arch/i386/math-emu/poly.h
@@ -3,9 +3,9 @@
| |
| Header file for the FPU-emu poly*.c source files. |
| |
- | Copyright (C) 1994 |
+ | Copyright (C) 1994,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
- | Australia. E-mail billm@vaxc.cc.monash.edu.au |
+ | Australia. E-mail billm@melbpc.org.au |
| |
| Declarations and definitions for functions operating on Xsig (12-byte |
| extended-significand) quantities. |
@@ -55,15 +55,20 @@ asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest);
actually be in-line.
*/
-/* Multiply two fixed-point 32 bit numbers. */
-extern inline void mul_32_32(const unsigned long arg1,
- const unsigned long arg2,
- unsigned long *out)
+/* Multiply two fixed-point 32 bit numbers, producing a 32 bit result.
+ The answer is the ms word of the product. */
+/* Some versions of gcc make it difficult to stop eax from being clobbered.
+ Merely specifying that it is used doesn't work...
+ */
+extern inline unsigned long mul_32_32(const unsigned long arg1,
+ const unsigned long arg2)
{
- asm volatile ("movl %1,%%eax; mull %2; movl %%edx,%0" \
- :"=g" (*out) \
- :"g" (arg1), "g" (arg2) \
- :"ax","dx");
+ int retval;
+ asm volatile ("mull %2; movl %%edx,%%eax" \
+ :"=a" (retval) \
+ :"0" (arg1), "g" (arg2) \
+ :"dx");
+ return retval;
}
diff --git a/arch/i386/math-emu/poly_sin.c b/arch/i386/math-emu/poly_sin.c
index f03df4c00..a83b51206 100644
--- a/arch/i386/math-emu/poly_sin.c
+++ b/arch/i386/math-emu/poly_sin.c
@@ -4,9 +4,9 @@
| Computation of an approximation of the sin function and the cosine |
| function by a polynomial. |
| |
- | Copyright (C) 1992,1993,1994,1997 |
+ | Copyright (C) 1992,1993,1994,1997,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
- | E-mail billm@suburbia.net |
+ | E-mail billm@melbpc.org.au |
| |
| |
+---------------------------------------------------------------------------*/
@@ -132,6 +132,9 @@ void poly_sine(FPU_REG *st0_ptr)
}
/* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
fixed_arg = 0x921fb54442d18469LL - fixed_arg;
+ /* There is a special case which arises due to rounding, to fix here. */
+ if ( fixed_arg == 0xffffffffffffffffLL )
+ fixed_arg = 0;
XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0;
mul64_Xsig(&argSqrd, &fixed_arg);
@@ -172,10 +175,9 @@ void poly_sine(FPU_REG *st0_ptr)
if ( argSqrd.msw & 0xffc00000 )
{
/* Get about 32 bit precision in these: */
- mul_32_32(0x898cc517, argSqrd.msw, &adj);
- fix_up -= adj/6;
+ fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6;
}
- mul_32_32(fix_up, LL_MSW(fixed_arg), &fix_up);
+ fix_up = mul_32_32(fix_up, LL_MSW(fixed_arg));
adj = accumulator.lsw; /* temp save */
accumulator.lsw -= fix_up;
@@ -211,7 +213,6 @@ void poly_cos(FPU_REG *st0_ptr)
FPU_REG result;
long int exponent, exp2, echange;
Xsig accumulator, argSqrd, fix_up, argTo4;
- unsigned long adj;
unsigned long long fixed_arg;
#ifdef PARANOID
@@ -300,6 +301,9 @@ void poly_cos(FPU_REG *st0_ptr)
}
/* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
fixed_arg = 0x921fb54442d18469LL - fixed_arg;
+ /* There is a special case which arises due to rounding, to fix here. */
+ if ( fixed_arg == 0xffffffffffffffffLL )
+ fixed_arg = 0;
exponent = -1;
exp2 = -1;
@@ -363,10 +367,8 @@ void poly_cos(FPU_REG *st0_ptr)
if ( argSqrd.msw & 0xffc00000 )
{
/* Get about 32 bit precision in these: */
- mul_32_32(0x898cc517, argSqrd.msw, &adj);
- fix_up.msw -= adj/2;
- mul_32_32(0x898cc517, argTo4.msw, &adj);
- fix_up.msw += adj/24;
+ fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2;
+ fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24;
}
exp2 += norm_Xsig(&accumulator);
diff --git a/arch/i386/math-emu/poly_tan.c b/arch/i386/math-emu/poly_tan.c
index 1743d6f0f..13a32b9fc 100644
--- a/arch/i386/math-emu/poly_tan.c
+++ b/arch/i386/math-emu/poly_tan.c
@@ -3,9 +3,9 @@
| |
| Compute the tan of a FPU_REG, using a polynomial approximation. |
| |
- | Copyright (C) 1992,1993,1994,1997 |
+ | Copyright (C) 1992,1993,1994,1997,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
- | Australia. E-mail billm@suburbia.net |
+ | Australia. E-mail billm@melbpc.org.au |
| |
| |
+---------------------------------------------------------------------------*/
@@ -84,6 +84,14 @@ void poly_tan(FPU_REG *st0_ptr)
}
/* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
XSIG_LL(accum) = 0x921fb54442d18469LL - XSIG_LL(accum);
+ /* This is a special case which arises due to rounding. */
+ if ( XSIG_LL(accum) == 0xffffffffffffffffLL )
+ {
+ FPU_settag0(TAG_Valid);
+ significand(st0_ptr) = 0x8a51e04daabda360LL;
+ setexponent16(st0_ptr, 0x41 + EXTENDED_Ebias | SIGN_Negative);
+ return;
+ }
argSignif.lsw = accum.lsw;
XSIG_LL(argSignif) = XSIG_LL(accum);
@@ -177,11 +185,11 @@ void poly_tan(FPU_REG *st0_ptr)
else if ( exponent > -30 )
{
adj = accum.msw >> -(exponent+1); /* tan */
- mul_32_32(adj, adj, &adj); /* tan^2 */
+ adj = mul_32_32(adj, adj); /* tan^2 */
}
else
adj = 0;
- mul_32_32(0x898cc517, adj, &adj); /* delta * tan^2 */
+ adj = mul_32_32(0x898cc517, adj); /* delta * tan^2 */
fix_up.msw += adj;
if ( !(fix_up.msw & 0x80000000) ) /* did fix_up overflow ? */
diff --git a/arch/i386/math-emu/reg_round.S b/arch/i386/math-emu/reg_round.S
index f6c11eb7d..ba00f5c5a 100644
--- a/arch/i386/math-emu/reg_round.S
+++ b/arch/i386/math-emu/reg_round.S
@@ -365,7 +365,7 @@ LRound_nearest_64:
jne LDo_64_round_up
/* Now test for round-to-even */
- testb $1,%ebx
+ testb $1,%bl
jz LCheck_truncate_64
LDo_64_round_up:
diff --git a/arch/i386/math-emu/version.h b/arch/i386/math-emu/version.h
index 2f819087d..a0d73a1d2 100644
--- a/arch/i386/math-emu/version.h
+++ b/arch/i386/math-emu/version.h
@@ -2,11 +2,11 @@
| version.h |
| |
| |
- | Copyright (C) 1992,1993,1994,1996,1997 |
+ | Copyright (C) 1992,1993,1994,1996,1997,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
- | E-mail billm@suburbia.net |
+ | E-mail billm@melbpc.org.au |
| |
| |
+---------------------------------------------------------------------------*/
-#define FPU_VERSION "wm-FPU-emu version 2.00"
+#define FPU_VERSION "wm-FPU-emu version 2.01"