From: James S. <jsi...@us...> - 2002-04-24 17:34:16
|
Update of /cvsroot/linux-mips/linux/arch/mips64/kernel In directory usw-pr-cvs1:/tmp/cvs-serv16961 Modified Files: traps.c unaligned.c Log Message: FPU emulator for the 64-bit kernel. Index: traps.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips64/kernel/traps.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- traps.c 21 Apr 2002 20:01:14 -0000 1.15 +++ traps.c 24 Apr 2002 17:34:12 -0000 1.16 @@ -49,6 +49,9 @@ extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); +extern int fpu_emulator_cop1Handler(struct pt_regs *); +void fpu_emulator_init_fpu(void); + char watch_available = 0; char dedicated_iv_available = 0; @@ -471,11 +474,15 @@ void do_cpu(struct pt_regs *regs) { u32 cpid; + int sig; cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; if (cpid != 1) goto bad_cid; + if (!(mips_cpu.options & MIPS_CPU_FPU)) + goto fp_emul; + regs->cp0_status |= ST0_CU1; #ifdef CONFIG_SMP @@ -499,6 +506,16 @@ } last_task_used_math = current; #endif + return; + +fp_emul: + if (!current->used_math) { + fpu_emulator_init_fpu(); + current->used_math = 1; + } + sig = fpu_emulator_cop1Handler(regs); + if (sig) + force_sig(sig, current); return; bad_cid: Index: unaligned.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips64/kernel/unaligned.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- unaligned.c 26 Feb 2002 17:34:15 -0000 1.5 +++ unaligned.c 24 Apr 2002 17:34:12 -0000 1.6 @@ -381,10 +381,24 @@ asmlinkage void do_ade(struct pt_regs *regs) { unsigned long pc; + extern int do_dsemulret(struct pt_regs *); + #if 0 printk("ade: Cpu%d[%s:%d:%0lx:%0lx]\n", smp_processor_id(), current->comm, current->pid, regs->cp0_badvaddr, regs->cp0_epc); #endif + + /* + * 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. + */ + /* Terminate if exception was recognized as a delay slot return */ + if (do_dsemulret(regs)) + return; + + /* Otherwise handle as normal */ /* * Did we catch a fault trying to load an instruction? |