summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-11-25 04:49:46 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-11-25 04:49:46 +0000
commit4c55adaa6d06e5533aebaceea7640ecf10952231 (patch)
tree0f2e4190d1e9db004e50c7f33a1fe46337fd1885 /arch
parent4c86076eb07eb647b1080355e18dc9d4c49bf7e1 (diff)
Kernel FPU emulator, chain saw edition.
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Makefile5
-rw-r--r--arch/mips/config.in1
-rw-r--r--arch/mips/defconfig1
-rw-r--r--arch/mips/defconfig-atlas1
-rw-r--r--arch/mips/defconfig-ddb54761
-rw-r--r--arch/mips/defconfig-decstation1
-rw-r--r--arch/mips/defconfig-ev961001
-rw-r--r--arch/mips/defconfig-ip221
-rw-r--r--arch/mips/defconfig-malta1
-rw-r--r--arch/mips/defconfig-orion1
-rw-r--r--arch/mips/defconfig-rm2001
-rw-r--r--arch/mips/kernel/Makefile6
-rw-r--r--arch/mips/kernel/branch.c11
-rw-r--r--arch/mips/kernel/proc.c9
-rw-r--r--arch/mips/kernel/process.c12
-rw-r--r--arch/mips/kernel/ptrace.c1
-rw-r--r--arch/mips/kernel/r4k_switch.S8
-rw-r--r--arch/mips/kernel/setup.c146
-rw-r--r--arch/mips/kernel/time.c3
-rw-r--r--arch/mips/kernel/traps.c111
-rw-r--r--arch/mips/math-emu/.cvsignore2
-rw-r--r--arch/mips/math-emu/Makefile28
-rw-r--r--arch/mips/math-emu/cp1emu.c1814
-rw-r--r--arch/mips/math-emu/dp_add.c193
-rw-r--r--arch/mips/math-emu/dp_cmp.c65
-rw-r--r--arch/mips/math-emu/dp_div.c167
-rw-r--r--arch/mips/math-emu/dp_fint.c85
-rw-r--r--arch/mips/math-emu/dp_flong.c83
-rw-r--r--arch/mips/math-emu/dp_frexp.c60
-rw-r--r--arch/mips/math-emu/dp_fsp.c77
-rw-r--r--arch/mips/math-emu/dp_logb.c61
-rw-r--r--arch/mips/math-emu/dp_modf.c87
-rw-r--r--arch/mips/math-emu/dp_mul.c187
-rw-r--r--arch/mips/math-emu/dp_scalb.c65
-rw-r--r--arch/mips/math-emu/dp_simple.c73
-rw-r--r--arch/mips/math-emu/dp_sqrt.c174
-rw-r--r--arch/mips/math-emu/dp_sub.c200
-rw-r--r--arch/mips/math-emu/dp_tint.c94
-rw-r--r--arch/mips/math-emu/dp_tlong.c148
-rw-r--r--arch/mips/math-emu/ieee754.c145
-rw-r--r--arch/mips/math-emu/ieee754.h490
-rw-r--r--arch/mips/math-emu/ieee754d.c148
-rw-r--r--arch/mips/math-emu/ieee754dp.c204
-rw-r--r--arch/mips/math-emu/ieee754dp.h81
-rw-r--r--arch/mips/math-emu/ieee754int.h135
-rw-r--r--arch/mips/math-emu/ieee754m.c56
-rw-r--r--arch/mips/math-emu/ieee754sp.c205
-rw-r--r--arch/mips/math-emu/ieee754sp.h87
-rw-r--r--arch/mips/math-emu/ieee754xcpt.c60
-rw-r--r--arch/mips/math-emu/kernel_linkage.c89
-rw-r--r--arch/mips/math-emu/sp_add.c188
-rw-r--r--arch/mips/math-emu/sp_cmp.c66
-rw-r--r--arch/mips/math-emu/sp_div.c168
-rw-r--r--arch/mips/math-emu/sp_fdp.c77
-rw-r--r--arch/mips/math-emu/sp_fint.c86
-rw-r--r--arch/mips/math-emu/sp_flong.c85
-rw-r--r--arch/mips/math-emu/sp_frexp.c61
-rw-r--r--arch/mips/math-emu/sp_logb.c62
-rw-r--r--arch/mips/math-emu/sp_modf.c88
-rw-r--r--arch/mips/math-emu/sp_mul.c182
-rw-r--r--arch/mips/math-emu/sp_scalb.c66
-rw-r--r--arch/mips/math-emu/sp_simple.c74
-rw-r--r--arch/mips/math-emu/sp_sqrt.c122
-rw-r--r--arch/mips/math-emu/sp_sub.c195
-rw-r--r--arch/mips/math-emu/sp_tint.c95
-rw-r--r--arch/mips/math-emu/sp_tlong.c95
-rw-r--r--arch/mips/mm/init.c6
-rw-r--r--arch/mips/mm/loadmmu.c5
-rw-r--r--arch/mips/mm/r4xx0.c5
69 files changed, 7339 insertions, 72 deletions
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index d9378c15b..ca802dba9 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -79,6 +79,11 @@ ifdef CONFIG_CPU_R10000
GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap
endif
+ifdef CONFIG_MIPS_FPU_EMULATOR
+CORE_FILES +=arch/mips/math-emu/fpu_emulator.o
+SUBDIRS +=arch/mips/math-emu
+endif
+
#
# The pipe options is bad for my low-mem machine
# Uncomment this if you want this.
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 35dd6a40c..65cb90b3d 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -166,6 +166,7 @@ if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" -o "$CONFIG_DDB5476"
else
bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
fi
+bool ' Kernel floating-point emulation' CONFIG_MIPS_FPU_EMULATOR
if [ "$CONFIG_PROC_FS" = "y" ]; then
define_bool CONFIG_KCORE_ELF y
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index b66bb0dfa..534d17b1d 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -61,6 +61,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
CONFIG_BINFMT_IRIX=y
diff --git a/arch/mips/defconfig-atlas b/arch/mips/defconfig-atlas
index 2e050a7dd..b7c45f78c 100644
--- a/arch/mips/defconfig-atlas
+++ b/arch/mips/defconfig-atlas
@@ -56,6 +56,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
CONFIG_BINFMT_IRIX=y
diff --git a/arch/mips/defconfig-ddb5476 b/arch/mips/defconfig-ddb5476
index bfdcd7419..77130d7da 100644
--- a/arch/mips/defconfig-ddb5476
+++ b/arch/mips/defconfig-ddb5476
@@ -57,6 +57,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
# CONFIG_BINFMT_AOUT is not set
diff --git a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation
index 987c40c54..d264f047a 100644
--- a/arch/mips/defconfig-decstation
+++ b/arch/mips/defconfig-decstation
@@ -57,6 +57,7 @@ CONFIG_CPU_HAS_WB=y
# General setup
#
CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
# CONFIG_BINFMT_AOUT is not set
diff --git a/arch/mips/defconfig-ev96100 b/arch/mips/defconfig-ev96100
index 144d4b92d..44eeaa0e1 100644
--- a/arch/mips/defconfig-ev96100
+++ b/arch/mips/defconfig-ev96100
@@ -58,6 +58,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
# CONFIG_BINFMT_IRIX is not set
diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22
index b66bb0dfa..534d17b1d 100644
--- a/arch/mips/defconfig-ip22
+++ b/arch/mips/defconfig-ip22
@@ -61,6 +61,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
CONFIG_BINFMT_IRIX=y
diff --git a/arch/mips/defconfig-malta b/arch/mips/defconfig-malta
index a5618827e..1e9f8e70b 100644
--- a/arch/mips/defconfig-malta
+++ b/arch/mips/defconfig-malta
@@ -56,6 +56,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
# CONFIG_BINFMT_AOUT is not set
diff --git a/arch/mips/defconfig-orion b/arch/mips/defconfig-orion
index 791b5b5b5..967043363 100644
--- a/arch/mips/defconfig-orion
+++ b/arch/mips/defconfig-orion
@@ -57,6 +57,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
# CONFIG_BINFMT_IRIX is not set
diff --git a/arch/mips/defconfig-rm200 b/arch/mips/defconfig-rm200
index 5331234e2..5eb83f270 100644
--- a/arch/mips/defconfig-rm200
+++ b/arch/mips/defconfig-rm200
@@ -60,6 +60,7 @@ CONFIG_CPU_HAS_LLSC=y
# General setup
#
CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
CONFIG_KCORE_ELF=y
CONFIG_ELF_KERNEL=y
# CONFIG_ARC_CONSOLE is not set
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 01b2148bf..ceafba8ec 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,7 +14,7 @@ EXTRA_ASFLAGS = -mips3 -mcpu=r4000
O_TARGET := kernel.o
O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
ioport.o reset.o semaphore.o setup.o syscall.o sysmips.o ipc.o \
- scall_o32.o softfp.o unaligned.o
+ scall_o32.o unaligned.o
OX_OBJS := mips_ksyms.o
ifdef CONFIG_CPU_R3000
@@ -32,6 +32,10 @@ ifdef CONFIG_MIPS_FPE_MODULE
M_OBJS += fpe.o
endif
+ifndef CONFIG_MIPS_FPU_EMULATOR
+O_OBJS += softfp.o
+endif
+
ifdef CONFIG_ROTTEN_IRQ
OX_OBJS += old-irq.o
endif
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4ca20214d..b74f87364 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -5,15 +5,19 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1996, 97, 2000 by Ralf Baechle
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/branch.h>
+#include <asm/cpu.h>
#include <asm/inst.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/processor.h>
/*
* Compute the return address and do emulate branch simulation, if required.
@@ -163,6 +167,11 @@ int __compute_return_epc(struct pt_regs *regs)
* And now the FPA/cp1 branch instructions.
*/
case cop1_op:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU))
+ fcr31 = current->thread.fpu.soft.sr;
+ else
+#endif
asm ("cfc1\t%0,$31":"=r" (fcr31));
bit = (insn.i_format.rt >> 2);
bit += (bit != 0);
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 701321a6b..0069c4a01 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
#include <asm/watch.h>
@@ -50,11 +51,9 @@ int get_cpuinfo(char *buffer)
len = sprintf(buffer, "cpu\t\t\t: MIPS\n");
len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n",
- cpu_name[mips_cputype <= CPU_LAST ?
- mips_cputype :
- CPU_UNKNOWN],
- (version >> 4) & 0x0f,
- version & 0x0f);
+ cpu_name[mips_cpu.cputype <= CPU_LAST ?
+ mips_cpu.cputype : CPU_UNKNOWN],
+ (version >> 4) & 0x0f, version & 0x0f);
len += sprintf(buffer + len, "system type\t\t: %s %s\n",
mach_group_names[mips_machgroup],
mach_group_to_name[mips_machgroup][mips_machtype]);
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6071935d5..d3ef5124f 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -6,6 +6,7 @@
* Copyright (C) 1994 - 2000 by Ralf Baechle and others.
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -20,6 +21,7 @@
#include <linux/a.out.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/mipsregs.h>
@@ -80,9 +82,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
- if (last_task_used_math == current) {
- set_cp0_status(ST0_CU1, ST0_CU1);
- save_fp(p);
+ if (last_task_used_math == current)
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if (mips_cpu.options & MIPS_CPU_FPU)
+#endif
+ {
+ set_cp0_status(ST0_CU1, ST0_CU1);
+ save_fp(p);
}
/* set up new TSS. */
childregs = (struct pt_regs *) childksp - 1;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 1aabad599..618f418f8 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -23,6 +23,7 @@
#include <asm/page.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 0ac3c532f..5fc53d678 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -95,6 +95,14 @@ LEAF(save_fp)
END(save_fp)
/*
+ * Restore a thread's fp context.
+ */
+LEAF(restore_fp)
+ FPU_RESTORE_DOUBLE(a0, t1) # clobbers t1
+ jr ra
+ END(r4xx0_restore_fp)
+
+/*
* Load the FPU with signalling NANS. This bit pattern we're using has
* the property that no matter whether considered as single or as double
* precision represents signaling NANS.
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index db1838916..58d834a43 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -36,6 +36,7 @@
#include <asm/asm.h>
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
+#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/stackframe.h>
#include <asm/system.h>
@@ -95,7 +96,6 @@ struct kbd_ops *kbd_ops;
* These are initialized so they are in the .data section
*/
unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
-unsigned long mips_cputype = CPU_UNKNOWN;
unsigned long mips_machtype = MACH_UNKNOWN;
unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
@@ -152,63 +152,153 @@ static inline int cpu_has_confreg(void)
#endif
}
+/* declaration of the global struct */
+struct mips_cpu mips_cpu = {PRID_IMP_UNKNOWN, CPU_UNKNOWN, 0, 0, 0,
+ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}};
+
+/* Shortcut for assembler access to mips_cpu.options */
+int *cpuoptions = &mips_cpu.options;
+
+#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
+ | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX)
+
static inline void cpu_probe(void)
{
- unsigned int prid = read_32bit_cp0_register(CP0_PRID);
- switch(prid & 0xff00) {
+ unsigned long config1;
+
+ mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID);
+ switch (mips_cpu.processor_id & 0xff00) {
case PRID_IMP_R2000:
- mips_cputype = CPU_R2000;
+ mips_cpu.cputype = CPU_R2000;
+ mips_cpu.isa_level = MIPS_CPU_ISA_I;
+ mips_cpu.options = MIPS_CPU_TLB;
+ mips_cpu.tlbsize = 32;
break;
case PRID_IMP_R3000:
- if((prid & 0xff) == PRID_REV_R3000A)
- if(cpu_has_confreg())
- mips_cputype = CPU_R3081E;
+ if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
+ if (cpu_has_confreg())
+ mips_cpu.cputype = CPU_R3081E;
else
- mips_cputype = CPU_R3000A;
+ mips_cpu.cputype = CPU_R3000A;
else
- mips_cputype = CPU_R3000;
+ mips_cpu.cputype = CPU_R3000;
+ mips_cpu.isa_level = MIPS_CPU_ISA_I;
+ mips_cpu.options = MIPS_CPU_TLB;
+ mips_cpu.tlbsize = 32;
break;
case PRID_IMP_R4000:
- if((prid & 0xff) == PRID_REV_R4400)
- mips_cputype = CPU_R4400SC;
+ if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
+ mips_cpu.cputype = CPU_R4400SC;
else
- mips_cputype = CPU_R4000SC;
+ mips_cpu.cputype = CPU_R4000SC;
+ mips_cpu.isa_level = MIPS_CPU_ISA_III;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_WATCH | MIPS_CPU_VCE;
+ mips_cpu.tlbsize = 48;
break;
case PRID_IMP_R4600:
- mips_cputype = CPU_R4600;
+ mips_cpu.cputype = CPU_R4600;
+ mips_cpu.isa_level = MIPS_CPU_ISA_III;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+ mips_cpu.tlbsize = 48;
break;
case PRID_IMP_R4650:
- mips_cputype = CPU_R4650;
+ mips_cpu.cputype = CPU_R4650;
+ mips_cpu.isa_level = MIPS_CPU_ISA_III;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+ mips_cpu.tlbsize = 48;
break;
case PRID_IMP_R4700:
- mips_cputype = CPU_R4700;
+ mips_cpu.cputype = CPU_R4700;
+ mips_cpu.isa_level = MIPS_CPU_ISA_III;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+ mips_cpu.tlbsize = 48;
break;
case PRID_IMP_R5000:
- mips_cputype = CPU_R5000;
+ mips_cpu.cputype = CPU_R5000;
+ mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+ mips_cpu.tlbsize = 48;
+ break;
+ case PRID_IMP_R5432:
+ mips_cpu.cputype = CPU_R5432;
+ mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+ mips_cpu.tlbsize = 48;
break;
- case PRID_IMP_R5432:
- mips_cputype = CPU_R5432;
- break;
case PRID_IMP_NEVADA:
- mips_cputype = CPU_NEVADA;
+ mips_cpu.cputype = CPU_NEVADA;
+ mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+ mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_DIVEC;
+ mips_cpu.tlbsize = 48;
break;
case PRID_IMP_R6000:
- mips_cputype = CPU_R6000;
+ mips_cpu.cputype = CPU_R6000;
+ mips_cpu.isa_level = MIPS_CPU_ISA_II;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+ mips_cpu.tlbsize = 32;
break;
case PRID_IMP_R6000A:
- mips_cputype = CPU_R6000A;
+ mips_cpu.cputype = CPU_R6000A;
+ mips_cpu.isa_level = MIPS_CPU_ISA_II;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+ mips_cpu.tlbsize = 32;
break;
case PRID_IMP_RM7000:
- mips_cputype = CPU_RM7000;
+ mips_cpu.cputype = CPU_RM7000;
+ mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_COUNTER;
break;
case PRID_IMP_R8000:
- mips_cputype = CPU_R8000;
+ mips_cpu.cputype = CPU_R8000;
+ mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR;
+ mips_cpu.tlbsize = 384; /* has wierd TLB: 3-way x 128 */
break;
case PRID_IMP_R10000:
- mips_cputype = CPU_R10000;
+ mips_cpu.cputype = CPU_R10000;
+ mips_cpu.cputype = MIPS_CPU_ISA_IV;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
+ mips_cpu.tlbsize = 64;
+ break;
+#ifdef CONFIG_CPU_MIPS32
+ case PRID_IMP_4KC:
+ mips_cpu.cputype = CPU_4KC;
+ mips_cpu.cputype = MIPS_CPU_ISA_M32;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER |
+ MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+ config1 = read_mips32_cp0_config1();
+ if (config1 & (1 << 3))
+ mips_cpu.options |= MIPS_CPU_WATCH;
+ if (config1 & (1 << 2))
+ mips_cpu.options |= MIPS_CPU_MIPS16;
+ if (config1 & 1)
+ mips_cpu.options |= MIPS_CPU_FPU;
break;
+ case PRID_IMP_5KC:
+ mips_cpu.cputype = CPU_5KC;
+ mips_cpu.cputype = MIPS_CPU_ISA_M64;
+ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER |
+ MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+ config1 = read_mips32_cp0_config1();
+ if (config1 & (1 << 3))
+ mips_cpu.options |= MIPS_CPU_WATCH;
+ if (config1 & (1 << 2))
+ mips_cpu.options |= MIPS_CPU_MIPS16;
+ if (config1 & 1)
+ mips_cpu.options |= MIPS_CPU_FPU;
+ break;
+#endif
default:
- mips_cputype = CPU_UNKNOWN;
+ mips_cpu.cputype = CPU_UNKNOWN;
}
}
@@ -232,9 +322,9 @@ asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_v
*/
loadmmu();
- /* Disable coprocessors */
+ /* Disable coprocessors and set FPU for 16 FPRs */
s = read_32bit_cp0_register(CP0_STATUS);
- s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX);
+ s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
s |= ST0_CU0;
write_32bit_cp0_register(CP0_STATUS, s);
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 6b65801d5..7b953e94f 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -17,6 +17,7 @@
#include <linux/kernel_stat.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -448,7 +449,7 @@ char cyclecounter_available;
static inline void init_cycle_counter(void)
{
- switch(mips_cputype) {
+ switch(mips_cpu.cputype) {
case CPU_UNKNOWN:
case CPU_R2000:
case CPU_R3000:
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ebfac0cd2..0abd55e78 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -16,12 +16,14 @@
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
+#include <asm/bootinfo.h>
#include <asm/branch.h>
+#include <asm/cpu.h>
#include <asm/cachectl.h>
+#include <asm/inst.h>
#include <asm/jazz.h>
#include <asm/pgtable.h>
#include <asm/io.h>
-#include <asm/bootinfo.h>
#include <asm/watch.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -66,6 +68,8 @@ extern asmlinkage void handle_fpe(void);
extern asmlinkage void handle_watch(void);
extern asmlinkage void handle_reserved(void);
+extern int fpu_emulator_cop1Handler(int, struct pt_regs *);
+
static char *cpu_names[] = CPU_NAMES;
char watch_available = 0;
@@ -318,9 +322,11 @@ int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31))
*/
void do_fpe(struct pt_regs *regs, unsigned long fcr31)
{
- unsigned long pc;
- unsigned int insn;
- extern void simfp(unsigned int);
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU))
+ panic("Floating Point Exception with No FPU");
+#endif
#ifdef CONFIG_MIPS_FPE_MODULE
if (fpe_handler != NULL) {
@@ -328,12 +334,50 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
return;
}
#endif
- if (fcr31 & 0x20000) {
+
+ if (fcr31 & FPU_CSR_UNI_X) {
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ extern void save_fp(struct task_struct *);
+ extern void restore_fp(struct task_struct *);
+ int sig;
+ /*
+ * Unimplemented operation exception. If we've got the
+ * Full software emulator on-board, let's use it...
+ *
+ * Force FPU to dump state into task/thread context.
+ * We're moving a lot of data here for what is probably
+ * a single instruction, but the alternative is to
+ * pre-decode the FP register operands before invoking
+ * the emulator, which seems a bit extreme for what
+ * should be an infrequent event.
+ */
+ save_fp(current);
+
+ /* Run the emulator */
+ sig = fpu_emulator_cop1Handler(0, regs);
+
+ /*
+ * We can't allow the emulated instruction to leave the
+ * Unimplemented Operation bit set in the FCR31 fp-register.
+ */
+ current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X;
+
+ /* Restore the hardware register state */
+ restore_fp(current);
+
+ /* If something went wrong, signal */
+ if (sig)
+ force_sig(sig, current);
+#else
+ /* Else use mini-emulator */
+
+ extern void simfp(int);
+ unsigned long pc;
+ unsigned int insn;
+
/* Retry instruction with flush to zero ... */
if (!(fcr31 & (1<<24))) {
- printk("Setting flush to zero for %s.\n",
- current->comm);
- fcr31 &= ~0x20000;
+ fcr31 &= ~FPU_CSR_UNI_X;
fcr31 |= (1<<24);
__asm__ __volatile__(
"ctc1\t%0,$31"
@@ -342,20 +386,13 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
return;
}
pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
- if (get_user(insn, (unsigned int *)pc)) {
- /* XXX Can this happen? */
+ if (get_user(insn, (unsigned int *)pc))
force_sig(SIGSEGV, current);
- }
-
- printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
- insn, regs->cp0_epc, current->comm);
- simfp(insn);
+#endif /* !CONFIG_MIPS_FPU_EMULATOR */
}
- if (compute_return_epc(regs))
- return;
- //force_sig(SIGFPE, current);
- printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
+ if (!compute_return_epc(regs))
+ force_sig(SIGFPE, current);
}
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -530,11 +567,33 @@ void do_cpu(struct pt_regs *regs)
unsigned int cpid;
extern void lazy_fpu_switch(void*);
extern void init_fpu(void);
-
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ void fpu_emulator_init_fpu(void);
+ int sig;
+#endif
cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
if (cpid != 1)
goto bad_cid;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+ if (last_task_used_math != current) {
+ if(!current->used_math) {
+ fpu_emulator_init_fpu();
+ current->used_math = 1;
+ }
+ }
+ sig = fpu_emulator_cop1Handler(0, regs);
+ last_task_used_math = current;
+ if(sig) {
+ force_sig(sig, current);
+ }
+ return;
+ }
+#else
+ if(!(mips_cpu.options & MIPS_CPU_FPU)) goto bad_cid;
+#endif
+
regs->cp0_status |= ST0_CU1;
if (last_task_used_math == current)
return;
@@ -599,7 +658,7 @@ static inline void watch_init(unsigned long cputype)
static inline void setup_dedicated_int(void)
{
extern void except_vec4(void);
- switch(mips_cputype) {
+ switch(mips_cpu.cputype) {
case CPU_NEVADA:
memcpy((void *)(KSEG0 + 0x200), except_vec4, 8);
set_cp0_cause(CAUSEF_IV, CAUSEF_IV);
@@ -655,7 +714,7 @@ void __init trap_init(void)
* Only some CPUs have the watch exceptions or a dedicated
* interrupt vector.
*/
- watch_init(mips_cputype);
+ watch_init(mips_cpu.cputype);
setup_dedicated_int();
set_except_vector(1, handle_mod);
@@ -684,7 +743,7 @@ void __init trap_init(void)
/*
* Handling the following exceptions depends mostly of the cpu type
*/
- switch(mips_cputype) {
+ switch(mips_cpu.cputype) {
case CPU_R10000:
/*
* The R10000 is in most aspects similar to the R4400. It
@@ -714,9 +773,9 @@ void __init trap_init(void)
case CPU_R5432:
case CPU_NEVADA:
case CPU_RM7000:
- if(mips_cputype == CPU_NEVADA) {
+ if(mips_cpu.cputype == CPU_NEVADA) {
memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
- } else if (mips_cputype == CPU_R4600)
+ } else if (mips_cpu.cputype == CPU_R4600)
memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
else
memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
@@ -759,7 +818,7 @@ void __init trap_init(void)
break;
case CPU_R8000:
printk("Detected unsupported CPU type %s.\n",
- cpu_names[mips_cputype]);
+ cpu_names[mips_cpu.cputype]);
panic("Can't handle CPU");
break;
diff --git a/arch/mips/math-emu/.cvsignore b/arch/mips/math-emu/.cvsignore
new file mode 100644
index 000000000..857dd22e9
--- /dev/null
+++ b/arch/mips/math-emu/.cvsignore
@@ -0,0 +1,2 @@
+.depend
+.*.flags
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
new file mode 100644
index 000000000..456e1067d
--- /dev/null
+++ b/arch/mips/math-emu/Makefile
@@ -0,0 +1,28 @@
+#
+# Makefile for the Linux/MIPS kernel FPU emulation.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: fpu_emulator.o
+EXTRA_ASFLAGS = -mips2 -mcpu=r4000
+O_TARGET:= fpu_emulator.o
+
+O_OBJS := cp1emu.o ieee754m.o ieee754d.o \
+ ieee754dp.o ieee754sp.o ieee754.o ieee754xcpt.o \
+ dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o \
+ dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
+ dp_tint.o dp_fint.o dp_tlong.o dp_flong.o \
+ sp_frexp.o sp_modf.o sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o \
+ sp_cmp.o sp_logb.o sp_scalb.o sp_simple.o \
+ sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
+ dp_sqrt.o sp_sqrt.o kernel_linkage.o
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
new file mode 100644
index 000000000..a95e4e600
--- /dev/null
+++ b/arch/mips/math-emu/cp1emu.c
@@ -0,0 +1,1814 @@
+/*
+ * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ *
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * A complete emulator for MIPS coprocessor 1 instructions. This is
+ * required for #float(switch) or #float(trap), where it catches all
+ * COP1 instructions via the "CoProcessor Unusable" exception.
+ *
+ * More surprisingly it is also required for #float(ieee), to help out
+ * the hardware fpu at the boundaries of the IEEE-754 representation
+ * (denormalised values, infinities, underflow, etc). It is made
+ * quite nasty because emulation of some non-COP1 instructions is
+ * required, e.g. in branch delay slots.
+ *
+ * Notes:
+ * 1) the IEEE754 library (-le) performs the actual arithmetic;
+ * 2) if you know that you won't have an fpu, then you'll get much
+ * better performance by compiling with -msoft-float! */
+
+/**************************************************************************
+ * Nov 7, 2000
+ * Massive changes to integrate with Linux kernel.
+ *
+ * Replace use of kernel data area with use of user stack
+ * for execution of instructions in branch delay slots.
+ *
+ * Replace use of static kernel variables with thread_struct elements.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+#include <asm/fpu_emulator.h>
+
+#include "ieee754.h"
+
+#ifdef __KERNEL__
+#define _mon_printf printk
+#endif
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+typedef void *vaddr_t;
+
+/* Function which emulates the instruction in a branch delay slot. */
+
+static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
+
+/* Function which emulates a floating point instruction. */
+
+static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+ mips_instruction);
+
+#if __mips >= 4 && __mips != 32
+static int fpux_emu(struct pt_regs *,
+ struct mips_fpu_soft_struct *, mips_instruction);
+#endif
+
+/* Further private data for which no space exists in mips_fpu_soft_struct */
+
+struct mips_fpu_emulator_private fpuemuprivate;
+
+/* Control registers */
+
+#define FPCREG_RID 0 /* $0 = revision id */
+#define FPCREG_CSR 31 /* $31 = csr */
+
+/* Convert Mips rounding mode (0..3) to IEEE library modes. */
+static const unsigned char ieee_rm[4] = {
+ IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+};
+
+#if __mips >= 4
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+ FPU_CSR_COND0,
+ FPU_CSR_COND1,
+ FPU_CSR_COND2,
+ FPU_CSR_COND3,
+ FPU_CSR_COND4,
+ FPU_CSR_COND5,
+ FPU_CSR_COND6,
+ FPU_CSR_COND7
+};
+#endif
+
+
+
+/*
+ * Redundant with logic already in kernel/branch.c,
+ * embedded in compute_return_epc. At some point,
+ * a single subroutine should be used across both
+ * modules.
+ */
+static int isBranchInstr(mips_instruction * i)
+{
+ switch (MIPSInst_OPCODE(*i)) {
+ case spec_op:
+ switch (MIPSInst_FUNC(*i)) {
+ case jalr_op:
+ case jr_op:
+ return 1;
+ }
+ break;
+
+ case bcond_op:
+ switch (MIPSInst_RT(*i)) {
+ case bltz_op:
+ case bgez_op:
+ case bltzl_op:
+ case bgezl_op:
+ case bltzal_op:
+ case bgezal_op:
+ case bltzall_op:
+ case bgezall_op:
+ return 1;
+ }
+ break;
+
+ case j_op:
+ case jal_op:
+ case jalx_op:
+ case beq_op:
+ case bne_op:
+ case blez_op:
+ case bgtz_op:
+ case beql_op:
+ case bnel_op:
+ case blezl_op:
+ case bgtzl_op:
+ return 1;
+
+ case cop0_op:
+ case cop1_op:
+ case cop2_op:
+ case cop1x_op:
+ if (MIPSInst_RS(*i) == bc_op)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+#define REG_TO_VA (vaddr_t)
+#define VA_TO_REG (unsigned long)
+
+static unsigned long
+mips_get_word(struct pt_regs *xcp, void *va, int *perr)
+{
+ unsigned long temp;
+
+ if (!user_mode(xcp)) {
+ *perr = 0;
+ return (*(unsigned long *) va);
+ } else {
+ /* Use kernel get_user() macro */
+ *perr = (int) get_user(temp, (unsigned long *) va);
+ return temp;
+ }
+}
+
+static unsigned long long
+mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
+{
+ unsigned long long temp;
+
+ if (!user_mode(xcp)) {
+ *perr = 0;
+ return (*(unsigned long long *) va);
+ } else {
+ /* Use kernel get_user() macro */
+ *perr = (int) get_user(temp, (unsigned long long *) va);
+ return temp;
+ }
+}
+
+static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
+{
+ if (!user_mode(xcp)) {
+ *(unsigned long *) va = val;
+ return 0;
+ } else {
+ /* Use kernel get_user() macro */
+ return (int) put_user(val, (unsigned long *) va);
+ }
+}
+
+static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
+{
+ if (!user_mode(xcp)) {
+ *(unsigned long long *) va = val;
+ return 0;
+ } else {
+ /* Use kernel get_user() macro */
+ return (int) put_user(val, (unsigned long long *) va);
+ }
+}
+
+
+/*
+ * In the Linux kernel, we support selection of FPR format on the
+ * basis of the Status.FR bit. This does imply that, if a full 32
+ * FPRs are desired, there needs to be a flip-flop that can be written
+ * to one at that bit position. In any case, normal MIPS ABI uses
+ * only the even FPRs (Status.FR = 0).
+ */
+
+#define CP0_STATUS_FR_SUPPORT
+
+/*
+ * Emulate the single floating point instruction pointed at by EPC.
+ * Two instructions if the instruction is in a branch delay slot.
+ */
+
+static int
+cop1Emulate(int xcptno, struct pt_regs *xcp,
+ struct mips_fpu_soft_struct *ctx)
+{
+ mips_instruction ir;
+ vaddr_t emulpc;
+ vaddr_t contpc;
+ unsigned int cond;
+ int err = 0;
+
+
+ ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
+ if (err) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+
+ /* XXX NEC Vr54xx bug workaround */
+ if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
+ xcp->cp0_cause &= ~CAUSEF_BD;
+
+ if (xcp->cp0_cause & CAUSEF_BD) {
+ /*
+ * The instruction to be emulated is in a branch delay slot
+ * which means that we have to emulate the branch instruction
+ * BEFORE we do the cop1 instruction.
+ *
+ * This branch could be a COP1 branch, but in that case we
+ * would have had a trap for that instruction, and would not
+ * come through this route.
+ *
+ * Linux MIPS branch emulator operates on context, updating the
+ * cp0_epc.
+ */
+ emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */
+
+ if (__compute_return_epc(xcp)) {
+#ifdef CP1DBG
+ _mon_printf("failed to emulate branch at %p\n",
+ REG_TO_VA(xcp->cp0_epc));
+#endif
+ return SIGILL;;
+ }
+ ir = mips_get_word(xcp, emulpc, &err);
+ if (err) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ contpc = REG_TO_VA xcp->cp0_epc;
+ } else {
+ emulpc = REG_TO_VA xcp->cp0_epc;
+ contpc = REG_TO_VA xcp->cp0_epc + 4;
+ }
+
+ emul:
+ fpuemuprivate.stats.emulated++;
+ switch (MIPSInst_OPCODE(ir)) {
+#ifdef CP0_STATUS_FR_SUPPORT
+ /* R4000+ 64-bit fpu registers */
+#ifndef SINGLE_ONLY_FPU
+ case ldc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ int ft = MIPSInst_RT(ir);
+ if (!(xcp->cp0_status & ST0_FR))
+ ft &= ~1;
+ ctx->regs[ft] = mips_get_dword(xcp, va, &err);
+ fpuemuprivate.stats.loads++;
+ if (err) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+
+ case sdc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ int ft = MIPSInst_RT(ir);
+ if (!(xcp->cp0_status & ST0_FR))
+ ft &= ~1;
+ fpuemuprivate.stats.stores++;
+ if (mips_put_dword(xcp, va, ctx->regs[ft])) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+#endif
+
+ case lwc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ fpureg_t val;
+ int ft = MIPSInst_RT(ir);
+ fpuemuprivate.stats.loads++;
+ val = mips_get_word(xcp, va, &err);
+ if (err) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ if (xcp->cp0_status & ST0_FR) {
+ /* load whole register */
+ ctx->regs[ft] = val;
+ } else if (ft & 1) {
+ /* load to m.s. 32 bits */
+#ifdef SINGLE_ONLY_FPU
+ /* illegal register in single-float mode */
+ return SIGILL;
+#else
+ ctx->regs[(ft & ~1)] &= 0xffffffff;
+ ctx->regs[(ft & ~1)] |= val << 32;
+#endif
+ } else {
+ /* load to l.s. 32 bits */
+ ctx->regs[ft] &= ~0xffffffffLL;
+ ctx->regs[ft] |= val;
+ }
+ }
+ break;
+
+ case swc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ unsigned int val;
+ int ft = MIPSInst_RT(ir);
+ fpuemuprivate.stats.stores++;
+ if (xcp->cp0_status & ST0_FR) {
+ /* store whole register */
+ val = ctx->regs[ft];
+ } else if (ft & 1) {
+#ifdef SINGLE_ONLY_FPU
+ /* illegal register in single-float mode */
+ return SIGILL;
+#else
+ /* store from m.s. 32 bits */
+ val = ctx->regs[(ft & ~1)] >> 32;
+#endif
+ } else {
+ /* store from l.s. 32 bits */
+ val = ctx->regs[ft];
+ }
+ if (mips_put_word(xcp, va, val)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+#else /* old 32-bit fpu registers */
+ case lwc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ ctx->regs[MIPSInst_RT(ir)] =
+ mips_get_word(xcp, va, &err);
+ fpuemuprivate.stats.loads++;
+ if (err) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+
+ case swc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ fpuemuprivate.stats.stores++;
+ if (mips_put_word
+ (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+ case ldc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ unsigned int rt = MIPSInst_RT(ir) & ~1;
+ int errs = 0;
+ fpuemuprivate.stats.loads++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+ ctx->regs[rt + 1] =
+ mips_get_word(xcp, va + 0, &err);
+ errs += err;
+ ctx->regs[rt + 0] =
+ mips_get_word(xcp, va + 4, &err);
+ errs += err;
+#else
+ ctx->regs[rt + 0] =
+ mips_get_word(xcp, va + 0, &err);
+ errs += err;
+ ctx->regs[rt + 1] =
+ mips_get_word(xcp, va + 4, &err);
+ errs += err;
+#endif
+ if (err)
+ return SIGBUS;
+ }
+ break;
+
+ case sdc1_op:
+ {
+ void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+ + MIPSInst_SIMM(ir);
+ unsigned int rt = MIPSInst_RT(ir) & ~1;
+ fpuemuprivate.stats.stores++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+ if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
+ return SIGBUS;
+ if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
+ return SIGBUS;
+#else
+ if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
+ return SIGBUS;
+ if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
+ return SIGBUS;
+#endif
+ }
+ break;
+#endif
+
+ case cop1_op:
+ switch (MIPSInst_RS(ir)) {
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case dmfc_op:
+ /* copregister fs -> gpr[rt] */
+ if (MIPSInst_RT(ir) != 0) {
+ int fs = MIPSInst_RD(ir);
+ if (!(xcp->cp0_status & ST0_FR))
+ fs &= ~1;
+ xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
+ }
+ break;
+
+ case dmtc_op:
+ /* copregister fs <- rt */
+ {
+ fpureg_t value;
+ int fs = MIPSInst_RD(ir);
+ if (!(xcp->cp0_status & ST0_FR))
+ fs &= ~1;
+ value =
+ (MIPSInst_RT(ir) ==
+ 0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+ ctx->regs[fs] = value;
+ }
+ break;
+#endif
+
+ case mfc_op:
+ /* copregister rd -> gpr[rt] */
+ if (MIPSInst_RT(ir) != 0) {
+ /* default value from l.s. 32 bits */
+ int value = ctx->regs[MIPSInst_RD(ir)];
+ if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+ /* illegal register in single-float mode */
+ return SIGILL;
+#else
+ if (!(xcp->cp0_status & ST0_FR)) {
+ /* move from m.s. 32 bits */
+ value =
+ ctx->
+ regs[MIPSInst_RD(ir) &
+ ~1] >> 32;
+ }
+#endif
+ }
+ xcp->regs[MIPSInst_RT(ir)] = value;
+ }
+ break;
+
+ case mtc_op:
+ /* copregister rd <- rt */
+ {
+ fpureg_t value;
+ if (MIPSInst_RT(ir) == 0)
+ value = 0;
+ else
+ value =
+ (unsigned int) xcp->
+ regs[MIPSInst_RT(ir)];
+ if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+ /* illegal register in single-float mode */
+ return SIGILL;
+#else
+ if (!(xcp->cp0_status & ST0_FR)) {
+ /* move to m.s. 32 bits */
+ ctx->
+ regs[
+ (MIPSInst_RD(ir) &
+ ~1)] &=
+ 0xffffffff;
+ ctx->
+ regs[
+ (MIPSInst_RD(ir) &
+ ~1)] |=
+ value << 32;
+ break;
+ }
+#endif
+ }
+ /* move to l.s. 32 bits */
+ ctx->regs[MIPSInst_RD(ir)] &=
+ ~0xffffffffLL;
+ ctx->regs[MIPSInst_RD(ir)] |= value;
+ }
+ break;
+#else
+
+ case mfc_op:
+ /* copregister rd -> gpr[rt] */
+ if (MIPSInst_RT(ir) != 0) {
+ unsigned value =
+ ctx->regs[MIPSInst_RD(ir)];
+ xcp->regs[MIPSInst_RT(ir)] = value;
+ }
+ break;
+
+ case mtc_op:
+ /* copregister rd <- rt */
+ {
+ unsigned value;
+ value =
+ (MIPSInst_RT(ir) ==
+ 0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+ ctx->regs[MIPSInst_RD(ir)] = value;
+ }
+ break;
+#endif
+
+ case cfc_op:
+ /* cop control register rd -> gpr[rt] */
+ {
+ unsigned value;
+
+ if (MIPSInst_RD(ir) == FPCREG_CSR) {
+ value = ctx->sr;
+#ifdef CSRTRACE
+ _mon_printf
+ ("%p gpr[%d]<-csr=%08x\n",
+ REG_TO_VA(xcp->cp0_epc),
+ MIPSInst_RT(ir), value);
+#endif
+ } else if (MIPSInst_RD(ir) == FPCREG_RID)
+ value = 0;
+ else
+ value = 0;
+ if (MIPSInst_RT(ir))
+ xcp->regs[MIPSInst_RT(ir)] = value;
+ }
+ break;
+
+ case ctc_op:
+ /* copregister rd <- rt */
+ {
+ unsigned value;
+
+ if (MIPSInst_RT(ir) == 0)
+ value = 0;
+ else
+ value = xcp->regs[MIPSInst_RT(ir)];
+
+ /* we only have one writable control reg
+ */
+ if (MIPSInst_RD(ir) == FPCREG_CSR) {
+#ifdef CSRTRACE
+ _mon_printf
+ ("%p gpr[%d]->csr=%08x\n",
+ REG_TO_VA(xcp->cp0_epc),
+ MIPSInst_RT(ir), value);
+#endif
+ ctx->sr = value;
+ /* copy new rounding mode to ieee library state! */
+ ieee754_csr.rm =
+ ieee_rm[value & 0x3];
+ }
+ }
+ break;
+
+ case bc_op:
+ if (xcp->cp0_cause & CAUSEF_BD) {
+ return SIGILL;
+ }
+ {
+ int likely = 0;
+
+#if __mips >= 4
+ cond =
+ ctx->
+ sr & fpucondbit[MIPSInst_RT(ir) >> 2];
+#else
+ cond = ctx->sr & FPU_CSR_COND;
+#endif
+ switch (MIPSInst_RT(ir) & 3) {
+ case bcfl_op:
+ likely = 1;
+ case bcf_op:
+ cond = !cond;
+ break;
+ case bctl_op:
+ likely = 1;
+ case bct_op:
+ break;
+ default:
+ /* thats an illegal instruction */
+ return SIGILL;
+ }
+
+ xcp->cp0_cause |= CAUSEF_BD;
+ if (cond) {
+ /* branch taken: emulate dslot instruction */
+ xcp->cp0_epc += 4;
+ contpc =
+ REG_TO_VA xcp->cp0_epc +
+ (MIPSInst_SIMM(ir) << 2);
+
+ ir =
+ mips_get_word(xcp,
+ REG_TO_VA(xcp->
+ cp0_epc),
+ &err);
+ if (err) {
+ fpuemuprivate.stats.
+ errors++;
+ return SIGBUS;
+ }
+
+ switch (MIPSInst_OPCODE(ir)) {
+ case lwc1_op:
+ case swc1_op:
+#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+ case ldc1_op:
+ case sdc1_op:
+#endif
+ case cop1_op:
+#if __mips >= 4 && __mips != 32
+ case cop1x_op:
+#endif
+ /* its one of ours */
+ goto emul;
+#if __mips >= 4
+ case spec_op:
+ if (MIPSInst_FUNC(ir) ==
+ movc_op) goto emul;
+ break;
+#endif
+ }
+
+ /* single step the non-cp1 instruction in the dslot */
+ return mips_dsemul(xcp, ir,
+ contpc);
+ } else {
+ /* branch not taken */
+ if (likely)
+ /* branch likely nullifies dslot if not taken */
+ xcp->cp0_epc += 4;
+ /* else continue & execute dslot as normal insn */
+ }
+ }
+ break;
+
+ default:
+ if (!(MIPSInst_RS(ir) & 0x10)) {
+ return SIGILL;
+ }
+ /* a real fpu computation instruction */
+ {
+ int sig;
+ if ((sig = fpu_emu(xcp, ctx, ir)))
+ return sig;
+ }
+ }
+ break;
+
+#if __mips >= 4 && __mips != 32
+ case cop1x_op:
+ {
+ int sig;
+ if ((sig = fpux_emu(xcp, ctx, ir)))
+ return sig;
+ }
+ break;
+#endif
+
+#if __mips >= 4
+ case spec_op:
+ if (MIPSInst_FUNC(ir) != movc_op)
+ return SIGILL;
+ cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+ if (((ctx->sr & cond) != 0) !=
+ ((MIPSInst_RT(ir) & 1) != 0)) return 0;
+ xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+ break;
+#endif
+
+ default:
+ return SIGILL;
+ }
+
+ /* we did it !! */
+ xcp->cp0_epc = VA_TO_REG(contpc);
+ xcp->cp0_cause &= ~CAUSEF_BD;
+ return 0;
+}
+
+/*
+ * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when
+ * we have to emulate the instruction in a COP1 branch delay slot. Do
+ * not change cp0_epc due to the instruction
+ *
+ * According to the spec:
+ * 1) it shouldnt be a branch :-)
+ * 2) it can be a COP instruction :-(
+ * 3) if we are tring to run a protected memory space we must take
+ * special care on memory access instructions :-(
+ */
+
+/*
+ * "Trampoline" return routine to catch exception following
+ * execution of delay-slot instruction execution.
+ */
+
+int do_dsemulret(struct pt_regs *xcp)
+{
+#ifdef DSEMUL_TRACE
+ _mon_printf("desemulret\n");
+#endif
+ /* Set EPC to return to post-branch instruction */
+ xcp->cp0_epc = current->thread.dsemul_epc;
+ /*
+ * Clear the state that got us here.
+ */
+ current->thread.dsemul_aerpc = (unsigned long) 0;
+
+ return 0;
+}
+
+
+#define AdELOAD 0x8c000001 /* lw $0,1($0) */
+
+static int
+mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
+{
+ mips_instruction *dsemul_insns;
+ mips_instruction forcetrap;
+ extern asmlinkage void handle_dsemulret(void);
+
+ if (ir == 0) { /* a nop is easy */
+ xcp->cp0_epc = VA_TO_REG(cpc);
+ return 0;
+ }
+#ifdef DSEMUL_TRACE
+ _mon_printf("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc);
+#endif
+
+ /*
+ * The strategy is to push the instruction onto the user stack
+ * and put a trap after it which we can catch and jump to
+ * the required address any alternative apart from full
+ * instruction emulation!!.
+ */
+ dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
+ dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */
+ /* Verify that the stack pointer is not competely insane */
+ if (verify_area
+ (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2))
+ return SIGBUS;
+
+ if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
+ fpuemuprivate.stats.errors++;
+ return (SIGBUS);
+ }
+
+ /*
+ * Algorithmics used a system call instruction, and
+ * borrowed that vector. MIPS/Linux version is a bit
+ * more heavyweight in the interests of portability and
+ * multiprocessor support. We flag the thread for special
+ * handling in the unaligned access handler and force an
+ * address error excpetion.
+ */
+
+ /* If one is *really* paranoid, one tests for a bad stack pointer */
+ if ((xcp->regs[29] & 0x3) == 0x3)
+ forcetrap = AdELOAD - 1;
+ else
+ forcetrap = AdELOAD;
+
+ if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
+ fpuemuprivate.stats.errors++;
+ return (SIGBUS);
+ }
+
+ /* Set thread state to catch and handle the exception */
+ current->thread.dsemul_epc = (unsigned long) cpc;
+ current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
+ xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
+
+ /* What we'd really like to do is just flush the line(s) of the */
+ /* icache containing the dsemulret instructions, but there's no */
+ /* mechanism to do this yet... */
+ flush_cache_all();
+ return SIGILL; /* force out of emulation loop */
+}
+
+/*
+ * Conversion table from MIPS compare ops 48-63
+ * cond = ieee754dp_cmp(x,y,IEEE754_UN);
+ */
+static const unsigned char cmptab[8] = {
+ 0, /* cmp_0 (sig) cmp_sf */
+ IEEE754_CUN, /* cmp_un (sig) cmp_ngle */
+ IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */
+ IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */
+ IEEE754_CLT, /* cmp_olt (sig) cmp_lt */
+ IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */
+ IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */
+ IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
+};
+
+#define SIFROMREG(si,x) ((si) = ctx->regs[x])
+#define SITOREG(si,x) (ctx->regs[x] = (int)(si))
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#define DIFROMREG(di,x) ((di) = ctx->regs[x])
+#define DITOREG(di,x) (ctx->regs[x] = (di))
+#endif
+
+#define SPFROMREG(sp,x) ((sp).bits = ctx->regs[x])
+#define SPTOREG(sp,x) (ctx->regs[x] = (sp).bits)
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#define DPFROMREG(dp,x) ((dp).bits = \
+ ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
+#define DPTOREG(dp,x) (ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\
+ = (dp).bits)
+#else
+/* Beware: MIPS COP1 doubles are always little_word endian in registers */
+#define DPFROMREG(dp,x) \
+ ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
+#define DPTOREG(dp,x) \
+ (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
+#endif
+
+#if __mips >= 4 && __mips != 32
+
+/*
+ * Additional MIPS4 instructions
+ */
+
+static ieee754dp fpemu_dp_recip(ieee754dp d)
+{
+ return ieee754dp_div(ieee754dp_one(0), d);
+}
+
+static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+{
+ return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
+}
+
+static ieee754sp fpemu_sp_recip(ieee754sp s)
+{
+ return ieee754sp_div(ieee754sp_one(0), s);
+}
+
+static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+{
+ return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
+}
+
+
+static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+ return ieee754dp_add(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+ return ieee754dp_sub(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+ return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
+}
+
+static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+ return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
+}
+
+
+static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+ return ieee754sp_add(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+ return ieee754sp_sub(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+ return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
+}
+
+static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+ return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
+}
+
+static int
+fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+ mips_instruction ir)
+{
+ unsigned rcsr = 0; /* resulting csr */
+
+ fpuemuprivate.stats.cp1xops++;
+
+ switch (MIPSInst_FMA_FFMT(ir)) {
+ case s_fmt: /* 0 */
+ {
+ ieee754sp(*handler) (ieee754sp, ieee754sp,
+ ieee754sp);
+ ieee754sp fd, fr, fs, ft;
+
+ switch (MIPSInst_FUNC(ir)) {
+ case lwxc1_op:
+ {
+ void *va =
+ REG_TO_VA(xcp->
+ regs[MIPSInst_FR(ir)]
+ +
+ xcp->
+ regs[MIPSInst_FT
+ (ir)]);
+ fpureg_t val;
+ int err = 0;
+ val = mips_get_word(xcp, va, &err);
+ if (err) {
+ fpuemuprivate.stats.
+ errors++;
+ return SIGBUS;
+ }
+ if (xcp->cp0_status & ST0_FR) {
+ /* load whole register */
+ ctx->
+ regs[MIPSInst_FD(ir)] =
+ val;
+ } else if (MIPSInst_FD(ir) & 1) {
+ /* load to m.s. 32 bits */
+#if defined(SINGLE_ONLY_FPU)
+ /* illegal register in single-float mode */
+ return SIGILL;
+#else
+ ctx->
+ regs[
+ (MIPSInst_FD(ir) &
+ ~1)] &=
+ 0xffffffff;
+ ctx->
+ regs[
+ (MIPSInst_FD(ir) &
+ ~1)] |=
+ val << 32;
+#endif
+ } else {
+ /* load to l.s. 32 bits */
+ ctx->
+ regs[MIPSInst_FD(ir)]
+ &= ~0xffffffffLL;
+ ctx->
+ regs[MIPSInst_FD(ir)]
+ |= val;
+ }
+ }
+ break;
+
+ case swxc1_op:
+ {
+ void *va =
+ REG_TO_VA(xcp->
+ regs[MIPSInst_FR(ir)]
+ +
+ xcp->
+ regs[MIPSInst_FT
+ (ir)]);
+ unsigned int val;
+ if (xcp->cp0_status & ST0_FR) {
+ /* store whole register */
+ val =
+ ctx->
+ regs[MIPSInst_FS(ir)];
+ } else if (MIPSInst_FS(ir) & 1) {
+#if defined(SINGLE_ONLY_FPU)
+ /* illegal register in single-float mode */
+ return SIGILL;
+#else
+ /* store from m.s. 32 bits */
+ val =
+ ctx->
+ regs[
+ (MIPSInst_FS(ir) &
+ ~1)] >> 32;
+#endif
+ } else {
+ /* store from l.s. 32 bits */
+ val =
+ ctx->
+ regs[MIPSInst_FS(ir)];
+ }
+ if (mips_put_word(xcp, va, val)) {
+ fpuemuprivate.stats.
+ errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+
+ case madd_s_op:
+ handler = fpemu_sp_madd;
+ goto scoptop;
+ case msub_s_op:
+ handler = fpemu_sp_msub;
+ goto scoptop;
+ case nmadd_s_op:
+ handler = fpemu_sp_nmadd;
+ goto scoptop;
+ case nmsub_s_op:
+ handler = fpemu_sp_nmsub;
+ goto scoptop;
+
+ scoptop:
+ SPFROMREG(fr, MIPSInst_FR(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ fd = (*handler) (fr, fs, ft);
+ SPTOREG(fd, MIPSInst_FD(ir));
+
+ copcsr:
+ if (ieee754_cxtest(IEEE754_INEXACT))
+ rcsr |=
+ FPU_CSR_INE_X | FPU_CSR_INE_S;
+ if (ieee754_cxtest(IEEE754_UNDERFLOW))
+ rcsr |=
+ FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+ if (ieee754_cxtest(IEEE754_OVERFLOW))
+ rcsr |=
+ FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+ if (ieee754_cxtest
+ (IEEE754_INVALID_OPERATION)) rcsr |=
+ FPU_CSR_INV_X | FPU_CSR_INV_S;
+
+ ctx->sr =
+ (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+ if ((ctx->sr >> 5) & ctx->
+ sr & FPU_CSR_ALL_E) {
+ /*_mon_printf ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+ return SIGFPE;
+ }
+
+ break;
+
+ default:
+ return SIGILL;
+ }
+ }
+ break;
+
+#if !defined(SINGLE_ONLY_FPU)
+ case d_fmt: /* 1 */
+ {
+ ieee754dp(*handler) (ieee754dp, ieee754dp,
+ ieee754dp);
+ ieee754dp fd, fr, fs, ft;
+
+ switch (MIPSInst_FUNC(ir)) {
+ case ldxc1_op:
+ {
+ void *va =
+ REG_TO_VA(xcp->
+ regs[MIPSInst_FR(ir)]
+ +
+ xcp->
+ regs[MIPSInst_FT
+ (ir)]);
+ int err = 0;
+ ctx->regs[MIPSInst_FD(ir)] =
+ mips_get_dword(xcp, va, &err);
+ if (err) {
+ fpuemuprivate.stats.
+ errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+
+ case sdxc1_op:
+ {
+ void *va =
+ REG_TO_VA(xcp->
+ regs[MIPSInst_FR(ir)]
+ +
+ xcp->
+ regs[MIPSInst_FT
+ (ir)]);
+ if (mips_put_dword
+ (xcp, va,
+ ctx->regs[MIPSInst_FS(ir)])) {
+ fpuemuprivate.stats.
+ errors++;
+ return SIGBUS;
+ }
+ }
+ break;
+
+ case madd_d_op:
+ handler = fpemu_dp_madd;
+ goto dcoptop;
+ case msub_d_op:
+ handler = fpemu_dp_msub;
+ goto dcoptop;
+ case nmadd_d_op:
+ handler = fpemu_dp_nmadd;
+ goto dcoptop;
+ case nmsub_d_op:
+ handler = fpemu_dp_nmsub;
+ goto dcoptop;
+
+ dcoptop:
+ DPFROMREG(fr, MIPSInst_FR(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ fd = (*handler) (fr, fs, ft);
+ DPTOREG(fd, MIPSInst_FD(ir));
+ goto copcsr;
+
+ default:
+ return SIGILL;
+ }
+ }
+ break;
+#endif
+
+ case 0x7: /* 7 */
+ {
+ if (MIPSInst_FUNC(ir) != pfetch_op) {
+ return SIGILL;
+ }
+ /* ignore prefx operation */
+ }
+ break;
+
+ default:
+ return SIGILL;
+ }
+
+ return 0;
+}
+#endif
+
+
+
+/*
+ * Emulate a single COP1 arithmetic instruction.
+ */
+static int
+fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+ mips_instruction ir)
+{
+ int rfmt; /* resulting format */
+ unsigned rcsr = 0; /* resulting csr */
+ unsigned cond;
+ union {
+ ieee754dp d;
+ ieee754sp s;
+ int w;
+#if __mips64
+ long long l;
+#endif
+ } rv; /* resulting value */
+
+ fpuemuprivate.stats.cp1ops++;
+ switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+
+ case s_fmt:{ /* 0 */
+ ieee754sp(*handler) ();
+
+ switch (MIPSInst_FUNC(ir)) {
+ /* binary ops */
+ case fadd_op:
+ handler = ieee754sp_add;
+ goto scopbop;
+ case fsub_op:
+ handler = ieee754sp_sub;
+ goto scopbop;
+ case fmul_op:
+ handler = ieee754sp_mul;
+ goto scopbop;
+ case fdiv_op:
+ handler = ieee754sp_div;
+ goto scopbop;
+
+ /* unary ops */
+#if __mips >= 2 || __mips64
+ case fsqrt_op:
+ handler = ieee754sp_sqrt;
+ goto scopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+ case frsqrt_op:
+ handler = fpemu_sp_rsqrt;
+ goto scopuop;
+ case frecip_op:
+ handler = fpemu_sp_recip;
+ goto scopuop;
+#endif
+#if __mips >= 4
+ case fmovc_op:
+ cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+ if (((ctx->sr & cond) != 0) !=
+ ((MIPSInst_FT(ir) & 1) != 0))
+ return 0;
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+ case fmovz_op:
+ if (xcp->regs[MIPSInst_FT(ir)] != 0)
+ return 0;
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+ case fmovn_op:
+ if (xcp->regs[MIPSInst_FT(ir)] == 0)
+ return 0;
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+#endif
+ case fabs_op:
+ handler = ieee754sp_abs;
+ goto scopuop;
+ case fneg_op:
+ handler = ieee754sp_neg;
+ goto scopuop;
+ case fmov_op:
+ /* an easy one */
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+ /* binary op on handler */
+scopbop:
+ {
+ ieee754sp fs, ft;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+
+ rv.s = (*handler) (fs, ft);
+ goto copcsr;
+ }
+scopuop:
+ {
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = (*handler) (fs);
+ goto copcsr;
+ }
+copcsr:
+ if (ieee754_cxtest(IEEE754_INEXACT))
+ rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+ if (ieee754_cxtest(IEEE754_UNDERFLOW))
+ rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+ if (ieee754_cxtest(IEEE754_OVERFLOW))
+ rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+ if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+ rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
+ if (ieee754_cxtest
+ (IEEE754_INVALID_OPERATION)) rcsr |=
+ FPU_CSR_INV_X | FPU_CSR_INV_S;
+ break;
+
+ /* unary conv ops */
+ case fcvts_op:
+ return SIGILL; /* not defined */
+ case fcvtd_op:
+#if defined(SINGLE_ONLY_FPU)
+ return SIGILL; /* not defined */
+#else
+ {
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fsp(fs);
+ rfmt = d_fmt;
+ goto copcsr;
+ }
+#endif
+ case fcvtw_op:
+ {
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.w = ieee754sp_tint(fs);
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+
+#if __mips >= 2 || __mips64
+ case fround_op:
+ case ftrunc_op:
+ case fceil_op:
+ case ffloor_op:
+ {
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.w = ieee754sp_tint(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+#endif /* __mips >= 2 */
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case fcvtl_op:
+ {
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.l = ieee754sp_tlong(fs);
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+
+ case froundl_op:
+ case ftruncl_op:
+ case fceill_op:
+ case ffloorl_op:
+ {
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.l = ieee754sp_tlong(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+#endif /* __mips64 && !fpu(single) */
+
+ default:
+ if (MIPSInst_FUNC(ir) >= fcmp_op) {
+ unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+ ieee754sp fs, ft;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+ rfmt = -1;
+ if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ } else {
+ return SIGILL;
+ }
+ break;
+ }
+ break;
+ }
+
+#if !defined(SINGLE_ONLY_FPU)
+ case d_fmt: {
+ ieee754dp(*handler) ();
+
+ switch (MIPSInst_FUNC(ir)) {
+ /* binary ops */
+ case fadd_op:
+ handler = ieee754dp_add;
+ goto dcopbop;
+ case fsub_op:
+ handler = ieee754dp_sub;
+ goto dcopbop;
+ case fmul_op:
+ handler = ieee754dp_mul;
+ goto dcopbop;
+ case fdiv_op:
+ handler = ieee754dp_div;
+ goto dcopbop;
+
+ /* unary ops */
+#if __mips >= 2 || __mips64
+ case fsqrt_op:
+ handler = ieee754dp_sqrt;
+ goto dcopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+ case frsqrt_op:
+ handler = fpemu_dp_rsqrt;
+ goto dcopuop;
+ case frecip_op:
+ handler = fpemu_dp_recip;
+ goto dcopuop;
+#endif
+#if __mips >= 4
+ case fmovc_op:
+ cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+ if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
+ return 0;
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+ case fmovz_op:
+ if (xcp->regs[MIPSInst_FT(ir)] != 0)
+ return 0;
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+ case fmovn_op:
+ if (xcp->regs[MIPSInst_FT(ir)] == 0)
+ return 0;
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+#endif
+ case fabs_op:
+ handler = ieee754dp_abs;
+ goto dcopuop;
+ case fneg_op:
+ handler = ieee754dp_neg;
+ goto dcopuop;
+ case fmov_op:
+ /* an easy one */
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+
+ /* binary op on handler */
+dcopbop:
+ {
+ ieee754dp fs, ft;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+
+ rv.d = (*handler) (fs, ft);
+ goto copcsr;
+ }
+dcopuop:
+ {
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = (*handler) (fs);
+ goto copcsr;
+ }
+
+ /* unary conv ops */
+ case fcvts_op:
+ {
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fdp(fs);
+ rfmt = s_fmt;
+ goto copcsr;
+ }
+ case fcvtd_op:
+ return SIGILL; /* not defined */
+ case fcvtw_op:
+ {
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.w = ieee754dp_tint(fs); /* wrong */
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+
+#if __mips >= 2 || __mips64
+ case fround_op:
+ case ftrunc_op:
+ case fceil_op:
+ case ffloor_op:
+ {
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.w = ieee754dp_tint(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+#endif
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case fcvtl_op:
+ {
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.l = ieee754dp_tlong(fs);
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+
+ case froundl_op:
+ case ftruncl_op:
+ case fceill_op:
+ case ffloorl_op:
+ {
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.l = ieee754dp_tlong(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+#endif /* __mips >= 3 && !fpu(single) */
+
+ default:
+ if (MIPSInst_FUNC(ir) >= fcmp_op) {
+ unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+ ieee754dp fs, ft;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+ rfmt = -1;
+ if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ } else {
+ return SIGILL;
+ }
+ break;
+ }
+ break;
+ }
+#endif /* !defined(SINGLE_ONLY_FPU) */
+
+ case w_fmt: {
+ switch (MIPSInst_FUNC(ir)) {
+ case fcvts_op:
+ /* convert word to single precision real */
+ rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+ rfmt = s_fmt;
+ goto copcsr;
+#if !defined(SINGLE_ONLY_FPU)
+ case fcvtd_op:
+ /* convert word to double precision real */
+ rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+ rfmt = d_fmt;
+ goto copcsr;
+#endif
+ default:
+ return SIGILL;
+ }
+ break;
+ }
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case l_fmt: {
+ switch (MIPSInst_FUNC(ir)) {
+ case fcvts_op:
+ /* convert long to single precision real */
+ rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+ rfmt = s_fmt;
+ goto copcsr;
+ case fcvtd_op:
+ /* convert long to double precision real */
+ rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+ rfmt = d_fmt;
+ goto copcsr;
+ default:
+ return SIGILL;
+ }
+ break;
+ }
+#endif
+
+ default:
+ return SIGILL;
+ }
+
+ /*
+ * Update the fpu CSR register for this operation.
+ * If an exception is required, generate a tidy SIGFPE exception,
+ * without updating the result register.
+ * Note: cause exception bits do not accumulate, they are rewritten
+ * for each op; only the flag/sticky bits accumulate.
+ */
+ ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+ if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
+ /*_mon_printf ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+ return SIGFPE;
+ }
+
+ /*
+ * Now we can safely write the result back to the register file.
+ */
+ switch (rfmt) {
+ case -1: {
+#if __mips >= 4
+ cond = fpucondbit[MIPSInst_FD(ir) >> 2];
+#else
+ cond = FPU_CSR_COND;
+#endif
+ if (rv.w)
+ ctx->sr |= cond;
+ else
+ ctx->sr &= ~cond;
+ break;
+ }
+#if !defined(SINGLE_ONLY_FPU)
+ case d_fmt:
+ DPTOREG(rv.d, MIPSInst_FD(ir));
+ break;
+#endif
+ case s_fmt:
+ SPTOREG(rv.s, MIPSInst_FD(ir));
+ break;
+ case w_fmt:
+ SITOREG(rv.w, MIPSInst_FD(ir));
+ break;
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case l_fmt:
+ DITOREG(rv.l, MIPSInst_FD(ir));
+ break;
+#endif
+ default:
+ return SIGILL;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Emulate the floating point instruction at EPC, and continue
+ * to run until we hit a non-fp instruction, or a backward
+ * branch. This cuts down dramatically on the per instruction
+ * exception overhead.
+ */
+int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp)
+{
+ struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+ unsigned long oldepc, prevepc;
+ unsigned int insn;
+ int sig = 0;
+ int err = 0;
+
+ oldepc = xcp->cp0_epc;
+ do {
+ prevepc = xcp->cp0_epc;
+ insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
+ if (err) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ if (insn != 0)
+ sig = cop1Emulate(xcptno, xcp, ctx);
+ else
+ xcp->cp0_epc += 4; /* skip nops */
+ } while (xcp->cp0_epc > prevepc && sig == 0);
+
+ /* SIGILL indicates a non-fpu instruction */
+ if (sig == SIGILL && xcp->cp0_epc != oldepc)
+ /* but if epc has advanced, then ignore it */
+ sig = 0;
+
+ return sig;
+}
+
+
+#ifdef NOTDEF
+/*
+ * Patch up the hardware fpu state when an f.p. exception occurs.
+ */
+static int cop1Patcher(int xcptno, struct pt_regs *xcp)
+{
+ struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+ unsigned sr;
+ int sig;
+
+ /* reenable Cp1, else fpe_save() will get nested exception */
+ sr = mips_bissr(ST0_CU1);
+
+ /* get fpu registers and status, then clear pending exceptions */
+ fpe_save(ctx);
+ fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
+
+ /* get current rounding mode for IEEE library, and emulate insn */
+ ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
+ sig = cop1Emulate(xcptno, xcp, ctx);
+
+ /* don't return with f.p. exceptions pending */
+ ctx->sr &= ~FPU_CSR_ALL_X;
+ fpe_restore(ctx);
+
+ mips_setsr(sr);
+ return sig;
+}
+
+void _cop1_init(int emulate)
+{
+ extern int _nofpu;
+
+ if (emulate) {
+ /*
+ * Install cop1 emulator to handle "coprocessor unusable" exception
+ */
+ xcption(XCPTCPU, cop1Handler);
+ fpuemuactive = 1; /* tell dbg.c that we are in charge */
+ _nofpu = 0; /* tell setjmp() it "has" an fpu */
+ } else {
+ /*
+ * Install cop1 emulator for floating point exceptions only,
+ * i.e. denormalised results, underflow, overflow etc, which
+ * must be emulated in s/w.
+ */
+#ifdef 1
+ /* r4000 or above use dedicate exception */
+ xcption(XCPTFPE, cop1Patcher);
+#else
+ /* r3000 et al use interrupt */
+ extern int _sbd_getfpuintr(void);
+ int intno = _sbd_getfpuintr();
+ intrupt(intno, cop1Patcher, 0);
+ mips_bissr(SR_IM0 << intno);
+#endif
+
+#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
+ /* For R4640/R4650 compiled *without* the -msingle-float flag,
+ then we share responsibility: the h/w handles the single
+ precision operations, and the trap emulator handles the
+ double precision. We set fpuemuactive so that dbg.c first
+ fetches the s/w state before saving the h/w state. */
+ fpuemuactive = 1;
+ {
+ int i;
+ /* initialise the unused d.p high order words to be NaN */
+ for (i = 0; i < 32; i++)
+ current->thread.fpu.soft.regs[i] =
+ 0x7ff80bad00000000LL;
+ }
+#endif /* (r4640 || r4650) && !fpu(single) */
+ }
+}
+#endif
diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c
new file mode 100644
index 000000000..0c6ad8b24
--- /dev/null
+++ b/arch/mips/math-emu/dp_add.c
@@ -0,0 +1,193 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ CLEARCX;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y, "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x, "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754dp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Inifity handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs == ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ else
+ return ieee754dp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ /* FALL THROUGH */
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* provide guard,round and stick bit space */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ ym = XDPSRS(ym, s);
+ ye += s;
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ xm = XDPSRS(xm, s);
+ xe += s;
+ }
+ assert(xe == ye);
+ assert(xe <= DP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm,xs,xe
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+ xm = XDPSRS1(xm);
+ xe++;
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0)
+ return ieee754dp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ /* normalize to rounding precision */
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+
+ }
+ DPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c
new file mode 100644
index 000000000..83cbda357
--- /dev/null
+++ b/arch/mips/math-emu/dp_cmp.c
@@ -0,0 +1,65 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp)
+{
+ CLEARCX;
+
+ if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+ if (cmp & IEEE754_CUN)
+ return 1;
+ if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+ if (SETCX(IEEE754_INVALID_OPERATION))
+ return ieee754si_xcpt(0, "fcmpf", x);
+ }
+ return 0;
+ } else {
+ long long int vx = x.bits;
+ long long int vy = y.bits;
+
+ if (vx < 0)
+ vx = -vx ^ DP_SIGN_BIT;
+ if (vy < 0)
+ vy = -vy ^ DP_SIGN_BIT;
+
+ if (vx < vy)
+ return (cmp & IEEE754_CLT) != 0;
+ else if (vx == vy)
+ return (cmp & IEEE754_CEQ) != 0;
+ else
+ return (cmp & IEEE754_CGT) != 0;
+ }
+}
diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c
new file mode 100644
index 000000000..86d4ca1d7
--- /dev/null
+++ b/arch/mips/math-emu/dp_div.c
@@ -0,0 +1,167 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y, "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x, "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754dp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return ieee754dp_zero(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return ieee754dp_inf(xs ^ ys);
+
+ /* Zero handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_ZERO_DIVIDE);
+ return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ieee754dp_zero(xs == ys ? 0 : 1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* provide rounding space */
+ xm <<= 3;
+ ym <<= 3;
+
+ {
+ /* now the dirty work */
+
+ unsigned long long rm = 0;
+ int re = xe - ye;
+ unsigned long long bm;
+
+ for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
+ if (xm >= ym) {
+ xm -= ym;
+ rm |= bm;
+ if (xm == 0)
+ break;
+ }
+ xm <<= 1;
+ }
+ rm <<= 1;
+ if (xm)
+ rm |= 1; /* have remainder, set sticky */
+
+ assert(rm);
+
+ /* normalise rm to rounding precision ?
+ */
+ while ((rm >> (DP_MBITS + 3)) == 0) {
+ rm <<= 1;
+ re--;
+ }
+
+ DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
new file mode 100644
index 000000000..e393d1f37
--- /dev/null
+++ b/arch/mips/math-emu/dp_fint.c
@@ -0,0 +1,85 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fint(int x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ if (x == 0)
+ return ieee754dp_zero(0);
+ if (x == 1 || x == -1)
+ return ieee754dp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754dp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1 << 31))
+ xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+
+#if 1
+ /* normalize - result can never be inexact or overflow */
+ xe = DP_MBITS;
+ while ((xm >> DP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+#else
+ /* normalize */
+ xe = DP_MBITS + 3;
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ DPNORMRET1(xs, xe, xm, "fint", x);
+#endif
+}
+
+ieee754dp ieee754dp_funs(unsigned int u)
+{
+ if ((int) u < 0)
+ return ieee754dp_add(ieee754dp_1e31(),
+ ieee754dp_fint(u & ~(1 << 31)));
+ return ieee754dp_fint(u);
+}
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
new file mode 100644
index 000000000..dc0ae5e77
--- /dev/null
+++ b/arch/mips/math-emu/dp_flong.c
@@ -0,0 +1,83 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_flong(long long x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ if (x == 0)
+ return ieee754dp_zero(0);
+ if (x == 1 || x == -1)
+ return ieee754dp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754dp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1ULL << 63))
+ xm = (1ULL << 63); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+
+ /* normalize */
+ xe = DP_MBITS + 3;
+ if (xm >> (DP_MBITS + 1 + 3)) {
+ /* shunt out overflow bits */
+ while (xm >> (DP_MBITS + 1 + 3)) {
+ XDPSRSX1();
+ }
+ } else {
+ /* normalize in grs extended double precision */
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ DPNORMRET1(xs, xe, xm, "dp_flong", x);
+}
+
+ieee754dp ieee754dp_fulong(unsigned long long u)
+{
+ if ((long long) u < 0)
+ return ieee754dp_add(ieee754dp_1e63(),
+ ieee754dp_flong(u & ~(1ULL << 63)));
+ return ieee754dp_flong(u);
+}
diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c
new file mode 100644
index 000000000..6139e3668
--- /dev/null
+++ b/arch/mips/math-emu/dp_frexp.c
@@ -0,0 +1,60 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+/* close to ieeep754dp_logb
+*/
+ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+{
+ COMPXDP;
+ CLEARCX;
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *eptr = 0;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ *eptr = xe + 1;
+ return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c
new file mode 100644
index 000000000..0a03458bb
--- /dev/null
+++ b/arch/mips/math-emu/dp_fsp.c
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fsp(ieee754sp x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ return ieee754dp_nanxcpt(builddp(xs,
+ DP_EMAX + 1 + DP_EBIAS,
+ ((unsigned long long) xm
+ << (DP_MBITS -
+ SP_MBITS))), "fsp",
+ x);
+ case IEEE754_CLASS_INF:
+ return ieee754dp_inf(xs);
+ case IEEE754_CLASS_ZERO:
+ return ieee754dp_zero(xs);
+ case IEEE754_CLASS_DNORM:
+ /* normalize */
+ while ((xm >> SP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+
+ /* CANT possibly overflow,underflow, or need rounding
+ */
+
+ /* drop the hidden bit */
+ xm &= ~SP_HIDDEN_BIT;
+
+ return builddp(xs, xe + DP_EBIAS,
+ (unsigned long long) xm << (DP_MBITS - SP_MBITS));
+}
diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c
new file mode 100644
index 000000000..cd0ad950a
--- /dev/null
+++ b/arch/mips/math-emu/dp_logb.c
@@ -0,0 +1,61 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_logb(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754dp_nanxcpt(x, "logb", x);
+ case IEEE754_CLASS_QNAN:
+ return x;
+ case IEEE754_CLASS_INF:
+ return ieee754dp_inf(0);
+ case IEEE754_CLASS_ZERO:
+ return ieee754dp_inf(1);
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ return ieee754dp_fint(xe);
+}
diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c
new file mode 100644
index 000000000..74afa85c5
--- /dev/null
+++ b/arch/mips/math-emu/dp_modf.c
@@ -0,0 +1,87 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *ip = x;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ /* far to small */
+ *ip = ieee754dp_zero(xs);
+ return x;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe < 0) {
+ *ip = ieee754dp_zero(xs);
+ return x;
+ }
+ if (xe >= DP_MBITS) {
+ *ip = x;
+ return ieee754dp_zero(xs);
+ }
+ /* generate ipart mantissa by clearing bottom bits
+ */
+ *ip = builddp(xs, xe + DP_EBIAS,
+ ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
+ ~DP_HIDDEN_BIT);
+
+ /* generate fpart mantissa by clearing top bits
+ * and normalizing (must be able to normalize)
+ */
+ xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
+ if (xm == 0)
+ return ieee754dp_zero(xs);
+
+ while ((xm >> DP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c
new file mode 100644
index 000000000..70be81b10
--- /dev/null
+++ b/arch/mips/math-emu/dp_mul.c
@@ -0,0 +1,187 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y, "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x, "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754dp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handeling */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ return ieee754dp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return ieee754dp_zero(xs ^ ys);
+
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* rm = xm * ym, re = xe+ye basicly */
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+ {
+ int re = xe + ye;
+ int rs = xs ^ ys;
+ unsigned long long rm;
+
+ /* shunt to top of word */
+ xm <<= 64 - (DP_MBITS + 1);
+ ym <<= 64 - (DP_MBITS + 1);
+
+ /* multiply 32bits xm,ym to give high 32bits rm with stickness
+ */
+
+ /* 32 * 32 => 64 */
+#define DPXMULT(x,y) ((unsigned long long)(x) * (unsigned long long)y)
+
+ {
+ unsigned lxm = xm;
+ unsigned hxm = xm >> 32;
+ unsigned lym = ym;
+ unsigned hym = ym >> 32;
+ unsigned long long lrm;
+ unsigned long long hrm;
+
+ lrm = DPXMULT(lxm, lym);
+ hrm = DPXMULT(hxm, hym);
+
+ {
+ unsigned long long t = DPXMULT(lxm, hym);
+ {
+ unsigned long long at =
+ lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 32);
+ }
+
+ {
+ unsigned long long t = DPXMULT(hxm, lym);
+ {
+ unsigned long long at =
+ lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 32);
+ }
+ rm = hrm | (lrm != 0);
+ }
+
+ /*
+ * sticky shift down to normal rounding precision
+ */
+ if ((signed long long) rm < 0) {
+ rm =
+ (rm >> (64 - (DP_MBITS + 1 + 3))) |
+ ((rm << (DP_MBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm =
+ (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
+ ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (DP_HIDDEN_BIT << 3));
+ DPNORMRET2(rs, re, rm, "mul", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c
new file mode 100644
index 000000000..210f6d501
--- /dev/null
+++ b/arch/mips/math-emu/dp_scalb.c
@@ -0,0 +1,65 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754dp_nanxcpt(x, "scalb", x, n);
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ return x;
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+{
+ return ieee754dp_scalb(x, n);
+}
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
new file mode 100644
index 000000000..f13845007
--- /dev/null
+++ b/arch/mips/math-emu/dp_simple.c
@@ -0,0 +1,73 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+int ieee754dp_finite(ieee754dp x)
+{
+ return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+{
+ CLEARCX;
+ DPSIGN(x) = DPSIGN(y);
+ return x;
+}
+
+
+ieee754dp ieee754dp_neg(ieee754dp x)
+{
+ CLEARCX;
+
+ if (ieee754dp_isnan(x)) /* but not infinity */
+ return ieee754dp_nanxcpt(x, "neg", x);
+
+ /* quick fix up */
+ DPSIGN(x) ^= 1;
+ return x;
+}
+
+
+ieee754dp ieee754dp_abs(ieee754dp x)
+{
+ CLEARCX;
+
+ if (ieee754dp_isnan(x)) /* but not infinity */
+ return ieee754dp_nanxcpt(x, "abs", x);
+
+ /* quick fix up */
+ DPSIGN(x) = 0;
+ return x;
+}
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c
new file mode 100644
index 000000000..bd8f9c8ba
--- /dev/null
+++ b/arch/mips/math-emu/dp_sqrt.c
@@ -0,0 +1,174 @@
+/* IEEE754 floating point arithmetic
+ * double precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+static const struct ieee754dp_konst knan = {
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+ 0, 0, DP_EBIAS + DP_EMAX + 1, 0
+#else
+ 0, DP_EBIAS + DP_EMAX + 1, 0, 0
+#endif
+};
+
+#define nan ((ieee754dp)knan)
+
+static const unsigned table[] = {
+ 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
+ 29598, 36145, 43202, 50740, 58733, 67158, 75992,
+ 85215, 83599, 71378, 60428, 50647, 41945, 34246,
+ 27478, 21581, 16499, 12183, 8588, 5674, 3403,
+ 1742, 661, 130
+};
+
+ieee754dp ieee754dp_sqrt(ieee754dp x)
+{
+ struct ieee754_csr oldcsr;
+ ieee754dp y, z, t;
+ unsigned scalx, yh;
+ COMPXDP;
+
+ EXPLODEXDP;
+
+ /* x == INF or NAN? */
+ switch (xc) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ /* sqrt(Nan) = Nan */
+ return ieee754dp_nanxcpt(x, "sqrt");
+ case IEEE754_CLASS_ZERO:
+ /* sqrt(0) = 0 */
+ return x;
+ case IEEE754_CLASS_INF:
+ if (xs)
+ /* sqrt(-Inf) = Nan */
+ return ieee754dp_nanxcpt(nan, "sqrt");
+ /* sqrt(+Inf) = Inf */
+ return x;
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ /* fall through */
+ case IEEE754_CLASS_NORM:
+ if (xs)
+ /* sqrt(-x) = Nan */
+ return ieee754dp_nanxcpt(nan, "sqrt");
+ break;
+ }
+
+ /* save old csr; switch off INX enable & flag; set RN rounding */
+ oldcsr = ieee754_csr;
+ ieee754_csr.mx &= ~IEEE754_INEXACT;
+ ieee754_csr.sx &= ~IEEE754_INEXACT;
+ ieee754_csr.rm = IEEE754_RN;
+
+ /* adjust exponent to prevent overflow */
+ scalx = 0;
+ if (xe > 512) { /* x > 2**-512? */
+ xe -= 512; /* x = x / 2**512 */
+ scalx += 256;
+ } else if (xe < -512) { /* x < 2**-512? */
+ xe += 512; /* x = x * 2**512 */
+ scalx -= 256;
+ }
+
+ y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+
+ /* magic initial approximation to almost 8 sig. bits */
+ yh = y.bits >> 32;
+ yh = (yh >> 1) + 0x1ff80000;
+ yh = yh - table[(yh >> 15) & 31];
+ y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff);
+
+ /* Heron's rule once with correction to improve to ~18 sig. bits */
+ /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
+ t = ieee754dp_div(x, y);
+ y = ieee754dp_add(y, t);
+ y.bits -= 0x0010000600000000LL;
+ y.bits &= 0xffffffff00000000LL;
+
+ /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
+ /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
+ z = t = ieee754dp_mul(y, y);
+ t.parts.bexp += 0x001;
+ t = ieee754dp_add(t, z);
+ z = ieee754dp_mul(ieee754dp_sub(x, z), y);
+
+ /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */
+ t = ieee754dp_div(z, ieee754dp_add(t, x));
+ t.parts.bexp += 0x001;
+ y = ieee754dp_add(y, t);
+
+ /* twiddle last bit to force y correctly rounded */
+
+ /* set RZ, clear INEX flag */
+ ieee754_csr.rm = IEEE754_RZ;
+ ieee754_csr.sx &= ~IEEE754_INEXACT;
+
+ /* t=x/y; ...chopped quotient, possibly inexact */
+ t = ieee754dp_div(x, y);
+
+ if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
+
+ if (!(ieee754_csr.sx & IEEE754_INEXACT))
+ /* t = t-ulp */
+ t.bits -= 1;
+
+ /* add inexact to result status */
+ oldcsr.cx |= IEEE754_INEXACT;
+ oldcsr.sx |= IEEE754_INEXACT;
+
+ switch (oldcsr.rm) {
+ case IEEE754_RP:
+ y.bits += 1;
+ /* drop through */
+ case IEEE754_RN:
+ t.bits += 1;
+ break;
+ }
+
+ /* y=y+t; ...chopped sum */
+ y = ieee754dp_add(y, t);
+
+ /* adjust scalx for correctly rounded sqrt(x) */
+ scalx -= 1;
+ }
+
+ /* py[n0]=py[n0]+scalx; ...scale back y */
+ y.parts.bexp += scalx;
+
+ /* restore rounding mode, possibly set inexact */
+ ieee754_csr = oldcsr;
+
+ return y;
+}
diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c
new file mode 100644
index 000000000..f98761ef3
--- /dev/null
+++ b/arch/mips/math-emu/dp_sub.c
@@ -0,0 +1,200 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y, "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x, "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754dp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Inifity handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs != ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ return ieee754dp_inf(ys ^ 1);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs != ys)
+ return x;
+ else
+ return ieee754dp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ /* quick fix up */
+ DPSIGN(y) ^= 1;
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+ /* FAAL THOROUGH */
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ /* normalize ym,ye */
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ /* normalize xm,xe */
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* flip sign of y and handle as add */
+ ys ^= 1;
+
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+
+ /* provide guard,round and stick bit dpace */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ ym = XDPSRS(ym, s);
+ ye += s;
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ xm = XDPSRS(xm, s);
+ xe += s;
+ }
+ assert(xe == ye);
+ assert(xe <= DP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+ xm = XDPSRS1(xm); /* shift preserving sticky */
+ xe++;
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0)
+ if (ieee754_csr.rm == IEEE754_RD)
+ return ieee754dp_zero(1); /* round negative inf. => sign = -1 */
+ else
+ return ieee754dp_zero(0); /* other round modes => sign = 1 */
+
+ /* normalize to rounding precision
+ */
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ DPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c
new file mode 100644
index 000000000..6ce86a33c
--- /dev/null
+++ b/arch/mips/math-emu/dp_tint.c
@@ -0,0 +1,94 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+int ieee754dp_tint(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM: /* much to small */
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754si_xcpt(0, "fixdp", x);
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 31) {
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+ }
+ if (xe < 0) {
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754si_xcpt(0, "fix", x);
+ }
+ /* oh gawd */
+ if (xe > DP_MBITS) {
+ xm <<= xe - DP_MBITS;
+ } else if (xe < DP_MBITS) {
+ /* XXX no rounding
+ */
+ xm >>= DP_MBITS - xe;
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+unsigned int ieee754dp_tuns(ieee754dp x)
+{
+ ieee754dp hb = ieee754dp_1e31();
+
+ /* what if x < 0 ?? */
+ if (ieee754dp_lt(x, hb))
+ return (unsigned) ieee754dp_tint(x);
+
+ return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
+ ((unsigned) 1 << 31);
+}
diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c
new file mode 100644
index 000000000..f941c4dd4
--- /dev/null
+++ b/arch/mips/math-emu/dp_tlong.c
@@ -0,0 +1,148 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+long long ieee754dp_tlong(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM: /* much too small */
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754di_xcpt(0, "dp_tlong", x);
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 63) {
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ }
+ if (xe < 0) {
+ if (ieee754_csr.rm == IEEE754_RU) {
+ if (xs) { /* Negative */
+ return 0x0000000000000000LL;
+ } else { /* Positive */
+ return 0x0000000000000001LL;
+ }
+ } else if (ieee754_csr.rm == IEEE754_RD) {
+ if (xs) { /* Negative , return -1 */
+ return 0xffffffffffffffffLL;
+ } else { /* Positive */
+ return 0x0000000000000000LL;
+ }
+ } else {
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754di_xcpt(0, "dp_tlong", x);
+ }
+ }
+ /* oh gawd */
+ if (xe > DP_MBITS) {
+ xm <<= xe - DP_MBITS;
+ } else if (xe < DP_MBITS) {
+ unsigned long long residue;
+ unsigned long long mask = 0;
+ int i;
+ int round;
+ int sticky;
+ int odd;
+
+ /* compute mask */
+ for (i = 0; i < DP_MBITS - xe; i++) {
+ mask = mask << 1;
+ mask = mask | 0x1;
+ }
+ residue = (xm & mask) << (64 - (DP_MBITS - xe));
+ round =
+ ((0x8000000000000000LL & residue) !=
+ 0x0000000000000000LL);
+ sticky =
+ ((0x7fffffffffffffffLL & residue) !=
+ 0x0000000000000000LL);
+
+ xm >>= DP_MBITS - xe;
+
+ odd = ((xm & 0x1) != 0x0000000000000000LL);
+
+ /* Do the rounding */
+ if (!round && sticky) {
+ if ((ieee754_csr.rm == IEEE754_RU && !xs)
+ || (ieee754_csr.rm == IEEE754_RD && xs)) {
+ xm++;
+ }
+ } else if (round && !sticky) {
+ if ((ieee754_csr.rm == IEEE754_RU && !xs)
+ || (ieee754_csr.rm == IEEE754_RD && xs)
+ || (ieee754_csr.rm == IEEE754_RN && odd)) {
+ xm++;
+ }
+ } else if (round && sticky) {
+ if ((ieee754_csr.rm == IEEE754_RU && !xs)
+ || (ieee754_csr.rm == IEEE754_RD && xs)
+ || (ieee754_csr.rm == IEEE754_RN)) {
+ xm++;
+ }
+ }
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+unsigned long long ieee754dp_tulong(ieee754dp x)
+{
+ ieee754dp hb = ieee754dp_1e63();
+
+ /* what if x < 0 ?? */
+ if (ieee754dp_lt(x, hb))
+ return (unsigned long long) ieee754dp_tlong(x);
+
+ return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
+ (1ULL << 63);
+}
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c
new file mode 100644
index 000000000..d9d75e40a
--- /dev/null
+++ b/arch/mips/math-emu/ieee754.c
@@ -0,0 +1,145 @@
+/* ieee754 floating point arithmetic
+ * single and double precision
+ *
+ * BUGS
+ * not much dp done
+ * doesnt generate IEEE754_INEXACT
+ *
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#include <varargs.h>
+#endif
+#include "ieee754int.h"
+
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+
+/* indexed by class */
+const char *const ieee754_cname[] = {
+ "Normal",
+ "Zero",
+ "Denormal",
+ "Infinity",
+ "QNaN",
+ "SNaN",
+};
+
+/* the control status register
+*/
+struct ieee754_csr ieee754_csr;
+
+/* special constants
+*/
+
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#define SPSTR(s,b,m) {m,b,s}
+#define DPSTR(s,b,mh,ml) {ml,mh,b,s}
+#endif
+
+#ifdef __MIPSEB__
+#define SPSTR(s,b,m) {s,b,m}
+#define DPSTR(s,b,mh,ml) {s,b,mh,ml}
+#endif
+
+const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+ DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */
+ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */
+ DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */
+ DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */
+ DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */
+ DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */
+ DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */
+ DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */
+ DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0), /* + indef quiet Nan */
+ DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */
+ DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */
+ DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */
+ DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */
+ DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */
+ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */
+ DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */
+ DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */
+};
+
+const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+ SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */
+ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */
+ SPSTR(0, SP_EBIAS, 0), /* + 1.0 */
+ SPSTR(1, SP_EBIAS, 0), /* - 1.0 */
+ SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */
+ SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */
+ SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */
+ SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */
+ SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000), /* + indef quiet Nan */
+ SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */
+ SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */
+ SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */
+ SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */
+ SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */
+ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */
+ SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */
+ SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */
+};
+
+
+int ieee754si_xcpt(int r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ if (!TSTX())
+ return r;
+ ax.op = op;
+ ax.rt = IEEE754_RT_SI;
+ ax.rv.si = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.si;
+}
+
+long long ieee754di_xcpt(long long r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ if (!TSTX())
+ return r;
+ ax.op = op;
+ ax.rt = IEEE754_RT_DI;
+ ax.rv.di = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.di;
+}
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
new file mode 100644
index 000000000..ad2c91aed
--- /dev/null
+++ b/arch/mips/math-emu/ieee754.h
@@ -0,0 +1,490 @@
+/* single and double precision fp ops
+ * missing extended precision.
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ * Nov 7, 2000
+ * Modification to allow integration with Linux kernel
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+/* Going from Algorithmics to Linux native environment, add this */
+#include <linux/types.h>
+
+/*
+ * Not very pretty, but the Linux kernel's normal va_list definition
+ * does not allow it to be used as a structure element, as it is here.
+ */
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#else
+
+/* Note that __KERNEL__ is taken to mean Linux kernel */
+
+#if #system(OpenBSD)
+#include <machine/types.h>
+#endif
+#include <machine/endian.h>
+
+#endif /* __KERNEL__ */
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+struct ieee754dp_konst {
+ unsigned mantlo:32;
+ unsigned manthi:20;
+ unsigned bexp:11;
+ unsigned sign:1;
+};
+struct ieee754sp_konst {
+ unsigned mant:23;
+ unsigned bexp:8;
+ unsigned sign:1;
+};
+
+typedef union _ieee754dp {
+ struct ieee754dp_konst oparts;
+ struct {
+ unsigned long long mant:52;
+ unsigned int bexp:11;
+ unsigned int sign:1;
+ } parts;
+ unsigned long long bits;
+ double d;
+} ieee754dp;
+
+typedef union _ieee754sp {
+ struct ieee754sp_konst parts;
+ float f;
+ unsigned long bits;
+} ieee754sp;
+#endif
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+struct ieee754dp_konst {
+ unsigned sign:1;
+ unsigned bexp:11;
+ unsigned manthi:20;
+ unsigned mantlo:32;
+};
+typedef union _ieee754dp {
+ struct ieee754dp_konst oparts;
+ struct {
+ unsigned int sign:1;
+ unsigned int bexp:11;
+ unsigned long long mant:52;
+ } parts;
+ double d;
+ unsigned long long bits;
+} ieee754dp;
+
+struct ieee754sp_konst {
+ unsigned sign:1;
+ unsigned bexp:8;
+ unsigned mant:23;
+};
+
+typedef union _ieee754sp {
+ struct ieee754sp_konst parts;
+ float f;
+ unsigned long bits;
+} ieee754sp;
+#endif
+
+/*
+ * single precision (often aka float)
+*/
+int ieee754sp_finite(ieee754sp x);
+int ieee754sp_class(ieee754sp x);
+
+ieee754sp ieee754sp_abs(ieee754sp x);
+ieee754sp ieee754sp_neg(ieee754sp x);
+ieee754sp ieee754sp_scalb(ieee754sp x, int);
+ieee754sp ieee754sp_logb(ieee754sp x);
+
+/* x with sign of y */
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_fint(int x);
+ieee754sp ieee754sp_funs(unsigned x);
+ieee754sp ieee754sp_flong(long long x);
+ieee754sp ieee754sp_fulong(unsigned long long x);
+ieee754sp ieee754sp_fdp(ieee754dp x);
+
+int ieee754sp_tint(ieee754sp x);
+unsigned int ieee754sp_tuns(ieee754sp x);
+long long ieee754sp_tlong(ieee754sp x);
+unsigned long long ieee754sp_tulong(ieee754sp x);
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
+ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
+ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+
+ieee754sp ieee754sp_ceil(ieee754sp x);
+ieee754sp ieee754sp_floor(ieee754sp x);
+ieee754sp ieee754sp_trunc(ieee754sp x);
+
+ieee754sp ieee754sp_sqrt(ieee754sp x);
+
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_finite(ieee754dp x);
+int ieee754dp_class(ieee754dp x);
+
+/* x with sign of y */
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_abs(ieee754dp x);
+ieee754dp ieee754dp_neg(ieee754dp x);
+ieee754dp ieee754dp_scalb(ieee754dp x, int);
+
+/* return exponent as integer in floating point format
+ */
+ieee754dp ieee754dp_logb(ieee754dp x);
+
+ieee754dp ieee754dp_fint(int x);
+ieee754dp ieee754dp_funs(unsigned x);
+ieee754dp ieee754dp_flong(long long x);
+ieee754dp ieee754dp_fulong(unsigned long long x);
+ieee754dp ieee754dp_fsp(ieee754sp x);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+int ieee754dp_tint(ieee754dp x);
+unsigned int ieee754dp_tuns(ieee754dp x);
+long long ieee754dp_tlong(ieee754dp x);
+unsigned long long ieee754dp_tulong(ieee754dp x);
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
+ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
+ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+ieee754dp ieee754dp_sqrt(ieee754dp x);
+
+
+
+/* 5 types of floating point number
+*/
+#define IEEE754_CLASS_NORM 0x00
+#define IEEE754_CLASS_ZERO 0x01
+#define IEEE754_CLASS_DNORM 0x02
+#define IEEE754_CLASS_INF 0x03
+#define IEEE754_CLASS_SNAN 0x04
+#define IEEE754_CLASS_QNAN 0x05
+extern const char *const ieee754_cname[];
+
+/* exception numbers */
+#define IEEE754_INEXACT 0x01
+#define IEEE754_UNDERFLOW 0x02
+#define IEEE754_OVERFLOW 0x04
+#define IEEE754_ZERO_DIVIDE 0x08
+#define IEEE754_INVALID_OPERATION 0x10
+
+/* cmp operators
+*/
+#define IEEE754_CLT 0x01
+#define IEEE754_CEQ 0x02
+#define IEEE754_CGT 0x04
+#define IEEE754_CUN 0x08
+
+/* rounding mode
+*/
+#define IEEE754_RN 0 /* round to nearest */
+#define IEEE754_RZ 1 /* round toward zero */
+#define IEEE754_RD 2 /* round toward -Infinity */
+#define IEEE754_RU 3 /* round toward +Infinity */
+
+/* other naming */
+#define IEEE754_RM IEEE754_RD
+#define IEEE754_RP IEEE754_RU
+
+/* "normal" comparisons
+*/
+static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y,
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CGT);
+}
+
+
+static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y,
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CGT);
+}
+
+static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+
+/* like strtod
+*/
+ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+
+
+/* the control status register
+*/
+struct ieee754_csr {
+ unsigned pad:13;
+ unsigned noq:1; /* set 1 for no quiet NaN's */
+ unsigned nod:1; /* set 1 for no denormalised numbers */
+ unsigned cx:5; /* exceptions this operation */
+ unsigned mx:5; /* exception enable mask */
+ unsigned sx:5; /* exceptions total */
+ unsigned rm:2; /* current rounding mode */
+};
+extern struct ieee754_csr ieee754_csr;
+
+static __inline unsigned ieee754_getrm(void)
+{
+ return (ieee754_csr.rm);
+}
+static __inline unsigned ieee754_setrm(unsigned rm)
+{
+ return (ieee754_csr.rm = rm);
+}
+
+/*
+ * get current exceptions
+ */
+static __inline unsigned ieee754_getcx(void)
+{
+ return (ieee754_csr.cx);
+}
+
+/* test for current exception condition
+ */
+static __inline int ieee754_cxtest(unsigned n)
+{
+ return (ieee754_csr.cx & n);
+}
+
+/*
+ * get sticky exceptions
+ */
+static __inline unsigned ieee754_getsx(void)
+{
+ return (ieee754_csr.sx);
+}
+
+/* clear sticky conditions
+*/
+static __inline unsigned ieee754_clrsx(void)
+{
+ return (ieee754_csr.sx = 0);
+}
+
+/* test for sticky exception condition
+ */
+static __inline int ieee754_sxtest(unsigned n)
+{
+ return (ieee754_csr.sx & n);
+}
+
+/* debugging */
+ieee754sp ieee754sp_dump(char *s, ieee754sp x);
+ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+
+#define IEEE754_SPCVAL_PZERO 0
+#define IEEE754_SPCVAL_NZERO 1
+#define IEEE754_SPCVAL_PONE 2
+#define IEEE754_SPCVAL_NONE 3
+#define IEEE754_SPCVAL_PTEN 4
+#define IEEE754_SPCVAL_NTEN 5
+#define IEEE754_SPCVAL_PINFINITY 6
+#define IEEE754_SPCVAL_NINFINITY 7
+#define IEEE754_SPCVAL_INDEF 8
+#define IEEE754_SPCVAL_PMAX 9 /* +max norm */
+#define IEEE754_SPCVAL_NMAX 10 /* -max norm */
+#define IEEE754_SPCVAL_PMIN 11 /* +min norm */
+#define IEEE754_SPCVAL_NMIN 12 /* +min norm */
+#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */
+#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */
+#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */
+
+extern const struct ieee754dp_konst __ieee754dp_spcvals[];
+extern const struct ieee754sp_konst __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+
+/* return infinity with given sign
+*/
+#define ieee754dp_inf(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef() \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31() \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63() \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+
+#define ieee754sp_inf(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef() \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31() \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63() \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+
+/* indefinite integer value
+*/
+#define ieee754si_indef() INT_MIN
+#ifdef LONG_LONG_MIN
+#define ieee754di_indef() LONG_LONG_MIN
+#else
+#define ieee754di_indef() (-9223372036854775807LL-1)
+#endif
+
+/* IEEE exception context, passed to handler */
+struct ieee754xctx {
+ const char *op; /* operation name */
+ int rt; /* result type */
+ union {
+ ieee754sp sp; /* single precision */
+ ieee754dp dp; /* double precision */
+#ifdef IEEE854_XP
+ ieee754xp xp; /* extended precision */
+#endif
+ int si; /* standard signed integer (32bits) */
+ long long di; /* extended signed integer (64bits) */
+ } rv; /* default result format implied by op */
+ va_list ap;
+};
+
+/* result types for xctx.rt */
+#define IEEE754_RT_SP 0
+#define IEEE754_RT_DP 1
+#define IEEE754_RT_XP 2
+#define IEEE754_RT_SI 3
+#define IEEE754_RT_DI 4
+
+extern void ieee754_xcpt(struct ieee754xctx *xcp);
+
+/* compat */
+#define ieee754dp_fix(x) ieee754dp_tint(x)
+#define ieee754sp_fix(x) ieee754sp_tint(x)
diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c
new file mode 100644
index 000000000..f2b85915d
--- /dev/null
+++ b/arch/mips/math-emu/ieee754d.c
@@ -0,0 +1,148 @@
+/* some debug functions
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ * Nov 7, 2000
+ * Modified to build and operate in Linux kernel environment.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+#define printf printk
+#else
+#include <stdio.h>
+#include <stdarg.h>
+#endif
+
+#include "ieee754.h"
+
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+#define DP_FBITS 52
+
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+#define SP_FBITS 23
+
+#define DP_MBIT(x) ((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT DP_MBIT(63)
+
+
+#define SP_MBIT(x) ((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT SP_MBIT(31)
+
+
+#define SPSIGN(sp) (sp.parts.sign)
+#define SPBEXP(sp) (sp.parts.bexp)
+#define SPMANT(sp) (sp.parts.mant)
+
+#define DPSIGN(dp) (dp.parts.sign)
+#define DPBEXP(dp) (dp.parts.bexp)
+#define DPMANT(dp) (dp.parts.mant)
+
+ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+{
+ int i;
+
+ printf("%s", m);
+ printf("<%08x,%08x>\n", (unsigned) (x.bits >> 32),
+ (unsigned) x.bits);
+ printf("\t=");
+ switch (ieee754dp_class(x)) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ printf("Nan %c", DPSIGN(x) ? '-' : '+');
+ for (i = DP_FBITS - 1; i >= 0; i--)
+ printf("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+ break;
+ case IEEE754_CLASS_INF:
+ printf("%cInfinity", DPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_ZERO:
+ printf("%cZero", DPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_DNORM:
+ printf("%c0.", DPSIGN(x) ? '-' : '+');
+ for (i = DP_FBITS - 1; i >= 0; i--)
+ printf("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+ printf("e%d", DPBEXP(x) - DP_EBIAS);
+ break;
+ case IEEE754_CLASS_NORM:
+ printf("%c1.", DPSIGN(x) ? '-' : '+');
+ for (i = DP_FBITS - 1; i >= 0; i--)
+ printf("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+ printf("e%d", DPBEXP(x) - DP_EBIAS);
+ break;
+ default:
+ printf("Illegal/Unknown IEEE754 value class");
+ }
+ printf("\n");
+ return x;
+}
+
+ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+{
+ int i;
+
+ printf("%s=", m);
+ printf("<%08x>\n", (unsigned) x.bits);
+ printf("\t=");
+ switch (ieee754sp_class(x)) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ printf("Nan %c", SPSIGN(x) ? '-' : '+');
+ for (i = SP_FBITS - 1; i >= 0; i--)
+ printf("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+ break;
+ case IEEE754_CLASS_INF:
+ printf("%cInfinity", SPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_ZERO:
+ printf("%cZero", SPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_DNORM:
+ printf("%c0.", SPSIGN(x) ? '-' : '+');
+ for (i = SP_FBITS - 1; i >= 0; i--)
+ printf("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+ printf("e%d", SPBEXP(x) - SP_EBIAS);
+ break;
+ case IEEE754_CLASS_NORM:
+ printf("%c1.", SPSIGN(x) ? '-' : '+');
+ for (i = SP_FBITS - 1; i >= 0; i--)
+ printf("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+ printf("e%d", SPBEXP(x) - SP_EBIAS);
+ break;
+ default:
+ printf("Illegal/Unknown IEEE754 value class");
+ }
+ printf("\n");
+ return x;
+}
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c
new file mode 100644
index 000000000..58790d072
--- /dev/null
+++ b/arch/mips/math-emu/ieee754dp.c
@@ -0,0 +1,204 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754dp.h"
+
+int ieee754dp_class(ieee754dp x)
+{
+ COMPXDP;
+ EXPLODEXDP;
+ return xc;
+}
+
+int ieee754dp_isnan(ieee754dp x)
+{
+ return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754dp_issnan(ieee754dp x)
+{
+ assert(ieee754dp_isnan(x));
+ if (ieee754_csr.noq)
+ return 1;
+ return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1));
+}
+
+
+ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+ if (!TSTX())
+ return r;
+
+ ax.op = op;
+ ax.rt = IEEE754_RT_DP;
+ ax.rv.dp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ assert(ieee754dp_isnan(r));
+
+ if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */
+ return r;
+
+ if (!SETCX(IEEE754_INVALID_OPERATION)) {
+ /* not enabled convert to a quiet NaN */
+ if (ieee754_csr.noq)
+ return r;
+ DPMANT(r) |= DP_MBIT(DP_MBITS - 1);
+ return r;
+ }
+
+ ax.op = op;
+ ax.rt = 0;
+ ax.rv.dp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+{
+ assert(ieee754dp_isnan(x));
+ assert(ieee754dp_isnan(y));
+
+ if (DPMANT(x) > DPMANT(y))
+ return x;
+ else
+ return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm)
+{
+ assert(xm); /* we dont gen exact zeros (probably should) */
+
+ assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */
+ assert(xm & (DP_HIDDEN_BIT << 3));
+
+ if (xe < DP_EMIN) {
+ /* strip lower bits */
+ int es = DP_EMIN - xe;
+
+ if (ieee754_csr.nod) {
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754dp_zero(sn);
+ }
+
+ /* sticky right shift es bits
+ */
+ xm = XDPSRS(xm, es);
+ xe += es;
+
+ assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+ assert(xe == DP_EMIN);
+ }
+ if (xm & (DP_MBIT(3) - 1)) {
+ SETCX(IEEE754_INEXACT);
+ /* inexact must round of 3 bits
+ */
+ switch (ieee754_csr.rm) {
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RN:
+ xm += 0x3 + ((xm >> 3) & 1);
+ /* xm += (xm&0x8)?0x4:0x3 */
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if (!sn) /* ?? */
+ xm += 0x8;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn) /* ?? */
+ xm += 0x8;
+ break;
+ }
+ /* adjust exponent for rounding add overflowing
+ */
+ if (xm >> (DP_MBITS + 3 + 1)) { /* add causes mantissa overflow */
+ xm >>= 1;
+ xe++;
+ }
+ }
+ /* strip grs bits */
+ xm >>= 3;
+
+ assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
+ assert(xe >= DP_EMIN);
+
+ if (xe > DP_EMAX) {
+ SETCX(IEEE754_OVERFLOW);
+ /* -O can be table indexed by (rm,sn) */
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ return ieee754dp_inf(sn);
+ case IEEE754_RZ:
+ return ieee754dp_max(sn);
+ case IEEE754_RU: /* toward +Infinity */
+ if (sn == 0)
+ return ieee754dp_inf(0);
+ else
+ return ieee754dp_max(1);
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn == 0)
+ return ieee754dp_max(0);
+ else
+ return ieee754dp_inf(1);
+ }
+ }
+ /* gen norm/denorm/zero */
+
+ if ((xm & DP_HIDDEN_BIT) == 0) {
+ /* we underflow (tiny/zero) */
+ assert(xe == DP_EMIN);
+ SETCX(IEEE754_UNDERFLOW);
+ return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
+ } else {
+ assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
+ assert(xm & DP_HIDDEN_BIT);
+
+ return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+ }
+}
diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h
new file mode 100644
index 000000000..da7b4c568
--- /dev/null
+++ b/arch/mips/math-emu/ieee754dp.h
@@ -0,0 +1,81 @@
+/*
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+/* 3bit extended double precision sticky right shift */
+#define XDPSRS(v,rs) \
+ ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+
+#define XDPSRSX1() \
+ (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define XDPSRS1(v) \
+ (((v) >> 1) | ((v) & 1))
+
+/* convert denormal to normalized with extended exponent */
+#define DPDNORMx(m,e) \
+ while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+#define DPDNORMX DPDNORMx(xm,xe)
+#define DPDNORMY DPDNORMx(ym,ye)
+
+static __inline ieee754dp builddp(int s, int bx, unsigned long long m)
+{
+ ieee754dp r;
+
+ assert((s) == 0 || (s) == 1);
+ assert((bx) >= DP_EMIN - 1 + DP_EBIAS
+ && (bx) <= DP_EMAX + 1 + DP_EBIAS);
+ assert(((m) >> DP_MBITS) == 0);
+
+ r.parts.sign = s;
+ r.parts.bexp = bx;
+ r.parts.mant = m;
+ return r;
+}
+
+extern int ieee754dp_isnan(ieee754dp);
+extern int ieee754dp_issnan(ieee754dp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
+extern ieee754dp ieee754dp_format(int, int, unsigned long long);
+
+
+#define DPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+ ieee754dp V = ieee754dp_format(s,e,m); \
+ if(TSTX()) \
+ return ieee754dp_xcpt(V,name,a0,a1); \
+ else \
+ return V; \
+}
+
+#define DPNORMRET1(s,e,m,name,a0) DPNORMRET2(s,e,m,name,a0,a0)
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h
new file mode 100644
index 000000000..6de10131f
--- /dev/null
+++ b/arch/mips/math-emu/ieee754int.h
@@ -0,0 +1,135 @@
+/*
+ * IEEE754 floating point
+ * common internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+#define DP_MBITS 52
+
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+#define SP_MBITS 23
+
+#define DP_MBIT(x) ((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS)
+#define DP_SIGN_BIT DP_MBIT(63)
+
+#define SP_MBIT(x) ((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS)
+#define SP_SIGN_BIT SP_MBIT(31)
+
+
+#define SPSIGN(sp) (sp.parts.sign)
+#define SPBEXP(sp) (sp.parts.bexp)
+#define SPMANT(sp) (sp.parts.mant)
+
+#define DPSIGN(dp) (dp.parts.sign)
+#define DPBEXP(dp) (dp.parts.bexp)
+#define DPMANT(dp) (dp.parts.mant)
+
+#define CLPAIR(x,y) ((x)*6+(y))
+
+#define CLEARCX \
+ (ieee754_csr.cx = 0)
+
+#define SETCX(x) \
+ (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x))
+
+#define TSTX() \
+ (ieee754_csr.cx & ieee754_csr.mx)
+
+
+#define COMPXSP \
+ unsigned xm; int xe; int xs; int xc
+
+#define COMPYSP \
+ unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v,vc,vs,ve,vm) \
+{\
+ vs = SPSIGN(v);\
+ ve = SPBEXP(v);\
+ vm = SPMANT(v);\
+ if(ve == SP_EMAX+1+SP_EBIAS){\
+ if(vm == 0)\
+ vc = IEEE754_CLASS_INF;\
+ else if(vm & SP_MBIT(SP_MBITS-1)) \
+ vc = IEEE754_CLASS_QNAN;\
+ else \
+ vc = IEEE754_CLASS_SNAN;\
+ } else if(ve == SP_EMIN-1+SP_EBIAS) {\
+ if(vm) {\
+ ve = SP_EMIN;\
+ vc = IEEE754_CLASS_DNORM;\
+ } else\
+ vc = IEEE754_CLASS_ZERO;\
+ } else {\
+ ve -= SP_EBIAS;\
+ vm |= SP_HIDDEN_BIT;\
+ vc = IEEE754_CLASS_NORM;\
+ }\
+}
+#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm)
+#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym)
+
+
+#define COMPXDP \
+unsigned long long xm; int xe; int xs; int xc
+
+#define COMPYDP \
+unsigned long long ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v,vc,vs,ve,vm) \
+{\
+ vm = DPMANT(v);\
+ vs = DPSIGN(v);\
+ ve = DPBEXP(v);\
+ if(ve == DP_EMAX+1+DP_EBIAS){\
+ if(vm == 0)\
+ vc = IEEE754_CLASS_INF;\
+ else if(vm & DP_MBIT(DP_MBITS-1)) \
+ vc = IEEE754_CLASS_QNAN;\
+ else \
+ vc = IEEE754_CLASS_SNAN;\
+ } else if(ve == DP_EMIN-1+DP_EBIAS) {\
+ if(vm) {\
+ ve = DP_EMIN;\
+ vc = IEEE754_CLASS_DNORM;\
+ } else\
+ vc = IEEE754_CLASS_ZERO;\
+ } else {\
+ ve -= DP_EBIAS;\
+ vm |= DP_HIDDEN_BIT;\
+ vc = IEEE754_CLASS_NORM;\
+ }\
+}
+#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm)
+#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym)
diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c
new file mode 100644
index 000000000..29b4e3376
--- /dev/null
+++ b/arch/mips/math-emu/ieee754m.c
@@ -0,0 +1,56 @@
+/*
+ * floor, trunc, ceil
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+ieee754dp ieee754dp_floor(ieee754dp x)
+{
+ ieee754dp i;
+
+ if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+ return ieee754dp_sub(i, ieee754dp_one(0));
+ else
+ return i;
+}
+
+ieee754dp ieee754dp_ceil(ieee754dp x)
+{
+ ieee754dp i;
+
+ if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+ return ieee754dp_add(i, ieee754dp_one(0));
+ else
+ return i;
+}
+
+ieee754dp ieee754dp_trunc(ieee754dp x)
+{
+ ieee754dp i;
+
+ (void) ieee754dp_modf(x, &i);
+ return i;
+}
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c
new file mode 100644
index 000000000..691a0ec87
--- /dev/null
+++ b/arch/mips/math-emu/ieee754sp.c
@@ -0,0 +1,205 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+int ieee754sp_class(ieee754sp x)
+{
+ COMPXSP;
+ EXPLODEXSP;
+ return xc;
+}
+
+int ieee754sp_isnan(ieee754sp x)
+{
+ return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754sp_issnan(ieee754sp x)
+{
+ assert(ieee754sp_isnan(x));
+ if (ieee754_csr.noq)
+ return 1;
+ return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1));
+}
+
+
+ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ if (!TSTX())
+ return r;
+
+ ax.op = op;
+ ax.rt = IEEE754_RT_SP;
+ ax.rv.sp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ assert(ieee754sp_isnan(r));
+
+ if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */
+ return r;
+
+ if (!SETCX(IEEE754_INVALID_OPERATION)) {
+ /* not enabled convert to a quiet NaN */
+ if (ieee754_csr.noq)
+ return r;
+ SPMANT(r) |= SP_MBIT(SP_MBITS - 1);
+ return r;
+ }
+
+ ax.op = op;
+ ax.rt = 0;
+ ax.rv.sp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+{
+ assert(ieee754sp_isnan(x));
+ assert(ieee754sp_isnan(y));
+
+ if (SPMANT(x) > SPMANT(y))
+ return x;
+ else
+ return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+{
+ assert(xm); /* we dont gen exact zeros (probably should) */
+
+ assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */
+ assert(xm & (SP_HIDDEN_BIT << 3));
+
+ if (xe < SP_EMIN) {
+ /* strip lower bits */
+ int es = SP_EMIN - xe;
+
+ if (ieee754_csr.nod) {
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754sp_zero(sn);
+ }
+
+ /* sticky right shift es bits
+ */
+ SPXSRSXn(es);
+
+ assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+ assert(xe == SP_EMIN);
+ }
+ if (xm & (SP_MBIT(3) - 1)) {
+ SETCX(IEEE754_INEXACT);
+ /* inexact must round of 3 bits
+ */
+ switch (ieee754_csr.rm) {
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RN:
+ xm += 0x3 + ((xm >> 3) & 1);
+ /* xm += (xm&0x8)?0x4:0x3 */
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if (!sn) /* ?? */
+ xm += 0x8;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn) /* ?? */
+ xm += 0x8;
+ break;
+ }
+ /* adjust exponent for rounding add overflowing
+ */
+ if (xm >> (SP_MBITS + 1 + 3)) { /* add causes mantissa overflow */
+ xm >>= 1;
+ xe++;
+ }
+ }
+ /* strip grs bits */
+ xm >>= 3;
+
+ assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
+ assert(xe >= SP_EMIN);
+
+ if (xe > SP_EMAX) {
+ SETCX(IEEE754_OVERFLOW);
+ /* -O can be table indexed by (rm,sn) */
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ return ieee754sp_inf(sn);
+ case IEEE754_RZ:
+ return ieee754sp_max(sn);
+ case IEEE754_RU: /* toward +Infinity */
+ if (sn == 0)
+ return ieee754sp_inf(0);
+ else
+ return ieee754sp_max(1);
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn == 0)
+ return ieee754sp_max(0);
+ else
+ return ieee754sp_inf(1);
+ }
+ }
+ /* gen norm/denorm/zero */
+
+ if ((xm & SP_HIDDEN_BIT) == 0) {
+ /* we underflow (tiny/zero) */
+ assert(xe == SP_EMIN);
+ SETCX(IEEE754_UNDERFLOW);
+ return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
+ } else {
+ assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
+ assert(xm & SP_HIDDEN_BIT);
+
+ return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+ }
+}
diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h
new file mode 100644
index 000000000..2ff769dcf
--- /dev/null
+++ b/arch/mips/math-emu/ieee754sp.h
@@ -0,0 +1,87 @@
+/*
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+/* 3bit extended single precision sticky right shift */
+#define SPXSRSXn(rs) \
+ (xe += rs, \
+ xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+
+#define SPXSRSX1() \
+ (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define SPXSRSYn(rs) \
+ (ye+=rs, \
+ ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+
+#define SPXSRSY1() \
+ (ye++, (ym = (ym >> 1) | (ym & 1)))
+
+/* convert denormal to normalized with extended exponent */
+#define SPDNORMx(m,e) \
+ while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+#define SPDNORMX SPDNORMx(xm,xe)
+#define SPDNORMY SPDNORMx(ym,ye)
+
+static __inline ieee754sp buildsp(int s, int bx, unsigned m)
+{
+ ieee754sp r;
+
+ assert((s) == 0 || (s) == 1);
+ assert((bx) >= SP_EMIN - 1 + SP_EBIAS
+ && (bx) <= SP_EMAX + 1 + SP_EBIAS);
+ assert(((m) >> SP_MBITS) == 0);
+
+ r.parts.sign = s;
+ r.parts.bexp = bx;
+ r.parts.mant = m;
+
+ return r;
+}
+
+extern int ieee754sp_isnan(ieee754sp);
+extern int ieee754sp_issnan(ieee754sp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
+extern ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+ ieee754sp V = ieee754sp_format(s,e,m); \
+ if(TSTX()) \
+ return ieee754sp_xcpt(V,name,a0,a1); \
+ else \
+ return V; \
+}
+
+#define SPNORMRET1(s,e,m,name,a0) SPNORMRET2(s,e,m,name,a0,a0)
diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c
new file mode 100644
index 000000000..5a80c29cf
--- /dev/null
+++ b/arch/mips/math-emu/ieee754xcpt.c
@@ -0,0 +1,60 @@
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ * Nov 7, 2000
+ * Added preprocessor hacks to map to Linux kernel diagnostics.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#if !#system(sde) && !defined(__KERNEL__)
+#include <stdio.h>
+#endif
+
+#ifdef __KERNEL__
+#define _mon_printf printk
+#endif
+
+#include "ieee754.h"
+
+/*
+ * Very naff exception handler (you can plug in your own and
+ * override this).
+ */
+
+static const char *const rtnames[] = {
+ "sp", "dp", "xp", "si", "di"
+};
+
+void ieee754_xcpt(struct ieee754xctx *xcp)
+{
+#if #system(sde) || defined(__KERNEL__)
+ _mon_printf("floating point exception in \"%s\", type=%s\n",
+ xcp->op, rtnames[xcp->rt]);
+#else
+ fprintf(stderr, "floating point exception in \"%s\", type=%s\n",
+ xcp->op, rtnames[xcp->rt]);
+#endif
+}
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
new file mode 100644
index 000000000..93c84f8b0
--- /dev/null
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * arch/mips/math_emu/kernel_linkage.c
+ *
+ * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *************************************************************************/
+/*
+ * Routines corresponding to Linux kernel FP context
+ * manipulation primitives for the Algorithmics MIPS
+ * FPU Emulator
+ */
+
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpu_emulator.h>
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+void fpu_emulator_init_fpu(void)
+{
+ int i;
+
+/* printk("Algorithmics/MIPS FPU Emulator v1.4\n");*/
+ current->thread.fpu.soft.sr = 0;
+ for (i = 0; i < 32; i++) {
+ current->thread.fpu.soft.regs[i] = SIGNALLING_NAN;
+ }
+}
+
+
+/*
+ * Emulator context save/restore to/from a signal context
+ * presumed to be on the user stack, and therefore accessed
+ * with appropriate macros from uaccess.h
+ */
+
+int fpu_emulator_save_context(struct sigcontext *sc)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < 32; i++) {
+ err |=
+ __put_user(current->thread.fpu.soft.regs[i],
+ &sc->sc_fpregs[i]);
+ }
+ err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+ err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+ return err;
+}
+
+int fpu_emulator_restore_context(struct sigcontext *sc)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < 32; i++) {
+ err |=
+ __get_user(current->thread.fpu.soft.regs[i],
+ &sc->sc_fpregs[i]);
+ }
+ err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+ err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+ return err;
+}
diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c
new file mode 100644
index 000000000..bdcbda8e9
--- /dev/null
+++ b/arch/mips/math-emu/sp_add.c
@@ -0,0 +1,188 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ CLEARCX;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y, "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x, "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754sp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Inifity handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs == ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ else
+ return ieee754sp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* provide guard,round and stick bit space */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ SPXSRSYn(s);
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ SPXSRSXn(s);
+ }
+ assert(xe == ye);
+ assert(xe <= SP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm,xs,xe
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+ SPXSRSX1();
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0)
+ return ieee754sp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ /* normalize in extended single precision */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+
+ }
+ SPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c
new file mode 100644
index 000000000..ae7c8247e
--- /dev/null
+++ b/arch/mips/math-emu/sp_cmp.c
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp)
+{
+ CLEARCX;
+
+ if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+ if (cmp & IEEE754_CUN)
+ return 1;
+ if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+ if (SETCX(IEEE754_INVALID_OPERATION))
+ return ieee754si_xcpt(0, "fcmpf", x);
+ }
+ return 0;
+ } else {
+ int vx = x.bits;
+ int vy = y.bits;
+
+ if (vx < 0)
+ vx = -vx ^ SP_SIGN_BIT;
+ if (vy < 0)
+ vy = -vy ^ SP_SIGN_BIT;
+
+ if (vx < vy)
+ return (cmp & IEEE754_CLT) != 0;
+ else if (vx == vy)
+ return (cmp & IEEE754_CEQ) != 0;
+ else
+ return (cmp & IEEE754_CGT) != 0;
+ }
+}
diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c
new file mode 100644
index 000000000..187f14fd3
--- /dev/null
+++ b/arch/mips/math-emu/sp_div.c
@@ -0,0 +1,168 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y, "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x, "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754sp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return ieee754sp_zero(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return ieee754sp_inf(xs ^ ys);
+
+ /* Zero handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_ZERO_DIVIDE);
+ return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ieee754sp_zero(xs == ys ? 0 : 1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* provide rounding space */
+ xm <<= 3;
+ ym <<= 3;
+
+ {
+ /* now the dirty work */
+
+ unsigned rm = 0;
+ int re = xe - ye;
+ unsigned bm;
+
+ for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
+ if (xm >= ym) {
+ xm -= ym;
+ rm |= bm;
+ if (xm == 0)
+ break;
+ }
+ xm <<= 1;
+ }
+ rm <<= 1;
+ if (xm)
+ rm |= 1; /* have remainder, set sticky */
+
+ assert(rm);
+
+ /* normalise rm to rounding precision ?
+ */
+ while ((rm >> (SP_MBITS + 3)) == 0) {
+ rm <<= 1;
+ re--;
+ }
+
+ SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c
new file mode 100644
index 000000000..e24f3cee7
--- /dev/null
+++ b/arch/mips/math-emu/sp_fdp.c
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fdp(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ return ieee754sp_nanxcpt(buildsp(xs,
+ SP_EMAX + 1 + SP_EBIAS,
+ (unsigned long)
+ (xm >>
+ (DP_MBITS - SP_MBITS))),
+ "fdp", x);
+ case IEEE754_CLASS_INF:
+ return ieee754sp_inf(xs);
+ case IEEE754_CLASS_ZERO:
+ return ieee754sp_zero(xs);
+ case IEEE754_CLASS_DNORM:
+ /* cant possibly be sp representable */
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+
+ {
+ unsigned long rm;
+
+ /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift
+ */
+ rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
+ ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+
+ SPNORMRET1(xs, xe, rm, "fdp", x);
+ }
+}
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
new file mode 100644
index 000000000..d5dc5afb3
--- /dev/null
+++ b/arch/mips/math-emu/sp_fint.c
@@ -0,0 +1,86 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fint(int x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ if (x == 0)
+ return ieee754sp_zero(0);
+ if (x == 1 | x == -1)
+ return ieee754sp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754sp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1 << 31))
+ xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+ xe = SP_MBITS + 3;
+
+ if (xm >> (SP_MBITS + 1 + 3)) {
+ /* shunt out overflow bits
+ */
+ while (xm >> (SP_MBITS + 1 + 3)) {
+ SPXSRSX1();
+ }
+ } else {
+ /* normalize in grs extended single precision
+ */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ SPNORMRET1(xs, xe, xm, "fint", x);
+}
+
+
+ieee754sp ieee754sp_funs(unsigned int u)
+{
+ if ((int) u < 0)
+ return ieee754sp_add(ieee754sp_1e31(),
+ ieee754sp_fint(u & ~(1 << 31)));
+ return ieee754sp_fint(u);
+}
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
new file mode 100644
index 000000000..7b3b7c4df
--- /dev/null
+++ b/arch/mips/math-emu/sp_flong.c
@@ -0,0 +1,85 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_flong(long long x)
+{
+ COMPXDP; /* <--- need 64-bit mantissa temp */
+
+ CLEARCX;
+
+ if (x == 0)
+ return ieee754sp_zero(0);
+ if (x == 1 | x == -1)
+ return ieee754sp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754sp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1ULL << 63))
+ xm = (1ULL << 63); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+ xe = SP_MBITS + 3;
+
+ if (xm >> (SP_MBITS + 1 + 3)) {
+ /* shunt out overflow bits
+ */
+ while (xm >> (SP_MBITS + 1 + 3)) {
+ SPXSRSX1();
+ }
+ } else {
+ /* normalize in grs extended single precision */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ SPNORMRET1(xs, xe, xm, "sp_flong", x);
+}
+
+
+ieee754sp ieee754sp_fulong(unsigned long long u)
+{
+ if ((long long) u < 0)
+ return ieee754sp_add(ieee754sp_1e63(),
+ ieee754sp_flong(u & ~(1ULL << 63)));
+ return ieee754sp_fint(u);
+}
diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c
new file mode 100644
index 000000000..cf8af4a50
--- /dev/null
+++ b/arch/mips/math-emu/sp_frexp.c
@@ -0,0 +1,61 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+/* close to ieeep754sp_logb
+*/
+ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+{
+ COMPXSP;
+ CLEARCX;
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *eptr = 0;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ SPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ *eptr = xe + 1;
+ return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c
new file mode 100644
index 000000000..6d9f5cc42
--- /dev/null
+++ b/arch/mips/math-emu/sp_logb.c
@@ -0,0 +1,62 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_logb(ieee754sp x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754sp_nanxcpt(x, "logb", x);
+ case IEEE754_CLASS_QNAN:
+ return x;
+ case IEEE754_CLASS_INF:
+ return ieee754sp_inf(0);
+ case IEEE754_CLASS_ZERO:
+ return ieee754sp_inf(1);
+ case IEEE754_CLASS_DNORM:
+ SPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ return ieee754sp_fint(xe);
+}
diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c
new file mode 100644
index 000000000..8129c8a65
--- /dev/null
+++ b/arch/mips/math-emu/sp_modf.c
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *ip = x;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ /* far to small */
+ *ip = ieee754sp_zero(xs);
+ return x;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe < 0) {
+ *ip = ieee754sp_zero(xs);
+ return x;
+ }
+ if (xe >= SP_MBITS) {
+ *ip = x;
+ return ieee754sp_zero(xs);
+ }
+ /* generate ipart mantissa by clearing bottom bits
+ */
+ *ip = buildsp(xs, xe + SP_EBIAS,
+ ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
+ ~SP_HIDDEN_BIT);
+
+ /* generate fpart mantissa by clearing top bits
+ * and normalizing (must be able to normalize)
+ */
+ xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
+ if (xm == 0)
+ return ieee754sp_zero(xs);
+
+ while ((xm >> SP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c
new file mode 100644
index 000000000..cfff13150
--- /dev/null
+++ b/arch/mips/math-emu/sp_mul.c
@@ -0,0 +1,182 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y, "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x, "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754sp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handeling */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ return ieee754sp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return ieee754sp_zero(xs ^ ys);
+
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* rm = xm * ym, re = xe+ye basicly */
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ {
+ int re = xe + ye;
+ int rs = xs ^ ys;
+ unsigned rm;
+
+ /* shunt to top of word */
+ xm <<= 32 - (SP_MBITS + 1);
+ ym <<= 32 - (SP_MBITS + 1);
+
+ /* multiply 32bits xm,ym to give high 32bits rm with stickness
+ */
+ {
+ unsigned short lxm = xm & 0xffff;
+ unsigned short hxm = xm >> 16;
+ unsigned short lym = ym & 0xffff;
+ unsigned short hym = ym >> 16;
+ unsigned lrm;
+ unsigned hrm;
+
+ lrm = lxm * lym; /* 16 * 16 => 32 */
+ hrm = hxm * hym; /* 16 * 16 => 32 */
+
+ {
+ unsigned t = lxm * hym; /* 16 * 16 => 32 */
+ {
+ unsigned at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 16);
+ }
+
+ {
+ unsigned t = hxm * lym; /* 16 * 16 => 32 */
+ {
+ unsigned at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 16);
+ }
+ rm = hrm | (lrm != 0);
+ }
+
+ /*
+ * sticky shift down to normal rounding precision
+ */
+ if ((int) rm < 0) {
+ rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
+ ((rm << (SP_MBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
+ ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (SP_HIDDEN_BIT << 3));
+
+ SPNORMRET2(rs, re, rm, "mul", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c
new file mode 100644
index 000000000..1e6cded64
--- /dev/null
+++ b/arch/mips/math-emu/sp_scalb.c
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754sp_nanxcpt(x, "scalb", x, n);
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ return x;
+ case IEEE754_CLASS_DNORM:
+ SPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+{
+ return ieee754sp_scalb(x, n);
+}
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
new file mode 100644
index 000000000..392876b19
--- /dev/null
+++ b/arch/mips/math-emu/sp_simple.c
@@ -0,0 +1,74 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+int ieee754sp_finite(ieee754sp x)
+{
+ return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+{
+ CLEARCX;
+ SPSIGN(x) = SPSIGN(y);
+ return x;
+}
+
+
+ieee754sp ieee754sp_neg(ieee754sp x)
+{
+ CLEARCX;
+
+ if (ieee754sp_isnan(x)) /* but not infinity */
+ return ieee754sp_nanxcpt(x, "neg", x);
+
+ /* quick fix up */
+ SPSIGN(x) ^= 1;
+ return x;
+}
+
+
+ieee754sp ieee754sp_abs(ieee754sp x)
+{
+ CLEARCX;
+
+ if (ieee754sp_isnan(x)) /* but not infinity */
+ return ieee754sp_nanxcpt(x, "abs", x);
+
+ /* quick fix up */
+ SPSIGN(x) = 0;
+ return x;
+}
diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c
new file mode 100644
index 000000000..5bf25b520
--- /dev/null
+++ b/arch/mips/math-emu/sp_sqrt.c
@@ -0,0 +1,122 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+#include "ieee754sp.h"
+
+static const struct ieee754sp_konst knan = {
+ 0, SP_EBIAS + SP_EMAX + 1, 0
+};
+
+#define nan ((ieee754sp)knan)
+
+ieee754sp ieee754sp_sqrt(ieee754sp x)
+{
+ int sign = (int) 0x80000000;
+ int ix, s, q, m, t, i;
+ unsigned int r;
+ COMPXDP;
+
+ /* take care of Inf and NaN */
+
+ EXPLODEXDP;
+
+ /* x == INF or NAN? */
+ switch (xc) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ /* sqrt(Nan) = Nan */
+ return ieee754sp_nanxcpt(x, "sqrt");
+ case IEEE754_CLASS_ZERO:
+ /* sqrt(0) = 0 */
+ return x;
+ case IEEE754_CLASS_INF:
+ if (xs)
+ /* sqrt(-Inf) = Nan */
+ return ieee754sp_nanxcpt(nan, "sqrt");
+ /* sqrt(+Inf) = Inf */
+ return x;
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ if (xs)
+ /* sqrt(-x) = Nan */
+ return ieee754sp_nanxcpt(nan, "sqrt");
+ break;
+ }
+
+ ix = x.bits;
+
+ /* normalize x */
+ m = (ix >> 23);
+ if (m == 0) { /* subnormal x */
+ for (i = 0; (ix & 0x00800000) == 0; i++)
+ ix <<= 1;
+ m -= i - 1;
+ }
+ m -= 127; /* unbias exponent */
+ ix = (ix & 0x007fffff) | 0x00800000;
+ if (m & 1) /* odd m, double x to make it even */
+ ix += ix;
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix += ix;
+ q = s = 0; /* q = sqrt(x) */
+ r = 0x01000000; /* r = moving bit from right to left */
+
+ while (r != 0) {
+ t = s + r;
+ if (t <= ix) {
+ s = t + r;
+ ix -= t;
+ q += r;
+ }
+ ix += ix;
+ r >>= 1;
+ }
+
+ if (ix != 0) {
+ switch (ieee754_csr.rm) {
+ case IEEE754_RP:
+ q += 2;
+ break;
+ case IEEE754_RN:
+ q += (q & 1);
+ break;
+ }
+ }
+ ix = (q >> 1) + 0x3f000000;
+ ix += (m << 23);
+ x.bits = ix;
+ return x;
+}
diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c
new file mode 100644
index 000000000..0372a85be
--- /dev/null
+++ b/arch/mips/math-emu/sp_sub.c
@@ -0,0 +1,195 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x,
+ y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y, "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x, "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ return ieee754sp_bestnan(x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Inifity handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs != ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ return ieee754sp_inf(ys ^ 1);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handeling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs != ys)
+ return x;
+ else
+ return ieee754sp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ /* quick fix up */
+ DPSIGN(y) ^= 1;
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* flip sign of y and handle as add */
+ ys ^= 1;
+
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+
+ /* provide guard,round and stick bit space */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ SPXSRSYn(s);
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ SPXSRSXn(s);
+ }
+ assert(xe == ye);
+ assert(xe <= SP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+ SPXSRSX1(); /* shift preserving sticky */
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0)
+ if (ieee754_csr.rm == IEEE754_RD)
+ return ieee754sp_zero(1); /* round negative inf. => sign = -1 */
+ else
+ return ieee754sp_zero(0); /* other round modes => sign = 1 */
+
+ /* normalize to rounding precision
+ */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ SPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c
new file mode 100644
index 000000000..eeb26551e
--- /dev/null
+++ b/arch/mips/math-emu/sp_tint.c
@@ -0,0 +1,95 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+int ieee754sp_tint(ieee754sp x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM: /* much to small */
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754si_xcpt(0, "fixsp", x);
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 31) {
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+ }
+ if (xe < 0) {
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754si_xcpt(0, "fix", x);
+ }
+ /* oh gawd */
+ if (xe > SP_MBITS) {
+ xm <<= xe - SP_MBITS;
+ } else if (xe < SP_MBITS) {
+ /* XXX no rounding
+ */
+ xm >>= SP_MBITS - xe;
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+unsigned int ieee754sp_tuns(ieee754sp x)
+{
+ ieee754sp hb = ieee754sp_1e31();
+
+ /* what if x < 0 ?? */
+ if (ieee754sp_lt(x, hb))
+ return (unsigned) ieee754sp_tint(x);
+
+ return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
+ ((unsigned) 1 << 31);
+}
diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c
new file mode 100644
index 000000000..23a2abf4d
--- /dev/null
+++ b/arch/mips/math-emu/sp_tlong.c
@@ -0,0 +1,95 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <limits.h>
+#ifdef __KERNEL__
+#define assert(expr) ((void)0)
+#else
+#include <assert.h>
+#endif
+#include <stdarg.h>
+
+#include "ieee754sp.h"
+
+long long ieee754sp_tlong(ieee754sp x)
+{
+ COMPXDP; /* <-- need 64-bit mantissa tmp */
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM: /* much to small */
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754di_xcpt(0, "sp_tlong", x);
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 63) {
+ SETCX(IEEE754_OVERFLOW);
+ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ }
+ if (xe < 0) {
+ SETCX(IEEE754_UNDERFLOW);
+ return ieee754di_xcpt(0, "sp_tlong", x);
+ }
+ /* oh gawd */
+ if (xe > SP_MBITS) {
+ xm <<= xe - SP_MBITS;
+ } else if (xe < SP_MBITS) {
+ /* XXX no rounding
+ */
+ xm >>= SP_MBITS - xe;
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+unsigned long long ieee754sp_tulong(ieee754sp x)
+{
+ ieee754sp hb = ieee754sp_1e63();
+
+ /* what if x < 0 ?? */
+ if (ieee754sp_lt(x, hb))
+ return (unsigned long long) ieee754sp_tlong(x);
+
+ return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
+ (1ULL << 63);
+}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 289dcd041..c632eee00 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -1,5 +1,4 @@
-/* $Id: init.c,v 1.26 2000/02/23 00:41:00 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -29,6 +28,7 @@
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
+#include <asm/cpu.h>
#include <asm/dma.h>
#include <asm/jazzdma.h>
#include <asm/system.h>
@@ -123,7 +123,7 @@ static inline unsigned long setup_zero_pages(void)
unsigned long order, size;
struct page *page;
- switch (mips_cputype) {
+ switch (mips_cpu.cputype) {
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_R4400SC:
diff --git a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c
index 748b9945f..ef7b4c3e1 100644
--- a/arch/mips/mm/loadmmu.c
+++ b/arch/mips/mm/loadmmu.c
@@ -9,10 +9,11 @@
#include <linux/sched.h>
#include <linux/mm.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/bootinfo.h>
/* memory functions */
void (*_clear_page)(void * page);
@@ -45,7 +46,7 @@ extern void ld_mmu_andes(void);
void __init loadmmu(void)
{
- switch(mips_cputype) {
+ switch (mips_cpu.cputype) {
#ifdef CONFIG_CPU_R3000
case CPU_R2000:
case CPU_R3000:
diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c
index 6f9718bea..b5bdafed4 100644
--- a/arch/mips/mm/r4xx0.c
+++ b/arch/mips/mm/r4xx0.c
@@ -19,12 +19,13 @@
#include <linux/sched.h>
#include <linux/mm.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/bcache.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/bootinfo.h>
#include <asm/mmu_context.h>
/* CP0 hazard avoidance. */
@@ -2699,7 +2700,7 @@ void __init ld_mmu_r4xx0(void)
probe_dcache(config);
setup_scache(config);
- switch(mips_cputype) {
+ switch(mips_cpu.cputype) {
case CPU_R4600: /* QED style two way caches? */
case CPU_R4700:
case CPU_R5000: