summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-12-10 07:56:02 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-12-10 07:56:02 +0000
commit57826f276a6fc8de0665dd956f78533fe0c25c7e (patch)
tree467de18afa9e4a3b3c02073a945a317a850991d7
parent5c03a0eb664aa8802f9e3ede6fb6531581302762 (diff)
Final round of FPU emulator bits.
-rw-r--r--arch/mips/kernel/ptrace.c38
-rw-r--r--arch/mips/kernel/r2300_fpu.S13
-rw-r--r--arch/mips/kernel/r4k_fpu.S13
-rw-r--r--arch/mips/kernel/r6000_fpu.S10
-rw-r--r--arch/mips/kernel/signal.c5
-rw-r--r--arch/mips/kernel/traps.c233
-rw-r--r--arch/mips/kernel/unaligned.c15
-rw-r--r--arch/mips/math-emu/cp1emu.c16
-rw-r--r--arch/mips/tools/offset.c11
-rw-r--r--include/asm-mips/asmmacro.h200
-rw-r--r--include/asm-mips/system.h8
11 files changed, 345 insertions, 217 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 618f418f8..02ef1a754 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -7,7 +7,10 @@
* Copyright (C) Linus Torvalds
* Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
* Copyright (C) 1996 David S. Miller
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999 MIPS Technologies, Inc.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -24,6 +27,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
@@ -131,13 +135,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
break;
case FPR_BASE ... FPR_BASE + 31:
if (child->used_math) {
+ unsigned long long *fregs
+ = (unsigned long long *)
+ &child->thread.fpu.hard.fp_regs[0];
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+ fregs = (unsigned long long *)
+ &child->thread.fpu.soft.regs[0];
+ } else
+#endif
if (last_task_used_math == child) {
enable_cp1();
save_fp(child);
disable_cp1();
last_task_used_math = NULL;
}
- tmp = child->thread.fpu.hard.fp_regs[addr - 32];
+ tmp = (unsigned long) fregs[(addr - 32)];
} else {
tmp = -1; /* FP not yet used */
}
@@ -158,6 +171,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
tmp = regs->lo;
break;
case FPC_CSR:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU))
+ tmp = child->thread.fpu.soft.sr;
+ else
+#endif
tmp = child->thread.fpu.hard.control;
break;
case FPC_EIR: { /* implementation / version register */
@@ -198,9 +216,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
regs->regs[addr] = data;
break;
case FPR_BASE ... FPR_BASE + 31: {
- unsigned int *fregs;
+ unsigned long long *fregs;
+ fregs = (unsigned long long *)&child->thread.fpu.hard.fp_regs[0];
if (child->used_math) {
- if (last_task_used_math == child) {
+ if (last_task_used_math == child)
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+ fregs = (unsigned long long *)
+ &child->thread.fpu.soft.regs[0];
+ } else
+#endif
+ {
enable_cp1();
save_fp(child);
disable_cp1();
@@ -213,7 +239,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
sizeof(child->thread.fpu.hard));
child->thread.fpu.hard.control = 0;
}
- fregs = child->thread.fpu.hard.fp_regs;
fregs[addr - FPR_BASE] = data;
break;
}
@@ -227,6 +252,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
regs->lo = data;
break;
case FPC_CSR:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ if(!(mips_cpu.options & MIPS_CPU_FPU))
+ child->thread.fpu.soft.sr = data;
+ else
+#endif
child->thread.fpu.hard.control = data;
break;
default:
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
index efb00dce1..34881ef94 100644
--- a/arch/mips/kernel/r2300_fpu.S
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -1,7 +1,4 @@
-/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $
- *
- * r2300_fpu.S: Save/restore floating point context for signal handlers.
- *
+/*
* 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.
@@ -30,7 +27,7 @@
.set noreorder
.set mips1
/* Save floating point context */
-LEAF(save_fp_context)
+LEAF(_save_fp_context)
li v0, 0 # assume success
cfc1 t1,fcr31
EX(swc1 $f0,(SC_FPREGS+0)(a0))
@@ -71,7 +68,7 @@ LEAF(save_fp_context)
.set nomacro
EX(sw t0,SC_FPC_EIR(a0))
.set macro
- END(save_fp_context)
+ END(_save_fp_context)
/*
* Restore FPU state:
@@ -82,7 +79,7 @@ LEAF(save_fp_context)
* frame on the current content of c0_status, not on the content of the
* stack frame which might have been changed by the user.
*/
-LEAF(restore_fp_context)
+LEAF(_restore_fp_context)
li v0, 0 # assume success
EX(lw t0,SC_FPC_CSR(a0))
EX(lwc1 $f0,(SC_FPREGS+0)(a0))
@@ -119,7 +116,7 @@ LEAF(restore_fp_context)
EX(lwc1 $f31,(SC_FPREGS+248)(a0))
jr ra
ctc1 t0,fcr31
- END(restore_fp_context)
+ END(_restore_fp_context)
.type fault@function
.ent fault
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index d55ac303a..6ad810d04 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -1,6 +1,4 @@
/*
- * r4k_fpu.S: Save/restore floating point context for signal handlers.
- *
* 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.
@@ -9,6 +7,9 @@
*
* Multi-arch abstraction and asm macros for easier reading:
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
*/
#include <asm/asm.h>
#include <asm/errno.h>
@@ -26,7 +27,7 @@
.set noreorder
.set mips3
/* Save floating point context */
-LEAF(save_fp_context)
+LEAF(_save_fp_context)
li v0, 0 # assume success
cfc1 t1,fcr31
@@ -54,7 +55,7 @@ LEAF(save_fp_context)
.set nomacro
EX(sw t0,SC_FPC_EIR(a0))
.set macro
- END(save_fp_context)
+ END(_save_fp_context)
/*
* Restore FPU state:
@@ -65,7 +66,7 @@ LEAF(save_fp_context)
* frame on the current content of c0_status, not on the content of the
* stack frame which might have been changed by the user.
*/
-LEAF(restore_fp_context)
+LEAF(_restore_fp_context)
li v0, 0 # assume success
EX(lw t0,SC_FPC_CSR(a0))
@@ -91,7 +92,7 @@ LEAF(restore_fp_context)
EX(ldc1 $f30,(SC_FPREGS+240)(a0))
jr ra
ctc1 t0,fcr31
- END(restore_fp_context)
+ END(_restore_fp_context)
.type fault@function
.ent fault
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
index 851b4dc48..d8d3b13fe 100644
--- a/arch/mips/kernel/r6000_fpu.S
+++ b/arch/mips/kernel/r6000_fpu.S
@@ -9,8 +9,6 @@
*
* Multi-arch abstraction and asm macros for easier reading:
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $
*/
#include <asm/asm.h>
#include <asm/fpregdef.h>
@@ -21,7 +19,7 @@
.set noreorder
.set mips2
/* Save floating point context */
- LEAF(save_fp_context)
+ LEAF(_save_fp_context)
mfc0 t0,CP0_STATUS
sll t0,t0,2
bgez t0,1f
@@ -49,7 +47,7 @@
sw t0,SC_FPC_CSR(a0)
1: jr ra
nop
- END(save_fp_context)
+ END(_save_fp_context)
/* Restore FPU state:
* - fp gp registers
@@ -59,7 +57,7 @@
* frame on the current content of c0_status, not on the content of the
* stack frame which might have been changed by the user.
*/
- LEAF(restore_fp_context)
+ LEAF(_restore_fp_context)
mfc0 t0,CP0_STATUS
sll t0,t0,2
@@ -86,4 +84,4 @@
ctc1 t0,fcr31
1: jr ra
nop
- END(restore_fp_context)
+ END(_restore_fp_context)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index ed821d7df..a1e26db87 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -33,8 +33,9 @@
extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
int options, unsigned long *ru);
extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern asmlinkage int save_fp_context(struct sigcontext *sc);
-extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
extern asmlinkage void syscall_trace(void);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 0abd55e78..779b72805 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -7,6 +7,9 @@
* Modified for R3000 by Paul M. Antoine, 1995, 1996
* Complete output from die() by Ulf Carlsson, 1998
* Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * 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/init.h>
@@ -28,6 +31,9 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
+#ifndef CONFIG_MIPS_FPU_EMULATOR
+#include <asm/inst.h>
+#endif
extern int console_loglevel;
@@ -66,6 +72,7 @@ extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
extern asmlinkage void handle_fpe(void);
extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void);
extern int fpu_emulator_cop1Handler(int, struct pt_regs *);
@@ -377,6 +384,8 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
/* Retry instruction with flush to zero ... */
if (!(fcr31 & (1<<24))) {
+ printk("Setting flush to zero for %s.\n",
+ current->comm);
fcr31 &= ~FPU_CSR_UNI_X;
fcr31 |= (1<<24);
__asm__ __volatile__(
@@ -386,13 +395,26 @@ 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))
+ if(pc & 0x80000000) insn = *(unsigned int *)pc;
+ else if (get_user(insn, (unsigned int *)pc)) {
+ /* XXX Can this happen? */
force_sig(SIGSEGV, current);
-#endif /* !CONFIG_MIPS_FPU_EMULATOR */
+ }
+
+ printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
+ insn, regs->cp0_epc, current->comm);
+ simfp(MIPSInst(insn));
+ compute_return_epc(regs);
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
+
+ return;
}
- if (!compute_return_epc(regs))
- force_sig(SIGFPE, current);
+ if (compute_return_epc(regs))
+ return;
+
+ force_sig(SIGFPE, current);
+ printk(KERN_DEBUG "Sent send SIGFPE to %s\n", current->comm);
}
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -465,8 +487,9 @@ void do_ri(struct pt_regs *regs)
if ((opcode & OPCODE) == SC)
simulate_sc(regs, opcode);
} else {
- printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
- current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+ printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n",
+ current->comm, (unsigned long)current->pid, opcode,
+ regs->cp0_epc, regs->regs[31]);
}
if (compute_return_epc(regs))
return;
@@ -553,8 +576,12 @@ void simulate_sc(struct pt_regs *regp, unsigned int opcode)
void do_ri(struct pt_regs *regs)
{
- printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
- current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+ unsigned int opcode;
+
+ get_insn_opcode(regs, &opcode);
+ printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n",
+ current->comm, (unsigned long)current->pid, opcode,
+ regs->cp0_epc, regs->regs[31]);
if (compute_return_epc(regs))
return;
force_sig(SIGILL, current);
@@ -622,6 +649,12 @@ void do_watch(struct pt_regs *regs)
panic("Caught WATCH exception - probably caused by stack overflow.");
}
+void do_mcheck(struct pt_regs *regs)
+{
+ show_regs(regs);
+ panic("Caught Machine Check exception - probably caused by multiple matching entries in the TLB.");
+}
+
void do_reserved(struct pt_regs *regs)
{
/*
@@ -632,40 +665,61 @@ void do_reserved(struct pt_regs *regs)
panic("Caught reserved exception - should not happen.");
}
-static inline void watch_init(unsigned long cputype)
+static inline void watch_init(void)
{
- switch(cputype) {
- case CPU_R10000:
- case CPU_R4000MC:
- case CPU_R4400MC:
- case CPU_R4000SC:
- case CPU_R4400SC:
- case CPU_R4000PC:
- case CPU_R4400PC:
- case CPU_R4200:
- case CPU_R4300:
- set_except_vector(23, handle_watch);
- watch_available = 1;
- break;
- }
+ if(mips_cpu.options & MIPS_CPU_WATCH ) {
+ (void)set_except_vector(23, handle_watch);
+ watch_available = 1;
+ }
}
/*
* Some MIPS CPUs have a dedicated interrupt vector which reduces the
* interrupt processing overhead. Use it where available.
- * FIXME: more CPUs than just the Nevada have this feature.
*/
static inline void setup_dedicated_int(void)
{
extern void except_vec4(void);
- switch(mips_cpu.cputype) {
- case CPU_NEVADA:
+
+ if(mips_cpu.options & MIPS_CPU_DIVEC) {
memcpy((void *)(KSEG0 + 0x200), except_vec4, 8);
set_cp0_cause(CAUSEF_IV, CAUSEF_IV);
dedicated_iv_available = 1;
}
}
+/*
+ * Some MIPS CPUs can enable/disable for cache parity detection, but does
+ * it different ways.
+ */
+static inline void parity_protection_init(void)
+{
+ switch(mips_cpu.cputype)
+ {
+ case CPU_5KC:
+ /* Set the PE bit (bit 31) in the CP0_ECC register. */
+ printk("Enable the cache parity protection for MIPS 5KC CPUs.\n");
+ write_32bit_cp0_register(CP0_ECC, read_32bit_cp0_register(CP0_ECC)
+ | 0x80000000);
+ break;
+ default:
+ }
+}
+
+void cache_parity_error(void)
+{
+ unsigned int reg_val;
+
+ /* For the moment, report the problem and hang. */
+ reg_val = read_32bit_cp0_register(CP0_ERROREPC);
+ printk("Cache error exception:\n");
+ printk("cp0_errorepc == %08x\n", reg_val);
+ reg_val = read_32bit_cp0_register(CP0_CACHEERR);
+ printk("c0_cacheerr == %08x\n", reg_val);
+
+ panic("Can't handle the cache error - panic!");
+}
+
unsigned long exception_handlers[32];
/*
@@ -673,23 +727,36 @@ unsigned long exception_handlers[32];
* to interrupt handlers in the address range from
* KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ...
*/
-void set_except_vector(int n, void *addr)
+void *set_except_vector(int n, void *addr)
{
unsigned handler = (unsigned long) addr;
+ unsigned old_handler = exception_handlers[n];
exception_handlers[n] = handler;
if (n == 0 && dedicated_iv_available) {
*(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
(0x03ffffff & (handler >> 2));
flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
}
+ return (void *)old_handler;
}
+asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage int _save_fp_context(struct sigcontext *sc);
+extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+#endif
+
void __init trap_init(void)
{
extern char except_vec0_nevada, except_vec0_r4000;
extern char except_vec0_r4600, except_vec0_r2300;
extern char except_vec1_generic, except_vec2_generic;
extern char except_vec3_generic, except_vec3_r4000;
+ extern char except_vec_ejtag_debug;
unsigned long i;
if(mips_machtype == MACH_MIPS_MAGNUM_4000 ||
@@ -708,71 +775,55 @@ void __init trap_init(void)
* Setup default vectors
*/
for(i = 0; i <= 31; i++)
- set_except_vector(i, handle_reserved);
+ (void)set_except_vector(i, handle_reserved);
+
+ /*
+ * Copy the EJTAG debug exception vector handler code to it's final
+ * destination.
+ */
+ memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
/*
* Only some CPUs have the watch exceptions or a dedicated
* interrupt vector.
*/
- watch_init(mips_cpu.cputype);
+ watch_init();
setup_dedicated_int();
- set_except_vector(1, handle_mod);
- set_except_vector(2, handle_tlbl);
- set_except_vector(3, handle_tlbs);
- set_except_vector(4, handle_adel);
- set_except_vector(5, handle_ades);
+ /*
+ * Some CPUs can enable/disable for cache parity detection, but does
+ * it different ways.
+ */
+ parity_protection_init();
+
+ (void)set_except_vector(1, handle_mod);
+ (void)set_except_vector(2, handle_tlbl);
+ (void)set_except_vector(3, handle_tlbs);
+ (void)set_except_vector(4, handle_adel);
+ (void)set_except_vector(5, handle_ades);
/*
* The Data Bus Error/ Instruction Bus Errors are signaled
* by external hardware. Therefore these two expection have
* board specific handlers.
*/
- set_except_vector(6, handle_ibe);
- set_except_vector(7, handle_dbe);
+ (void)set_except_vector(6, handle_ibe);
+ (void)set_except_vector(7, handle_dbe);
ibe_board_handler = default_be_board_handler;
dbe_board_handler = default_be_board_handler;
- set_except_vector(8, handle_sys);
- set_except_vector(9, handle_bp);
- set_except_vector(10, handle_ri);
- set_except_vector(11, handle_cpu);
- set_except_vector(12, handle_ov);
- set_except_vector(13, handle_tr);
- set_except_vector(15, handle_fpe);
-
+ (void)set_except_vector(8, handle_sys);
+ (void)set_except_vector(9, handle_bp);
+ (void)set_except_vector(10, handle_ri);
+ (void)set_except_vector(11, handle_cpu);
+ (void)set_except_vector(12, handle_ov);
+ (void)set_except_vector(13, handle_tr);
+ (void)set_except_vector(15, handle_fpe);
+
/*
* Handling the following exceptions depends mostly of the cpu type
*/
- switch(mips_cpu.cputype) {
- case CPU_R10000:
- /*
- * The R10000 is in most aspects similar to the R4400. It
- * should get some special optimizations.
- */
- write_32bit_cp0_register(CP0_FRAMEMASK, 0);
- set_cp0_status(ST0_XX, ST0_XX);
- /*
- * The R10k might even work for Linux/MIPS - but we're paranoid
- * and refuse to run until this is tested on real silicon
- */
- panic("CPU too expensive - making holiday in the ANDES!");
- break;
- case CPU_R4000MC:
- case CPU_R4400MC:
- case CPU_R4000SC:
- case CPU_R4400SC:
- vce_available = 1;
- /* Fall through ... */
- case CPU_R4000PC:
- case CPU_R4400PC:
- case CPU_R4200:
- case CPU_R4300:
- /* case CPU_R4640: */
- case CPU_R4600:
- case CPU_R5000:
- case CPU_R5432:
- case CPU_NEVADA:
- case CPU_RM7000:
+ if((mips_cpu.options & MIPS_CPU_4KEX)
+ && (mips_cpu.options & MIPS_CPU_4KTLB)) {
if(mips_cpu.cputype == CPU_NEVADA) {
memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
} else if (mips_cpu.cputype == CPU_R4600)
@@ -782,17 +833,41 @@ void __init trap_init(void)
/* Cache error vector already set above. */
- if (vce_available) {
+ if (mips_cpu.options & MIPS_CPU_VCE) {
memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
0x80);
} else {
memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
0x80);
}
- break;
+ if(mips_cpu.options & MIPS_CPU_FPU) {
+ save_fp_context = _save_fp_context;
+ restore_fp_context = _restore_fp_context;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ } else {
+ save_fp_context = fpu_emulator_save_context;
+ restore_fp_context = fpu_emulator_restore_context;
+#endif
+ }
+ } else switch(mips_cpu.cputype) {
+ case CPU_R10000:
+ /*
+ * The R10000 is in most aspects similar to the R4400. It
+ * should get some special optimizations.
+ */
+ write_32bit_cp0_register(CP0_FRAMEMASK, 0);
+ set_cp0_status(ST0_XX, ST0_XX);
+ /*
+ * The R10k might even work for Linux/MIPS - but we're paranoid
+ * and refuse to run until this is tested on real silicon
+ */
+ panic("CPU too expensive - making holiday in the ANDES!");
+ break;
case CPU_R6000:
case CPU_R6000A:
+ save_fp_context = _save_fp_context;
+ restore_fp_context = _restore_fp_context;
#if 0
/*
* The R6000 is the only R-series CPU that features a machine
@@ -802,8 +877,8 @@ void __init trap_init(void)
* current list of targets for Linux/MIPS.
* (Duh, crap, there is someone with a tripple R6k machine)
*/
- set_except_vector(14, handle_mc);
- set_except_vector(15, handle_ndc);
+ (void)set_except_vector(14, handle_mc);
+ (void)set_except_vector(15, handle_ndc);
#endif
case CPU_R2000:
case CPU_R3000:
@@ -813,6 +888,8 @@ void __init trap_init(void)
case CPU_R3052:
case CPU_R3081:
case CPU_R3081E:
+ save_fp_context = _save_fp_context;
+ restore_fp_context = _restore_fp_context;
memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
break;
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index a5b8791c1..672388d52 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -379,6 +379,21 @@ unsigned long unaligned_instructions;
asmlinkage void do_ade(struct pt_regs *regs)
{
unsigned long pc;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+ extern int do_dsemulret(struct pt_regs *);
+
+ /*
+ * Address errors may be deliberately induced
+ * by the FPU emulator to take retake control
+ * of the CPU after executing the instruction
+ * in the delay slot of an emulated branch.
+ */
+
+ if((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) {
+ (void)do_dsemulret(regs);
+ return;
+ }
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
/*
* Did we catch a fault trying to load an instruction?
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index a95e4e600..e26bacd24 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -872,14 +872,14 @@ mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
* 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 */
+ 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])
diff --git a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c
index 977a791d8..7df4a6c1d 100644
--- a/arch/mips/tools/offset.c
+++ b/arch/mips/tools/offset.c
@@ -1,12 +1,13 @@
-/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $
- *
+/*
* offset.c: Calculate pt_regs and task_struct offsets.
*
* Copyright (C) 1996 David S. Miller
* Copyright (C) 1997, 1998, 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
*/
-
#include <linux/types.h>
#include <linux/sched.h>
@@ -120,6 +121,10 @@ void output_thread_defines(void)
thread.irix_trampoline);
offset("#define THREAD_OLDCTX ", struct task_struct, \
thread.irix_oldctx);
+ offset("#define THREAD_DSEEPC ", struct task_struct, \
+ thread.dsemul_epc);
+ offset("#define THREAD_DSEAERPC ", struct task_struct, \
+ thread.dsemul_aerpc);
linefeed;
}
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index fb3692dd7..7becc9bd1 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -3,124 +3,122 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
* Copyright (C) 1998 Ralf Baechle
- *
- * $Id: asmmacro.h,v 1.3 1998/03/27 04:47:58 ralf Exp $
*/
-#ifndef __MIPS_ASMMACRO_H
-#define __MIPS_ASMMACRO_H
+#ifndef _ASM_ASMMACRO_H
+#define _ASM_ASMMACRO_H
#include <asm/offset.h>
#define FPU_SAVE_DOUBLE(thread, tmp) \
cfc1 tmp, fcr31; \
sdc1 $f0, (THREAD_FPU + 0x000)(thread); \
- sdc1 $f2, (THREAD_FPU + 0x008)(thread); \
- sdc1 $f4, (THREAD_FPU + 0x010)(thread); \
- sdc1 $f6, (THREAD_FPU + 0x018)(thread); \
- sdc1 $f8, (THREAD_FPU + 0x020)(thread); \
- sdc1 $f10, (THREAD_FPU + 0x028)(thread); \
- sdc1 $f12, (THREAD_FPU + 0x030)(thread); \
- sdc1 $f14, (THREAD_FPU + 0x038)(thread); \
- sdc1 $f16, (THREAD_FPU + 0x040)(thread); \
- sdc1 $f18, (THREAD_FPU + 0x048)(thread); \
- sdc1 $f20, (THREAD_FPU + 0x050)(thread); \
- sdc1 $f22, (THREAD_FPU + 0x058)(thread); \
- sdc1 $f24, (THREAD_FPU + 0x060)(thread); \
- sdc1 $f26, (THREAD_FPU + 0x068)(thread); \
- sdc1 $f28, (THREAD_FPU + 0x070)(thread); \
- sdc1 $f30, (THREAD_FPU + 0x078)(thread); \
- sw tmp, (THREAD_FPU + 0x080)(thread)
+ sdc1 $f2, (THREAD_FPU + 0x010)(thread); \
+ sdc1 $f4, (THREAD_FPU + 0x020)(thread); \
+ sdc1 $f6, (THREAD_FPU + 0x030)(thread); \
+ sdc1 $f8, (THREAD_FPU + 0x040)(thread); \
+ sdc1 $f10, (THREAD_FPU + 0x050)(thread); \
+ sdc1 $f12, (THREAD_FPU + 0x060)(thread); \
+ sdc1 $f14, (THREAD_FPU + 0x070)(thread); \
+ sdc1 $f16, (THREAD_FPU + 0x080)(thread); \
+ sdc1 $f18, (THREAD_FPU + 0x090)(thread); \
+ sdc1 $f20, (THREAD_FPU + 0x0a0)(thread); \
+ sdc1 $f22, (THREAD_FPU + 0x0b0)(thread); \
+ sdc1 $f24, (THREAD_FPU + 0x0c0)(thread); \
+ sdc1 $f26, (THREAD_FPU + 0x0d0)(thread); \
+ sdc1 $f28, (THREAD_FPU + 0x0e0)(thread); \
+ sdc1 $f30, (THREAD_FPU + 0x0f0)(thread); \
+ sw tmp, (THREAD_FPU + 0x100)(thread)
#define FPU_SAVE_SINGLE(thread,tmp) \
cfc1 tmp, fcr31; \
swc1 $f0, (THREAD_FPU + 0x000)(thread); \
- swc1 $f1, (THREAD_FPU + 0x004)(thread); \
- swc1 $f2, (THREAD_FPU + 0x008)(thread); \
- swc1 $f3, (THREAD_FPU + 0x00c)(thread); \
- swc1 $f4, (THREAD_FPU + 0x010)(thread); \
- swc1 $f5, (THREAD_FPU + 0x014)(thread); \
- swc1 $f6, (THREAD_FPU + 0x018)(thread); \
- swc1 $f7, (THREAD_FPU + 0x01c)(thread); \
- swc1 $f8, (THREAD_FPU + 0x020)(thread); \
- swc1 $f9, (THREAD_FPU + 0x024)(thread); \
- swc1 $f10, (THREAD_FPU + 0x028)(thread); \
- swc1 $f11, (THREAD_FPU + 0x02c)(thread); \
- swc1 $f12, (THREAD_FPU + 0x030)(thread); \
- swc1 $f13, (THREAD_FPU + 0x034)(thread); \
- swc1 $f14, (THREAD_FPU + 0x038)(thread); \
- swc1 $f15, (THREAD_FPU + 0x03c)(thread); \
- swc1 $f16, (THREAD_FPU + 0x040)(thread); \
- swc1 $f17, (THREAD_FPU + 0x044)(thread); \
- swc1 $f18, (THREAD_FPU + 0x048)(thread); \
- swc1 $f19, (THREAD_FPU + 0x04c)(thread); \
- swc1 $f20, (THREAD_FPU + 0x050)(thread); \
- swc1 $f21, (THREAD_FPU + 0x054)(thread); \
- swc1 $f22, (THREAD_FPU + 0x058)(thread); \
- swc1 $f23, (THREAD_FPU + 0x05c)(thread); \
- swc1 $f24, (THREAD_FPU + 0x060)(thread); \
- swc1 $f25, (THREAD_FPU + 0x064)(thread); \
- swc1 $f26, (THREAD_FPU + 0x068)(thread); \
- swc1 $f27, (THREAD_FPU + 0x06c)(thread); \
- swc1 $f28, (THREAD_FPU + 0x070)(thread); \
- swc1 $f29, (THREAD_FPU + 0x074)(thread); \
- swc1 $f30, (THREAD_FPU + 0x078)(thread); \
- swc1 $f31, (THREAD_FPU + 0x07c)(thread); \
- sw tmp, (THREAD_FPU + 0x080)(thread)
+ swc1 $f1, (THREAD_FPU + 0x008)(thread); \
+ swc1 $f2, (THREAD_FPU + 0x010)(thread); \
+ swc1 $f3, (THREAD_FPU + 0x018)(thread); \
+ swc1 $f4, (THREAD_FPU + 0x020)(thread); \
+ swc1 $f5, (THREAD_FPU + 0x028)(thread); \
+ swc1 $f6, (THREAD_FPU + 0x030)(thread); \
+ swc1 $f7, (THREAD_FPU + 0x038)(thread); \
+ swc1 $f8, (THREAD_FPU + 0x040)(thread); \
+ swc1 $f9, (THREAD_FPU + 0x048)(thread); \
+ swc1 $f10, (THREAD_FPU + 0x050)(thread); \
+ swc1 $f11, (THREAD_FPU + 0x058)(thread); \
+ swc1 $f12, (THREAD_FPU + 0x060)(thread); \
+ swc1 $f13, (THREAD_FPU + 0x068)(thread); \
+ swc1 $f14, (THREAD_FPU + 0x070)(thread); \
+ swc1 $f15, (THREAD_FPU + 0x078)(thread); \
+ swc1 $f16, (THREAD_FPU + 0x080)(thread); \
+ swc1 $f17, (THREAD_FPU + 0x088)(thread); \
+ swc1 $f18, (THREAD_FPU + 0x090)(thread); \
+ swc1 $f19, (THREAD_FPU + 0x098)(thread); \
+ swc1 $f20, (THREAD_FPU + 0x0a0)(thread); \
+ swc1 $f21, (THREAD_FPU + 0x0a8)(thread); \
+ swc1 $f22, (THREAD_FPU + 0x0b0)(thread); \
+ swc1 $f23, (THREAD_FPU + 0x0b8)(thread); \
+ swc1 $f24, (THREAD_FPU + 0x0c0)(thread); \
+ swc1 $f25, (THREAD_FPU + 0x0c8)(thread); \
+ swc1 $f26, (THREAD_FPU + 0x0d0)(thread); \
+ swc1 $f27, (THREAD_FPU + 0x0d8)(thread); \
+ swc1 $f28, (THREAD_FPU + 0x0e0)(thread); \
+ swc1 $f29, (THREAD_FPU + 0x0e8)(thread); \
+ swc1 $f30, (THREAD_FPU + 0x0f0)(thread); \
+ swc1 $f31, (THREAD_FPU + 0x0f8)(thread); \
+ sw tmp, (THREAD_FPU + 0x100)(thread)
#define FPU_RESTORE_DOUBLE(thread, tmp) \
- lw tmp, (THREAD_FPU + 0x080)(thread); \
+ lw tmp, (THREAD_FPU + 0x100)(thread); \
ldc1 $f0, (THREAD_FPU + 0x000)(thread); \
- ldc1 $f2, (THREAD_FPU + 0x008)(thread); \
- ldc1 $f4, (THREAD_FPU + 0x010)(thread); \
- ldc1 $f6, (THREAD_FPU + 0x018)(thread); \
- ldc1 $f8, (THREAD_FPU + 0x020)(thread); \
- ldc1 $f10, (THREAD_FPU + 0x028)(thread); \
- ldc1 $f12, (THREAD_FPU + 0x030)(thread); \
- ldc1 $f14, (THREAD_FPU + 0x038)(thread); \
- ldc1 $f16, (THREAD_FPU + 0x040)(thread); \
- ldc1 $f18, (THREAD_FPU + 0x048)(thread); \
- ldc1 $f20, (THREAD_FPU + 0x050)(thread); \
- ldc1 $f22, (THREAD_FPU + 0x058)(thread); \
- ldc1 $f24, (THREAD_FPU + 0x060)(thread); \
- ldc1 $f26, (THREAD_FPU + 0x068)(thread); \
- ldc1 $f28, (THREAD_FPU + 0x070)(thread); \
- ldc1 $f30, (THREAD_FPU + 0x078)(thread); \
+ ldc1 $f2, (THREAD_FPU + 0x010)(thread); \
+ ldc1 $f4, (THREAD_FPU + 0x020)(thread); \
+ ldc1 $f6, (THREAD_FPU + 0x030)(thread); \
+ ldc1 $f8, (THREAD_FPU + 0x040)(thread); \
+ ldc1 $f10, (THREAD_FPU + 0x050)(thread); \
+ ldc1 $f12, (THREAD_FPU + 0x060)(thread); \
+ ldc1 $f14, (THREAD_FPU + 0x070)(thread); \
+ ldc1 $f16, (THREAD_FPU + 0x080)(thread); \
+ ldc1 $f18, (THREAD_FPU + 0x090)(thread); \
+ ldc1 $f20, (THREAD_FPU + 0x0a0)(thread); \
+ ldc1 $f22, (THREAD_FPU + 0x0b0)(thread); \
+ ldc1 $f24, (THREAD_FPU + 0x0c0)(thread); \
+ ldc1 $f26, (THREAD_FPU + 0x0d0)(thread); \
+ ldc1 $f28, (THREAD_FPU + 0x0e0)(thread); \
+ ldc1 $f30, (THREAD_FPU + 0x0f0)(thread); \
ctc1 tmp, fcr31
#define FPU_RESTORE_SINGLE(thread,tmp) \
- lw tmp, (THREAD_FPU + 0x080)(thread); \
+ lw tmp, (THREAD_FPU + 0x100)(thread); \
lwc1 $f0, (THREAD_FPU + 0x000)(thread); \
- lwc1 $f1, (THREAD_FPU + 0x004)(thread); \
- lwc1 $f2, (THREAD_FPU + 0x008)(thread); \
- lwc1 $f3, (THREAD_FPU + 0x00c)(thread); \
- lwc1 $f4, (THREAD_FPU + 0x010)(thread); \
- lwc1 $f5, (THREAD_FPU + 0x014)(thread); \
- lwc1 $f6, (THREAD_FPU + 0x018)(thread); \
- lwc1 $f7, (THREAD_FPU + 0x01c)(thread); \
- lwc1 $f8, (THREAD_FPU + 0x020)(thread); \
- lwc1 $f9, (THREAD_FPU + 0x024)(thread); \
- lwc1 $f10, (THREAD_FPU + 0x028)(thread); \
- lwc1 $f11, (THREAD_FPU + 0x02c)(thread); \
- lwc1 $f12, (THREAD_FPU + 0x030)(thread); \
- lwc1 $f13, (THREAD_FPU + 0x034)(thread); \
- lwc1 $f14, (THREAD_FPU + 0x038)(thread); \
- lwc1 $f15, (THREAD_FPU + 0x03c)(thread); \
- lwc1 $f16, (THREAD_FPU + 0x040)(thread); \
- lwc1 $f17, (THREAD_FPU + 0x044)(thread); \
- lwc1 $f18, (THREAD_FPU + 0x048)(thread); \
- lwc1 $f19, (THREAD_FPU + 0x04c)(thread); \
- lwc1 $f20, (THREAD_FPU + 0x050)(thread); \
- lwc1 $f21, (THREAD_FPU + 0x054)(thread); \
- lwc1 $f22, (THREAD_FPU + 0x058)(thread); \
- lwc1 $f23, (THREAD_FPU + 0x05c)(thread); \
- lwc1 $f24, (THREAD_FPU + 0x060)(thread); \
- lwc1 $f25, (THREAD_FPU + 0x064)(thread); \
- lwc1 $f26, (THREAD_FPU + 0x068)(thread); \
- lwc1 $f27, (THREAD_FPU + 0x06c)(thread); \
- lwc1 $f28, (THREAD_FPU + 0x070)(thread); \
- lwc1 $f29, (THREAD_FPU + 0x074)(thread); \
- lwc1 $f30, (THREAD_FPU + 0x078)(thread); \
- lwc1 $f31, (THREAD_FPU + 0x07c)(thread); \
+ lwc1 $f1, (THREAD_FPU + 0x008)(thread); \
+ lwc1 $f2, (THREAD_FPU + 0x010)(thread); \
+ lwc1 $f3, (THREAD_FPU + 0x018)(thread); \
+ lwc1 $f4, (THREAD_FPU + 0x020)(thread); \
+ lwc1 $f5, (THREAD_FPU + 0x028)(thread); \
+ lwc1 $f6, (THREAD_FPU + 0x030)(thread); \
+ lwc1 $f7, (THREAD_FPU + 0x038)(thread); \
+ lwc1 $f8, (THREAD_FPU + 0x040)(thread); \
+ lwc1 $f9, (THREAD_FPU + 0x048)(thread); \
+ lwc1 $f10, (THREAD_FPU + 0x050)(thread); \
+ lwc1 $f11, (THREAD_FPU + 0x058)(thread); \
+ lwc1 $f12, (THREAD_FPU + 0x060)(thread); \
+ lwc1 $f13, (THREAD_FPU + 0x068)(thread); \
+ lwc1 $f14, (THREAD_FPU + 0x070)(thread); \
+ lwc1 $f15, (THREAD_FPU + 0x078)(thread); \
+ lwc1 $f16, (THREAD_FPU + 0x080)(thread); \
+ lwc1 $f17, (THREAD_FPU + 0x088)(thread); \
+ lwc1 $f18, (THREAD_FPU + 0x090)(thread); \
+ lwc1 $f19, (THREAD_FPU + 0x098)(thread); \
+ lwc1 $f20, (THREAD_FPU + 0x0a0)(thread); \
+ lwc1 $f21, (THREAD_FPU + 0x0a8)(thread); \
+ lwc1 $f22, (THREAD_FPU + 0x0b0)(thread); \
+ lwc1 $f23, (THREAD_FPU + 0x0b8)(thread); \
+ lwc1 $f24, (THREAD_FPU + 0x0c0)(thread); \
+ lwc1 $f25, (THREAD_FPU + 0x0c8)(thread); \
+ lwc1 $f26, (THREAD_FPU + 0x0d0)(thread); \
+ lwc1 $f27, (THREAD_FPU + 0x0d8)(thread); \
+ lwc1 $f28, (THREAD_FPU + 0x0e0)(thread); \
+ lwc1 $f29, (THREAD_FPU + 0x0e8)(thread); \
+ lwc1 $f30, (THREAD_FPU + 0x0f0)(thread); \
+ lwc1 $f31, (THREAD_FPU + 0x0f8)(thread); \
ctc1 tmp, fcr31
#define CPU_SAVE_NONSCRATCH(thread) \
@@ -148,4 +146,4 @@
lw fp, THREAD_REG30(thread); \
lw ra, THREAD_REG31(thread)
-#endif /* !(__MIPS_ASMMACRO_H) */
+#endif /* _ASM_ASMMACRO_H */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index deca93a7b..68117be89 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -6,6 +6,12 @@
* Copyright (C) 1994 - 1999 by Ralf Baechle
* Copyright (C) 1996 by Paul M. Antoine
* Copyright (C) 1994 - 1999 by Ralf Baechle
+ *
+ * Changed set_except_vector declaration to allow return of previous
+ * vector address value - necessary for "borrowing" vectors.
+ *
+ * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
*/
#ifndef _ASM_SYSTEM_H
#define _ASM_SYSTEM_H
@@ -231,7 +237,7 @@ __xchg(unsigned long x, volatile void * ptr, int size)
return x;
}
-extern void set_except_vector(int n, void *addr);
+extern void *set_except_vector(int n, void *addr);
extern void __die(const char *, struct pt_regs *, const char *where,
unsigned long line) __attribute__((noreturn));