summaryrefslogtreecommitdiffstats
path: root/arch/alpha/math-emu
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /arch/alpha/math-emu
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff)
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too o Upgrade to 2.1.89. Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'arch/alpha/math-emu')
-rw-r--r--arch/alpha/math-emu/Makefile10
-rw-r--r--arch/alpha/math-emu/fp-emul.c122
-rw-r--r--arch/alpha/math-emu/ieee-math.c33
3 files changed, 43 insertions, 122 deletions
diff --git a/arch/alpha/math-emu/Makefile b/arch/alpha/math-emu/Makefile
index 308533a02..6ea85465f 100644
--- a/arch/alpha/math-emu/Makefile
+++ b/arch/alpha/math-emu/Makefile
@@ -2,11 +2,11 @@
# Makefile for math-emulator files...
#
-OBJS = fp-emul.o ieee-math.o
+O_TARGET := math-emu.o
+O_OBJS := fp-emul.o ieee-math.o
-math-emu.a: $(OBJS)
- $(AR) rcs $@ $(OBJS)
-
-dep:
+ifeq ($(CONFIG_MATHEMU),m)
+M_OBJS := $(O_TARGET)
+endif
include $(TOPDIR)/Rules.make
diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c
index f1ff5a2be..543044019 100644
--- a/arch/alpha/math-emu/fp-emul.c
+++ b/arch/alpha/math-emu/fp-emul.c
@@ -1,5 +1,5 @@
+#include <linux/module.h>
#include <linux/types.h>
-
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -52,111 +52,33 @@
#define MISC_TRAPB 0x0000
#define MISC_EXCB 0x0400
+extern unsigned long alpha_read_fp_reg (unsigned long reg);
+extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
+
-extern unsigned long rdfpcr (void);
-extern void wrfpcr (unsigned long);
+#ifdef MODULE
+MODULE_DESCRIPTION("FP Software completion module");
-unsigned long
-alpha_read_fp_reg (unsigned long reg)
+extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
+static long (*save_emul)(struct pt_regs *, unsigned long);
+long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
+
+int init_module(void)
{
- unsigned long r;
-
- switch (reg) {
- case 0: asm ("stt $f0,%0" : "m="(r)); break;
- case 1: asm ("stt $f1,%0" : "m="(r)); break;
- case 2: asm ("stt $f2,%0" : "m="(r)); break;
- case 3: asm ("stt $f3,%0" : "m="(r)); break;
- case 4: asm ("stt $f4,%0" : "m="(r)); break;
- case 5: asm ("stt $f5,%0" : "m="(r)); break;
- case 6: asm ("stt $f6,%0" : "m="(r)); break;
- case 7: asm ("stt $f7,%0" : "m="(r)); break;
- case 8: asm ("stt $f8,%0" : "m="(r)); break;
- case 9: asm ("stt $f9,%0" : "m="(r)); break;
- case 10: asm ("stt $f10,%0" : "m="(r)); break;
- case 11: asm ("stt $f11,%0" : "m="(r)); break;
- case 12: asm ("stt $f12,%0" : "m="(r)); break;
- case 13: asm ("stt $f13,%0" : "m="(r)); break;
- case 14: asm ("stt $f14,%0" : "m="(r)); break;
- case 15: asm ("stt $f15,%0" : "m="(r)); break;
- case 16: asm ("stt $f16,%0" : "m="(r)); break;
- case 17: asm ("stt $f17,%0" : "m="(r)); break;
- case 18: asm ("stt $f18,%0" : "m="(r)); break;
- case 19: asm ("stt $f19,%0" : "m="(r)); break;
- case 20: asm ("stt $f20,%0" : "m="(r)); break;
- case 21: asm ("stt $f21,%0" : "m="(r)); break;
- case 22: asm ("stt $f22,%0" : "m="(r)); break;
- case 23: asm ("stt $f23,%0" : "m="(r)); break;
- case 24: asm ("stt $f24,%0" : "m="(r)); break;
- case 25: asm ("stt $f25,%0" : "m="(r)); break;
- case 26: asm ("stt $f26,%0" : "m="(r)); break;
- case 27: asm ("stt $f27,%0" : "m="(r)); break;
- case 28: asm ("stt $f28,%0" : "m="(r)); break;
- case 29: asm ("stt $f29,%0" : "m="(r)); break;
- case 30: asm ("stt $f30,%0" : "m="(r)); break;
- case 31: asm ("stt $f31,%0" : "m="(r)); break;
- default:
- break;
- }
- return r;
+ save_emul = alpha_fp_emul_imprecise;
+ alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise;
+ return 0;
}
-
-#if 0
-/*
- * This is IMHO the better way of implementing LDT(). But it
- * has the disadvantage that gcc 2.7.0 refuses to compile it
- * (invalid operand constraints), so instead, we use the uglier
- * macro below.
- */
-# define LDT(reg,val) \
- asm volatile ("ldt $f"#reg",%0" :: "m"(val));
-#else
-# define LDT(reg,val) \
- asm volatile ("ldt $f"#reg",0(%0)" :: "r"(&val));
-#endif
-
-void
-alpha_write_fp_reg (unsigned long reg, unsigned long val)
+void cleanup_module(void)
{
- switch (reg) {
- case 0: LDT( 0, val); break;
- case 1: LDT( 1, val); break;
- case 2: LDT( 2, val); break;
- case 3: LDT( 3, val); break;
- case 4: LDT( 4, val); break;
- case 5: LDT( 5, val); break;
- case 6: LDT( 6, val); break;
- case 7: LDT( 7, val); break;
- case 8: LDT( 8, val); break;
- case 9: LDT( 9, val); break;
- case 10: LDT(10, val); break;
- case 11: LDT(11, val); break;
- case 12: LDT(12, val); break;
- case 13: LDT(13, val); break;
- case 14: LDT(14, val); break;
- case 15: LDT(15, val); break;
- case 16: LDT(16, val); break;
- case 17: LDT(17, val); break;
- case 18: LDT(18, val); break;
- case 19: LDT(19, val); break;
- case 20: LDT(20, val); break;
- case 21: LDT(21, val); break;
- case 22: LDT(22, val); break;
- case 23: LDT(23, val); break;
- case 24: LDT(24, val); break;
- case 25: LDT(25, val); break;
- case 26: LDT(26, val); break;
- case 27: LDT(27, val); break;
- case 28: LDT(28, val); break;
- case 29: LDT(29, val); break;
- case 30: LDT(30, val); break;
- case 31: LDT(31, val); break;
- default:
- break;
- }
+ alpha_fp_emul_imprecise = save_emul;
}
+#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
+
+#endif /* MODULE */
/*
* Emulate the floating point instruction at address PC. Returns 0 if
@@ -334,6 +256,8 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
unsigned long trigger_pc = regs->pc - 4;
unsigned long insn, opcode, rc;
+ MOD_INC_USE_COUNT;
+
/*
* Turn off the bits corresponding to registers that are the
* target of instructions that set bits in the exception
@@ -354,12 +278,14 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
case OPC_PAL:
case OPC_JSR:
case 0x30 ... 0x3f: /* branches */
+ MOD_DEC_USE_COUNT;
return 0;
case OPC_MISC:
switch (insn & 0xffff) {
case MISC_TRAPB:
case MISC_EXCB:
+ MOD_DEC_USE_COUNT;
return 0;
default:
@@ -386,11 +312,13 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
{
/* re-execute insns in trap-shadow: */
regs->pc = trigger_pc + 4;
+ MOD_DEC_USE_COUNT;
return 1;
}
break;
}
trigger_pc -= 4;
}
+ MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/arch/alpha/math-emu/ieee-math.c b/arch/alpha/math-emu/ieee-math.c
index d408eece5..59d7dfa6d 100644
--- a/arch/alpha/math-emu/ieee-math.c
+++ b/arch/alpha/math-emu/ieee-math.c
@@ -137,9 +137,8 @@ sub128 (const unsigned long a[2], const unsigned long b[2], unsigned long c[2])
static inline void
mul64 (const unsigned long a, const unsigned long b, unsigned long c[2])
{
- asm ("mulq %2,%3,%0\n\t"
- "umulh %2,%3,%1"
- : "r="(c[0]), "r="(c[1]) : "r"(a), "r"(b));
+ c[0] = a * b;
+ asm ("umulh %1,%2,%0" : "=r"(c[1]) : "r"(a), "r"(b));
}
@@ -276,7 +275,7 @@ make_s_ieee (long f, EXTENDED *a, unsigned long *b)
{
unsigned long res, sticky;
- if (!a->f[0] && !a->f[1]) {
+ if (!a->e && !a->f[0] && !a->f[1]) {
*b = (unsigned long) a->s << 63; /* return +/-0 */
return 0;
}
@@ -356,7 +355,7 @@ make_t_ieee (long f, EXTENDED *a, unsigned long *b)
{
unsigned long res, sticky;
- if (!a->f[0] && !a->f[1]) {
+ if (!a->e && !a->f[0] && !a->f[1]) {
*b = (unsigned long) a->s << 63; /* return +/-0 */
return 0;
}
@@ -384,7 +383,7 @@ make_t_ieee (long f, EXTENDED *a, unsigned long *b)
a->e = -0x3ff;
}
}
- if (a->e > 0x3ff) {
+ if (a->e >= 0x3ff) {
res = FPCR_OVF | FPCR_INE;
if (f & IEEE_TRAP_ENABLE_OVF) {
a->e -= 0x600; /* scale down result by 2^alpha */
@@ -777,25 +776,25 @@ ieee_CVTTQ (int f, unsigned long a, unsigned long *b)
midway = (temp.f[0] & 0x003fffffffffffff) == 0;
if ((midway && (temp.f[0] & 0x0080000000000000)) ||
!midway)
- ++b;
+ ++*b;
}
break;
case ROUND_PINF:
- if ((temp.f[0] & 0x003fffffffffffff) != 0)
- ++b;
+ if ((temp.f[0] & 0x007fffffffffffff) != 0)
+ ++*b;
break;
case ROUND_NINF:
- if ((temp.f[0] & 0x003fffffffffffff) != 0)
- --b;
+ if ((temp.f[0] & 0x007fffffffffffff) != 0)
+ --*b;
break;
case ROUND_CHOP:
/* no action needed */
break;
}
- if ((temp.f[0] & 0x003fffffffffffff) != 0)
+ if ((temp.f[0] & 0x007fffffffffffff) != 0)
res |= FPCR_INE;
if (temp.s) {
@@ -1143,12 +1142,9 @@ ieee_MULS (int f, unsigned long a, unsigned long b, unsigned long *c)
return 0;
}
op_c.s = op_a.s ^ op_b.s;
- op_c.e = op_a.e + op_b.e;
+ op_c.e = op_a.e + op_b.e - 55;
mul64(op_a.f[0], op_b.f[0], op_c.f);
- normalize(&op_c);
- op_c.e -= 55; /* drop the 55 original bits. */
-
return round_s_ieee(f, &op_c, c);
}
@@ -1200,12 +1196,9 @@ ieee_MULT (int f, unsigned long a, unsigned long b, unsigned long *c)
return 0;
}
op_c.s = op_a.s ^ op_b.s;
- op_c.e = op_a.e + op_b.e;
+ op_c.e = op_a.e + op_b.e - 55;
mul64(op_a.f[0], op_b.f[0], op_c.f);
- normalize(&op_c);
- op_c.e -= 55; /* drop the 55 original bits. */
-
return round_t_ieee(f, &op_c, c);
}