summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/math-emu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/math-emu')
-rw-r--r--arch/sparc64/math-emu/fabsq.c2
-rw-r--r--arch/sparc64/math-emu/faddd.c3
-rw-r--r--arch/sparc64/math-emu/faddq.c3
-rw-r--r--arch/sparc64/math-emu/fadds.c3
-rw-r--r--arch/sparc64/math-emu/fcmpeq.c2
-rw-r--r--arch/sparc64/math-emu/fcmpq.c2
-rw-r--r--arch/sparc64/math-emu/fdivd.c10
-rw-r--r--arch/sparc64/math-emu/fdivq.c10
-rw-r--r--arch/sparc64/math-emu/fdivs.c11
-rw-r--r--arch/sparc64/math-emu/fdmulq.c3
-rw-r--r--arch/sparc64/math-emu/fdtoi.c2
-rw-r--r--arch/sparc64/math-emu/fdtoq.c3
-rw-r--r--arch/sparc64/math-emu/fdtos.c3
-rw-r--r--arch/sparc64/math-emu/fdtox.c2
-rw-r--r--arch/sparc64/math-emu/fitoq.c3
-rw-r--r--arch/sparc64/math-emu/fmuld.c3
-rw-r--r--arch/sparc64/math-emu/fmulq.c3
-rw-r--r--arch/sparc64/math-emu/fmuls.c3
-rw-r--r--arch/sparc64/math-emu/fnegq.c2
-rw-r--r--arch/sparc64/math-emu/fqtod.c3
-rw-r--r--arch/sparc64/math-emu/fqtoi.c2
-rw-r--r--arch/sparc64/math-emu/fqtos.c3
-rw-r--r--arch/sparc64/math-emu/fqtox.c2
-rw-r--r--arch/sparc64/math-emu/fsmuld.c3
-rw-r--r--arch/sparc64/math-emu/fsqrtd.c3
-rw-r--r--arch/sparc64/math-emu/fsqrtq.c3
-rw-r--r--arch/sparc64/math-emu/fsqrts.c3
-rw-r--r--arch/sparc64/math-emu/fstod.c3
-rw-r--r--arch/sparc64/math-emu/fstoi.c2
-rw-r--r--arch/sparc64/math-emu/fstoq.c3
-rw-r--r--arch/sparc64/math-emu/fstox.c2
-rw-r--r--arch/sparc64/math-emu/fsubd.c3
-rw-r--r--arch/sparc64/math-emu/fsubq.c3
-rw-r--r--arch/sparc64/math-emu/fsubs.c3
-rw-r--r--arch/sparc64/math-emu/fxtoq.c3
-rw-r--r--arch/sparc64/math-emu/math.c97
-rw-r--r--arch/sparc64/math-emu/op-2.h8
-rw-r--r--arch/sparc64/math-emu/op-common.h28
-rw-r--r--arch/sparc64/math-emu/sfp-machine.h130
-rw-r--r--arch/sparc64/math-emu/soft-fp.h35
40 files changed, 274 insertions, 141 deletions
diff --git a/arch/sparc64/math-emu/fabsq.c b/arch/sparc64/math-emu/fabsq.c
index e01b02046..62a7e1839 100644
--- a/arch/sparc64/math-emu/fabsq.c
+++ b/arch/sparc64/math-emu/fabsq.c
@@ -2,5 +2,5 @@ int FABSQ(unsigned long *rd, unsigned long *rs2)
{
rd[0] = rs2[0] & 0x7fffffffffffffffUL;
rd[1] = rs2[1];
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/faddd.c b/arch/sparc64/math-emu/faddd.c
index 69b9f7c24..7c755b872 100644
--- a/arch/sparc64/math-emu/faddd.c
+++ b/arch/sparc64/math-emu/faddd.c
@@ -8,6 +8,5 @@ int FADDD(void *rd, void *rs2, void *rs1)
__FP_UNPACK_D(A, rs1);
__FP_UNPACK_D(B, rs2);
FP_ADD_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/faddq.c b/arch/sparc64/math-emu/faddq.c
index 07245eb95..052c6c9cd 100644
--- a/arch/sparc64/math-emu/faddq.c
+++ b/arch/sparc64/math-emu/faddq.c
@@ -8,6 +8,5 @@ int FADDQ(void *rd, void *rs2, void *rs1)
__FP_UNPACK_Q(A, rs1);
__FP_UNPACK_Q(B, rs2);
FP_ADD_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fadds.c b/arch/sparc64/math-emu/fadds.c
index 71295ae47..35bb2030e 100644
--- a/arch/sparc64/math-emu/fadds.c
+++ b/arch/sparc64/math-emu/fadds.c
@@ -8,6 +8,5 @@ int FADDS(void *rd, void *rs2, void *rs1)
__FP_UNPACK_S(A, rs1);
__FP_UNPACK_S(B, rs2);
FP_ADD_S(R, A, B);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
}
diff --git a/arch/sparc64/math-emu/fcmpeq.c b/arch/sparc64/math-emu/fcmpeq.c
index e74b1b06b..e99864f55 100644
--- a/arch/sparc64/math-emu/fcmpeq.c
+++ b/arch/sparc64/math-emu/fcmpeq.c
@@ -21,5 +21,5 @@ int FCMPEQ(void *rd, void *rs2, void *rs1)
case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
}
*(unsigned long *)rd = fsr;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fcmpq.c b/arch/sparc64/math-emu/fcmpq.c
index 9effefb1f..54ec4492f 100644
--- a/arch/sparc64/math-emu/fcmpq.c
+++ b/arch/sparc64/math-emu/fcmpq.c
@@ -21,5 +21,5 @@ int FCMPQ(void *rd, void *rs2, void *rs1)
case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
}
*(unsigned long *)rd = fsr;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fdivd.c b/arch/sparc64/math-emu/fdivd.c
index 2984290fc..a19dbdd78 100644
--- a/arch/sparc64/math-emu/fdivd.c
+++ b/arch/sparc64/math-emu/fdivd.c
@@ -4,10 +4,16 @@
int FDIVD(void *rd, void *rs2, void *rs1)
{
FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ int ret = 0;
__FP_UNPACK_D(A, rs1);
__FP_UNPACK_D(B, rs2);
+ if(B_c == FP_CLS_ZERO &&
+ A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if(__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
FP_DIV_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return (ret | __FP_PACK_D(rd, R));
}
diff --git a/arch/sparc64/math-emu/fdivq.c b/arch/sparc64/math-emu/fdivq.c
index e5858c0af..9bc0987f5 100644
--- a/arch/sparc64/math-emu/fdivq.c
+++ b/arch/sparc64/math-emu/fdivq.c
@@ -4,10 +4,16 @@
int FDIVQ(void *rd, void *rs2, void *rs1)
{
FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ int ret;
__FP_UNPACK_Q(A, rs1);
__FP_UNPACK_Q(B, rs2);
+ if(B_c == FP_CLS_ZERO &&
+ A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if(__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
FP_DIV_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return (ret | __FP_PACK_Q(rd, R));
}
diff --git a/arch/sparc64/math-emu/fdivs.c b/arch/sparc64/math-emu/fdivs.c
index 704f218c9..41095dc4c 100644
--- a/arch/sparc64/math-emu/fdivs.c
+++ b/arch/sparc64/math-emu/fdivs.c
@@ -4,10 +4,17 @@
int FDIVS(void *rd, void *rs2, void *rs1)
{
FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ int ret = 0;
__FP_UNPACK_S(A, rs1);
__FP_UNPACK_S(B, rs2);
+ if(B_c == FP_CLS_ZERO &&
+ A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if(__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
FP_DIV_S(R, A, B);
- __FP_PACK_S(rd, R);
- return 1;
+ return (ret | __FP_PACK_S(rd, R));
}
+
diff --git a/arch/sparc64/math-emu/fdmulq.c b/arch/sparc64/math-emu/fdmulq.c
index 7862a0039..4d4b5916a 100644
--- a/arch/sparc64/math-emu/fdmulq.c
+++ b/arch/sparc64/math-emu/fdmulq.c
@@ -11,6 +11,5 @@ int FDMULQ(void *rd, void *rs2, void *rs1)
__FP_UNPACK_D(IN, rs2);
FP_CONV(Q,D,2,1,B,IN);
FP_MUL_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fdtoi.c b/arch/sparc64/math-emu/fdtoi.c
index f7ba0f1f2..1b12a6395 100644
--- a/arch/sparc64/math-emu/fdtoi.c
+++ b/arch/sparc64/math-emu/fdtoi.c
@@ -9,5 +9,5 @@ int FDTOI(unsigned *rd, void *rs2)
__FP_UNPACK_D(A, rs2);
FP_TO_INT_D(r, A, 32, 1);
*rd = r;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fdtoq.c b/arch/sparc64/math-emu/fdtoq.c
index 42e4009c6..b37b31198 100644
--- a/arch/sparc64/math-emu/fdtoq.c
+++ b/arch/sparc64/math-emu/fdtoq.c
@@ -8,6 +8,5 @@ int FDTOQ(void *rd, void *rs2)
__FP_UNPACK_D(A, rs2);
FP_CONV(Q,D,2,1,R,A);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fdtos.c b/arch/sparc64/math-emu/fdtos.c
index fb7fede54..ae9f382ed 100644
--- a/arch/sparc64/math-emu/fdtos.c
+++ b/arch/sparc64/math-emu/fdtos.c
@@ -8,6 +8,5 @@ int FDTOS(void *rd, void *rs2)
__FP_UNPACK_D(A, rs2);
FP_CONV(S,D,1,1,R,A);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
}
diff --git a/arch/sparc64/math-emu/fdtox.c b/arch/sparc64/math-emu/fdtox.c
index 1a93b585c..062651a47 100644
--- a/arch/sparc64/math-emu/fdtox.c
+++ b/arch/sparc64/math-emu/fdtox.c
@@ -9,5 +9,5 @@ int FDTOX(unsigned long *rd, void *rs2)
__FP_UNPACK_D(A, rs2);
FP_TO_INT_D(r, A, 64, 1);
*rd = r;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fitoq.c b/arch/sparc64/math-emu/fitoq.c
index 5d08bbe18..68ba2839b 100644
--- a/arch/sparc64/math-emu/fitoq.c
+++ b/arch/sparc64/math-emu/fitoq.c
@@ -7,6 +7,5 @@ int FITOQ(void *rd, void *rs2)
int a = *(int *)rs2;
FP_FROM_INT_Q(R, a, 32, int);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fmuld.c b/arch/sparc64/math-emu/fmuld.c
index 04d1f38df..707bb45c1 100644
--- a/arch/sparc64/math-emu/fmuld.c
+++ b/arch/sparc64/math-emu/fmuld.c
@@ -8,6 +8,5 @@ int FMULD(void *rd, void *rs2, void *rs1)
__FP_UNPACK_D(A, rs1);
__FP_UNPACK_D(B, rs2);
FP_MUL_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/fmulq.c b/arch/sparc64/math-emu/fmulq.c
index 4d099be6f..94400d023 100644
--- a/arch/sparc64/math-emu/fmulq.c
+++ b/arch/sparc64/math-emu/fmulq.c
@@ -8,6 +8,5 @@ int FMULQ(void *rd, void *rs2, void *rs1)
__FP_UNPACK_Q(A, rs1);
__FP_UNPACK_Q(B, rs2);
FP_MUL_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fmuls.c b/arch/sparc64/math-emu/fmuls.c
index 8a358d030..b16509964 100644
--- a/arch/sparc64/math-emu/fmuls.c
+++ b/arch/sparc64/math-emu/fmuls.c
@@ -8,6 +8,5 @@ int FMULS(void *rd, void *rs2, void *rs1)
__FP_UNPACK_S(A, rs1);
__FP_UNPACK_S(B, rs2);
FP_MUL_S(R, A, B);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
}
diff --git a/arch/sparc64/math-emu/fnegq.c b/arch/sparc64/math-emu/fnegq.c
index 2251e3308..745020ee3 100644
--- a/arch/sparc64/math-emu/fnegq.c
+++ b/arch/sparc64/math-emu/fnegq.c
@@ -2,6 +2,6 @@ int FNEGQ(unsigned long *rd, unsigned long *rs2)
{
rd[0] = rs2[0] ^ 0x8000000000000000UL;
rd[1] = rs2[1];
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fqtod.c b/arch/sparc64/math-emu/fqtod.c
index 1f9161999..29e41cf6a 100644
--- a/arch/sparc64/math-emu/fqtod.c
+++ b/arch/sparc64/math-emu/fqtod.c
@@ -8,6 +8,5 @@ int FQTOD(void *rd, void *rs2)
__FP_UNPACK_Q(A, rs2);
FP_CONV(D,Q,1,2,R,A);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/fqtoi.c b/arch/sparc64/math-emu/fqtoi.c
index 06d67ff81..1bb213f19 100644
--- a/arch/sparc64/math-emu/fqtoi.c
+++ b/arch/sparc64/math-emu/fqtoi.c
@@ -9,5 +9,5 @@ int FQTOI(unsigned *rd, void *rs2)
__FP_UNPACK_Q(A, rs2);
FP_TO_INT_Q(r, A, 32, 1);
*rd = r;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fqtos.c b/arch/sparc64/math-emu/fqtos.c
index 833f10618..382912d11 100644
--- a/arch/sparc64/math-emu/fqtos.c
+++ b/arch/sparc64/math-emu/fqtos.c
@@ -8,6 +8,5 @@ int FQTOS(void *rd, void *rs2)
__FP_UNPACK_Q(A, rs2);
FP_CONV(S,Q,1,2,R,A);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
}
diff --git a/arch/sparc64/math-emu/fqtox.c b/arch/sparc64/math-emu/fqtox.c
index 6cdabc8cd..484ca6900 100644
--- a/arch/sparc64/math-emu/fqtox.c
+++ b/arch/sparc64/math-emu/fqtox.c
@@ -9,5 +9,5 @@ int FQTOX(unsigned long *rd, void *rs2)
__FP_UNPACK_Q(A, rs2);
FP_TO_INT_Q(r, A, 64, 1);
*rd = r;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fsmuld.c b/arch/sparc64/math-emu/fsmuld.c
index 1a0eefd06..b6bf61b0f 100644
--- a/arch/sparc64/math-emu/fsmuld.c
+++ b/arch/sparc64/math-emu/fsmuld.c
@@ -11,6 +11,5 @@ int FSMULD(void *rd, void *rs2, void *rs1)
__FP_UNPACK_S(IN, rs2);
FP_CONV(D,S,1,1,B,IN);
FP_MUL_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/fsqrtd.c b/arch/sparc64/math-emu/fsqrtd.c
index 59f5e3bf3..b022f7d37 100644
--- a/arch/sparc64/math-emu/fsqrtd.c
+++ b/arch/sparc64/math-emu/fsqrtd.c
@@ -7,6 +7,5 @@ int FSQRTD(void *rd, void *rs2)
__FP_UNPACK_D(A, rs2);
FP_SQRT_D(R, A);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/fsqrtq.c b/arch/sparc64/math-emu/fsqrtq.c
index 8f84aa850..7e620079f 100644
--- a/arch/sparc64/math-emu/fsqrtq.c
+++ b/arch/sparc64/math-emu/fsqrtq.c
@@ -7,6 +7,5 @@ int FSQRTQ(void *rd, void *rs2)
__FP_UNPACK_Q(A, rs2);
FP_SQRT_Q(R, A);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fsqrts.c b/arch/sparc64/math-emu/fsqrts.c
index d57cdc98e..62ff0b782 100644
--- a/arch/sparc64/math-emu/fsqrts.c
+++ b/arch/sparc64/math-emu/fsqrts.c
@@ -7,6 +7,5 @@ int FSQRTS(void *rd, void *rs2)
__FP_UNPACK_S(A, rs2);
FP_SQRT_S(R, A);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
}
diff --git a/arch/sparc64/math-emu/fstod.c b/arch/sparc64/math-emu/fstod.c
index 60f1bc8a4..91935f78e 100644
--- a/arch/sparc64/math-emu/fstod.c
+++ b/arch/sparc64/math-emu/fstod.c
@@ -8,6 +8,5 @@ int FSTOD(void *rd, void *rs2)
__FP_UNPACK_S(A, rs2);
FP_CONV(D,S,1,1,R,A);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/fstoi.c b/arch/sparc64/math-emu/fstoi.c
index 4adc7d170..5ff3854cc 100644
--- a/arch/sparc64/math-emu/fstoi.c
+++ b/arch/sparc64/math-emu/fstoi.c
@@ -9,5 +9,5 @@ int FSTOI(unsigned *rd, void *rs2)
__FP_UNPACK_S(A, rs2);
FP_TO_INT_S(r, A, 32, 1);
*rd = r;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fstoq.c b/arch/sparc64/math-emu/fstoq.c
index 06313a77f..1a56e0055 100644
--- a/arch/sparc64/math-emu/fstoq.c
+++ b/arch/sparc64/math-emu/fstoq.c
@@ -8,6 +8,5 @@ int FSTOQ(void *rd, void *rs2)
__FP_UNPACK_S(A, rs2);
FP_CONV(Q,S,2,1,R,A);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fstox.c b/arch/sparc64/math-emu/fstox.c
index 555fba2ee..fa2135f8b 100644
--- a/arch/sparc64/math-emu/fstox.c
+++ b/arch/sparc64/math-emu/fstox.c
@@ -9,5 +9,5 @@ int FSTOX(unsigned long *rd, void *rs2)
__FP_UNPACK_S(A, rs2);
FP_TO_INT_S(r, A, 64, 1);
*rd = r;
- return 1;
+ return 0;
}
diff --git a/arch/sparc64/math-emu/fsubd.c b/arch/sparc64/math-emu/fsubd.c
index b0f451b32..bbd11c611 100644
--- a/arch/sparc64/math-emu/fsubd.c
+++ b/arch/sparc64/math-emu/fsubd.c
@@ -10,6 +10,5 @@ int FSUBD(void *rd, void *rs2, void *rs1)
if (B_c != FP_CLS_NAN)
B_s ^= 1;
FP_ADD_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
}
diff --git a/arch/sparc64/math-emu/fsubq.c b/arch/sparc64/math-emu/fsubq.c
index ef006a540..d5cc260cf 100644
--- a/arch/sparc64/math-emu/fsubq.c
+++ b/arch/sparc64/math-emu/fsubq.c
@@ -10,6 +10,5 @@ int FSUBQ(void *rd, void *rs2, void *rs1)
if (B_c != FP_CLS_NAN)
B_s ^= 1;
FP_ADD_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/fsubs.c b/arch/sparc64/math-emu/fsubs.c
index d060f095a..ff8fa12b1 100644
--- a/arch/sparc64/math-emu/fsubs.c
+++ b/arch/sparc64/math-emu/fsubs.c
@@ -10,6 +10,5 @@ int FSUBS(void *rd, void *rs2, void *rs1)
if (B_c != FP_CLS_NAN)
B_s ^= 1;
FP_ADD_S(R, A, B);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
}
diff --git a/arch/sparc64/math-emu/fxtoq.c b/arch/sparc64/math-emu/fxtoq.c
index 7c2f7df48..411e51571 100644
--- a/arch/sparc64/math-emu/fxtoq.c
+++ b/arch/sparc64/math-emu/fxtoq.c
@@ -7,6 +7,5 @@ int FXTOQ(void *rd, void *rs2)
long a = *(long *)rs2;
FP_FROM_INT_Q(R, a, 64, long);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
}
diff --git a/arch/sparc64/math-emu/math.c b/arch/sparc64/math-emu/math.c
index 5a71804b9..f4493e224 100644
--- a/arch/sparc64/math-emu/math.c
+++ b/arch/sparc64/math-emu/math.c
@@ -1,7 +1,8 @@
-/* $Id: math.c,v 1.5 1998/06/12 14:54:27 jj Exp $
+/* $Id: math.c,v 1.7 1999/02/10 14:16:26 davem Exp $
* arch/sparc64/math-emu/math.c
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
*
* Emulation routines originate from soft-fp package, which is part
* of glibc and has appropriate copyrights in it.
@@ -14,6 +15,8 @@
#include <asm/ptrace.h>
#include <asm/uaccess.h>
+#include "soft-fp.h"
+
#define FLOATFUNC(x) extern int x(void *,void *,void *);
FLOATFUNC(FMOVQ)
@@ -54,6 +57,91 @@ FLOATFUNC(FSTOD)
FLOATFUNC(FSTOI)
FLOATFUNC(FDTOI)
+#define FSR_TEM_SHIFT 23UL
+#define FSR_TEM_MASK (0x1fUL << FSR_TEM_SHIFT)
+#define FSR_AEXC_SHIFT 5UL
+#define FSR_AEXC_MASK (0x1fUL << FSR_AEXC_SHIFT)
+#define FSR_CEXC_SHIFT 0UL
+#define FSR_CEXC_MASK (0x1fUL << FSR_CEXC_SHIFT)
+
+/* All routines returning an exception to raise should detect
+ * such exceptions _before_ rounding to be consistant with
+ * the behavior of the hardware in the implemented cases
+ * (and thus with the recommendations in the V9 architecture
+ * manual).
+ *
+ * We return 0 if a SIGFPE should be sent, 1 otherwise.
+ */
+static int record_exception(struct pt_regs *regs, int eflag)
+{
+ u64 fsr = current->tss.xfsr[0];
+ int would_trap;
+
+ /* Determine if this exception would have generated a trap. */
+ would_trap = (fsr & ((long)eflag << FSR_TEM_SHIFT)) != 0UL;
+
+ /* If trapping, we only want to signal one bit. */
+ if(would_trap != 0) {
+ eflag &= ((fsr & FSR_TEM_MASK) >> FSR_TEM_SHIFT);
+ if((eflag & (eflag - 1)) != 0) {
+ if(eflag & EFLAG_INVALID)
+ eflag = EFLAG_INVALID;
+ else if(eflag & EFLAG_DIVZERO)
+ eflag = EFLAG_DIVZERO;
+ else if(eflag & EFLAG_INEXACT)
+ eflag = EFLAG_INEXACT;
+ }
+ }
+
+ /* Set CEXC, here are the rules:
+ *
+ * 1) In general all FPU ops will set one and only one
+ * bit in the CEXC field, this is always the case
+ * when the IEEE exception trap is enabled in TEM.
+ *
+ * 2) As a special case, if an overflow or underflow
+ * is being signalled, AND the trap is not enabled
+ * in TEM, then the inexact field shall also be set.
+ */
+ fsr &= ~(FSR_CEXC_MASK);
+ if(would_trap ||
+ (eflag & (EFLAG_OVERFLOW | EFLAG_UNDERFLOW)) == 0) {
+ fsr |= ((long)eflag << FSR_CEXC_SHIFT);
+ } else {
+ fsr |= (((long)eflag << FSR_CEXC_SHIFT) |
+ (EFLAG_INEXACT << FSR_CEXC_SHIFT));
+ }
+
+ /* Set the AEXC field, rules are:
+ *
+ * 1) If a trap would not be generated, the
+ * CEXC just generated is OR'd into the
+ * existing value of AEXC.
+ *
+ * 2) When a trap is generated, AEXC is cleared.
+ */
+ if(would_trap == 0)
+ fsr |= ((long)eflag << FSR_AEXC_SHIFT);
+ else
+ fsr &= ~(FSR_AEXC_MASK);
+
+ /* If trapping, indicate fault trap type IEEE. */
+ if(would_trap != 0)
+ fsr |= (1UL << 14);
+
+ current->tss.xfsr[0] = fsr;
+
+ /* If we will not trap, advance the program counter over
+ * the instruction being handled.
+ */
+ if(would_trap == 0) {
+ regs->tpc = regs->tnpc;
+ regs->tnpc += 4;
+ }
+
+ return (would_trap ? 0 : 1);
+}
+
int do_mathemu(struct pt_regs *regs, struct fpustate *f)
{
unsigned long pc = regs->tpc;
@@ -175,7 +263,12 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
current->tss.fpsaved[0] |= flags;
break;
}
- func(rd, rs2, rs1);
+ flags = func(rd, rs2, rs1);
+ if(flags != 0)
+ return record_exception(regs, flags);
+
+ /* Success and no exceptions detected. */
+ current->tss.xfsr[0] &= ~(FSR_CEXC_MASK);
regs->tpc = regs->tnpc;
regs->tnpc += 4;
return 1;
diff --git a/arch/sparc64/math-emu/op-2.h b/arch/sparc64/math-emu/op-2.h
index 5999cfc3b..8ac63188c 100644
--- a/arch/sparc64/math-emu/op-2.h
+++ b/arch/sparc64/math-emu/op-2.h
@@ -190,14 +190,14 @@
\
__FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
_FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
+ 0, _b_f1, _b_f0, 0, \
_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
- 0, _b_f1, _b_f0, 0); \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \
__FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
_FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
+ 0, _c_f1, _c_f0, 0, \
_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
- 0, _c_f1, _c_f0, 0); \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \
\
/* Normalize since we know where the msb of the multiplicands \
were (bit B), we know that the msb of the of the product is \
diff --git a/arch/sparc64/math-emu/op-common.h b/arch/sparc64/math-emu/op-common.h
index ac49cd6c2..6090e0213 100644
--- a/arch/sparc64/math-emu/op-common.h
+++ b/arch/sparc64/math-emu/op-common.h
@@ -53,14 +53,14 @@ do { \
*/
#define _FP_PACK_CANONICAL(fs, wc, X) \
-do { \
+({int __ret = 0; \
switch (X##_c) \
{ \
case FP_CLS_NORMAL: \
X##_e += _FP_EXPBIAS_##fs; \
if (X##_e > 0) \
{ \
- _FP_ROUND(wc, X); \
+ __ret |= _FP_ROUND(wc, X); \
if (_FP_FRAC_OVERP_##wc(fs, X)) \
{ \
_FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \
@@ -73,6 +73,7 @@ do { \
/* overflow to infinity */ \
X##_e = _FP_EXPMAX_##fs; \
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ __ret |= EFLAG_OVERFLOW; \
} \
} \
else \
@@ -82,7 +83,7 @@ do { \
if (X##_e <= _FP_WFRACBITS_##fs) \
{ \
_FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
- _FP_ROUND(wc, X); \
+ __ret |= _FP_ROUND(wc, X); \
_FP_FRAC_SLL_##wc(X, 1); \
if (_FP_FRAC_OVERP_##wc(fs, X)) \
{ \
@@ -93,6 +94,7 @@ do { \
{ \
X##_e = 0; \
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \
+ __ret |= EFLAG_UNDERFLOW; \
} \
} \
else \
@@ -100,6 +102,7 @@ do { \
/* underflow to zero */ \
X##_e = 0; \
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ __ret |= EFLAG_UNDERFLOW; \
} \
} \
break; \
@@ -125,7 +128,8 @@ do { \
_FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \
break; \
} \
-} while (0)
+ __ret; \
+})
/*
@@ -424,11 +428,19 @@ do { \
} \
else \
{ \
- /* Force -0 -> +0 */ \
- if (!X##_e && _FP_FRAC_ZEROP_##wc(X)) X##_s = 0; \
- if (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) X##_s = 0; \
+ int __is_zero_x; \
+ int __is_zero_y; \
+ \
+ __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
+ __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
\
- if (X##_s != Y##_s) \
+ if (__is_zero_x && __is_zero_y) \
+ ret = 0; \
+ else if (__is_zero_x) \
+ ret = Y##_s ? 1 : -1; \
+ else if (__is_zero_y) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_s != Y##_s) \
ret = X##_s ? -1 : 1; \
else if (X##_e > Y##_e) \
ret = X##_s ? -1 : 1; \
diff --git a/arch/sparc64/math-emu/sfp-machine.h b/arch/sparc64/math-emu/sfp-machine.h
index f15a5ea4a..3846ac4f9 100644
--- a/arch/sparc64/math-emu/sfp-machine.h
+++ b/arch/sparc64/math-emu/sfp-machine.h
@@ -52,16 +52,6 @@
X##_s = _flo->bits.sign; \
} while (0)
-#define __FP_PACK_RAW_1(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac = X##_f; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
#define __FP_UNPACK_RAW_2(fs, X, val) \
do { \
union _FP_UNION_##fs *_flo = \
@@ -73,53 +63,80 @@
X##_s = _flo->bits.sign; \
} while (0)
-#define __FP_PACK_RAW_2(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac0 = X##_f0; \
- _flo->bits.frac1 = X##_f1; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
#define __FP_UNPACK_S(X,val) \
do { \
__FP_UNPACK_RAW_1(S,X,val); \
_FP_UNPACK_CANONICAL(S,1,X); \
} while (0)
-#define __FP_PACK_S(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- __FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
#define __FP_UNPACK_D(X,val) \
do { \
__FP_UNPACK_RAW_1(D,X,val); \
_FP_UNPACK_CANONICAL(D,1,X); \
} while (0)
-#define __FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,1,X); \
- __FP_PACK_RAW_1(D,val,X); \
- } while (0)
-
#define __FP_UNPACK_Q(X,val) \
do { \
__FP_UNPACK_RAW_2(Q,X,val); \
_FP_UNPACK_CANONICAL(Q,2,X); \
} while (0)
-#define __FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,2,X); \
- __FP_PACK_RAW_2(Q,val,X); \
+#define __FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+#define __FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
} while (0)
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#define __FPU_TEM \
+ (((current->tss.xfsr[0])>>23)&0x1f)
+#define __FPU_TRAP_P(bits) \
+ ((__FPU_TEM & (bits)) != 0)
+
+#define __FP_PACK_S(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(S,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_D(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(D,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(D,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_Q(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(Q,2,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_2(Q,val,X); \
+ __exc; \
+})
+
+/* Obtain the current rounding mode. */
+#define FP_ROUNDMODE ((current->tss.xfsr[0] >> 30) & 0x3)
+
#include <linux/types.h>
#include <asm/byteorder.h>
@@ -153,28 +170,24 @@
#define umul_ppmm(wh, wl, u, v) \
do { \
- long tmp1 = 0, tmp2 = 0, tmp3 = 0; \
__asm__ ("mulx %2,%3,%1
- srlx %2,32,%4
- srl %3,0,%5
- mulx %4,%5,%6
- srlx %3,32,%4
- srl %2,0,%5
- mulx %4,%5,%5
- srlx %2,32,%4
- add %5,%6,%6
- srlx %3,32,%5
- mulx %4,%5,%4
- srlx %6,32,%5
- add %4,%5,%0" \
+ srlx %2,32,%%g1
+ srl %3,0,%%g2
+ mulx %%g1,%%g2,%%g3
+ srlx %3,32,%%g1
+ srl %2,0,%%g2
+ mulx %%g1,%%g2,%%g2
+ srlx %2,32,%%g1
+ add %%g2,%%g3,%%g3
+ srlx %3,32,%%g2
+ mulx %%g1,%%g2,%%g1
+ srlx %%g3,32,%%g2
+ add %%g1,%%g2,%0" \
: "=r" ((UDItype)(wh)), \
"=&r" ((UDItype)(wl)) \
: "r" ((UDItype)(u)), \
- "r" ((UDItype)(v)), \
- "r" ((UDItype)(tmp1)), \
- "r" ((UDItype)(tmp2)), \
- "r" ((UDItype)(tmp3)) \
- : "cc"); \
+ "r" ((UDItype)(v)) \
+ : "g1", "g2", "g3", "cc"); \
} while (0)
#define udiv_qrnnd(q, r, n1, n0, d) \
@@ -223,3 +236,10 @@
#else
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif
+
+/* Exception flags. */
+#define EFLAG_INVALID (1 << 4)
+#define EFLAG_OVERFLOW (1 << 3)
+#define EFLAG_UNDERFLOW (1 << 2)
+#define EFLAG_DIVZERO (1 << 1)
+#define EFLAG_INEXACT (1 << 0)
diff --git a/arch/sparc64/math-emu/soft-fp.h b/arch/sparc64/math-emu/soft-fp.h
index a4f72e78f..b54f86217 100644
--- a/arch/sparc64/math-emu/soft-fp.h
+++ b/arch/sparc64/math-emu/soft-fp.h
@@ -14,45 +14,56 @@
# define FP_RND_ZERO 1
# define FP_RND_PINF 2
# define FP_RND_MINF 3
+#ifndef FP_ROUNDMODE
# define FP_ROUNDMODE FP_RND_NEAREST
#endif
+#endif
#define _FP_ROUND_NEAREST(wc, X) \
- do { \
+({ int __ret = EFLAG_INEXACT; \
if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
_FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
- } while(0)
+ else __ret = 0; \
+ __ret; \
+})
-#define _FP_ROUND_ZERO(wc, X)
+#define _FP_ROUND_ZERO(wc, X) 0 /* XXX */
#define _FP_ROUND_PINF(wc, X) \
- do { \
+({ int __ret = EFLAG_INEXACT; \
if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
_FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
- } while (0)
+ else __ret = 0; \
+ __ret; \
+})
#define _FP_ROUND_MINF(wc, X) \
- do { \
+({ int __ret = EFLAG_INEXACT; \
if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
_FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
- } while (0)
+ else __ret = 0; \
+ __ret; \
+})
#define _FP_ROUND(wc, X) \
+({ int __ret = 0; \
switch (FP_ROUNDMODE) \
{ \
case FP_RND_NEAREST: \
- _FP_ROUND_NEAREST(wc,X); \
+ __ret |= _FP_ROUND_NEAREST(wc,X); \
break; \
case FP_RND_ZERO: \
- _FP_ROUND_ZERO(wc,X); \
+ __ret |= _FP_ROUND_ZERO(wc,X); \
break; \
case FP_RND_PINF: \
- _FP_ROUND_PINF(wc,X); \
+ __ret |= _FP_ROUND_PINF(wc,X); \
break; \
case FP_RND_MINF: \
- _FP_ROUND_MINF(wc,X); \
+ __ret |= _FP_ROUND_MINF(wc,X); \
break; \
- }
+ }; \
+ __ret; \
+})
#define FP_CLS_NORMAL 0
#define FP_CLS_ZERO 1