File: /usr/src/linux/arch/mips64/math-emu/cp1emu.c

1     /*
2      * MIPS floating point support
3      *
4      * This program is free software; you can distribute it and/or modify it
5      * under the terms of the GNU General Public License (Version 2) as
6      * published by the Free Software Foundation.
7      *
8      * This program is distributed in the hope it will be useful, but WITHOUT
9      * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10      * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11      * for more details.
12      *
13      * You should have received a copy of the GNU General Public License along
14      * with this program; if not, write to the Free Software Foundation, Inc.,
15      * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16      *
17      * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
18      * 
19      * A complete emulator for MIPS coprocessor 1 instructions.  This is
20      * required for #float(switch) or #float(trap), where it catches all
21      * COP1 instructions via the "CoProcessor Unusable" exception.  
22      *
23      * More surprisingly it is also required for #float(ieee), to help out
24      * the hardware fpu at the boundaries of the IEEE-754 representation
25      * (denormalised values, infinities, underflow, etc).  It is made
26      * quite nasty because emulation of some non-COP1 instructions is
27      * required, e.g. in branch delay slots.
28      * 
29      * Notes: 
30      *  1) the IEEE754 library (-le) performs the actual arithmetic;
31      *  2) if you know that you won't have an fpu, then you'll get much 
32      *     better performance by compiling with -msoft-float!  */
33      *
34      *  Nov 7, 2000
35      *  Massive changes to integrate with Linux kernel.
36      *
37      *  Replace use of kernel data area with use of user stack 
38      *  for execution of instructions in branch delay slots.
39      *
40      *  Replace use of static kernel variables with thread_struct elements.
41      *
42      * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
43      * http://www.algor.co.uk
44      *
45      * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
46      * Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
47      */
48     #include <linux/config.h>
49     #include <linux/mm.h>
50     #include <linux/signal.h>
51     #include <linux/smp.h>
52     #include <linux/smp_lock.h>
53     
54     #include <asm/asm.h>
55     #include <asm/branch.h>
56     #include <asm/bootinfo.h>
57     #include <asm/byteorder.h>
58     #include <asm/cpu.h>
59     #include <asm/inst.h>
60     #include <asm/uaccess.h>
61     #include <asm/processor.h>
62     #include <asm/mipsregs.h>
63     #include <asm/system.h>
64     #include <asm/pgtable.h>
65     
66     #include <asm/fpu_emulator.h>
67     
68     #include "ieee754.h"
69     
70     /* Strap kernel emulator for full MIPS IV emulation */
71     
72     #ifdef __mips
73     #undef __mips
74     #endif
75     #define __mips 4
76     
77     typedef void *vaddr_t;
78     
79     /* Function which emulates the instruction in a branch delay slot. */
80     
81     static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
82     
83     /* Function which emulates a floating point instruction. */
84     
85     static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
86     	 mips_instruction);
87     
88     #if __mips >= 4 && __mips != 32
89     static int fpux_emu(struct pt_regs *,
90     		    struct mips_fpu_soft_struct *, mips_instruction);
91     #endif
92     
93     /* Further private data for which no space exists in mips_fpu_soft_struct */
94     
95     struct mips_fpu_emulator_private fpuemuprivate;
96     
97     /* Control registers */
98     
99     #define FPCREG_RID	0	/* $0  = revision id */
100     #define FPCREG_CSR	31	/* $31 = csr */
101     
102     /* Convert Mips rounding mode (0..3) to IEEE library modes. */
103     static const unsigned char ieee_rm[4] = {
104     	IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
105     };
106     
107     #if __mips >= 4
108     /* convert condition code register number to csr bit */
109     static const unsigned int fpucondbit[8] = {
110     	FPU_CSR_COND0,
111     	FPU_CSR_COND1,
112     	FPU_CSR_COND2,
113     	FPU_CSR_COND3,
114     	FPU_CSR_COND4,
115     	FPU_CSR_COND5,
116     	FPU_CSR_COND6,
117     	FPU_CSR_COND7
118     };
119     #endif
120     
121     
122     
123     /* 
124      * Redundant with logic already in kernel/branch.c,
125      * embedded in compute_return_epc.  At some point,
126      * a single subroutine should be used across both
127      * modules.
128      */
129     static int isBranchInstr(mips_instruction * i)
130     {
131     	switch (MIPSInst_OPCODE(*i)) {
132     	case spec_op:
133     		switch (MIPSInst_FUNC(*i)) {
134     		case jalr_op:
135     		case jr_op:
136     			return 1;
137     		}
138     		break;
139     
140     	case bcond_op:
141     		switch (MIPSInst_RT(*i)) {
142     		case bltz_op:
143     		case bgez_op:
144     		case bltzl_op:
145     		case bgezl_op:
146     		case bltzal_op:
147     		case bgezal_op:
148     		case bltzall_op:
149     		case bgezall_op:
150     			return 1;
151     		}
152     		break;
153     
154     	case j_op:
155     	case jal_op:
156     	case jalx_op:
157     	case beq_op:
158     	case bne_op:
159     	case blez_op:
160     	case bgtz_op:
161     	case beql_op:
162     	case bnel_op:
163     	case blezl_op:
164     	case bgtzl_op:
165     		return 1;
166     
167     	case cop0_op:
168     	case cop1_op:
169     	case cop2_op:
170     	case cop1x_op:
171     		if (MIPSInst_RS(*i) == bc_op)
172     			return 1;
173     		break;
174     	}
175     
176     	return 0;
177     }
178     
179     #define REG_TO_VA (vaddr_t)
180     #define VA_TO_REG (unsigned long)
181     
182     static unsigned long
183     mips_get_word(struct pt_regs *xcp, void *va, int *perr)
184     {
185     	unsigned long temp;
186     
187     	if (!user_mode(xcp)) {
188     		*perr = 0;
189     		return (*(unsigned long *) va);
190     	} else {
191     		/* Use kernel get_user() macro */
192     		*perr = (int) get_user(temp, (unsigned long *) va);
193     		return temp;
194     	}
195     }
196     
197     static unsigned long long
198     mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
199     {
200     	unsigned long long temp;
201     
202     	if (!user_mode(xcp)) {
203     		*perr = 0;
204     		return (*(unsigned long long *) va);
205     	} else {
206     		/* Use kernel get_user() macro */
207     		*perr = (int) get_user(temp, (unsigned long long *) va);
208     		return temp;
209     	}
210     }
211     
212     static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
213     {
214     	if (!user_mode(xcp)) {
215     		*(unsigned long *) va = val;
216     		return 0;
217     	} else {
218     		/* Use kernel get_user() macro */
219     		return (int) put_user(val, (unsigned long *) va);
220     	}
221     }
222     
223     static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
224     {
225     	if (!user_mode(xcp)) {
226     		*(unsigned long long *) va = val;
227     		return 0;
228     	} else {
229     		/* Use kernel get_user() macro */
230     		return (int) put_user(val, (unsigned long long *) va);
231     	}
232     }
233     
234     
235     /*
236      * In the Linux kernel, we support selection of FPR format on the
237      * basis of the Status.FR bit.  This does imply that, if a full 32
238      * FPRs are desired, there needs to be a flip-flop that can be written
239      * to one at that bit position.  In any case, normal MIPS ABI uses
240      * only the even FPRs (Status.FR = 0).
241      */
242     
243     #define CP0_STATUS_FR_SUPPORT
244     
245     /*
246      * Emulate the single floating point instruction pointed at by EPC.
247      * Two instructions if the instruction is in a branch delay slot.
248      */
249     
250     static int
251     cop1Emulate(int xcptno, struct pt_regs *xcp,
252     	    struct mips_fpu_soft_struct *ctx)
253     {
254     	mips_instruction ir;
255     	vaddr_t emulpc;
256     	vaddr_t contpc;
257     	unsigned int cond;
258     	int err = 0;
259     
260     
261     	ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
262     	if (err) {
263     		fpuemuprivate.stats.errors++;
264     		return SIGBUS;
265     	}
266     
267     	/* XXX NEC Vr54xx bug workaround */
268     	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
269     		xcp->cp0_cause &= ~CAUSEF_BD;
270     
271     	if (xcp->cp0_cause & CAUSEF_BD) {
272     		/*
273     		 * The instruction to be emulated is in a branch delay slot
274     		 * which means that we have to  emulate the branch instruction
275     		 * BEFORE we do the cop1 instruction. 
276     		 *
277     		 * This branch could be a COP1 branch, but in that case we
278     		 * would have had a trap for that instruction, and would not
279     		 * come through this route.
280     		 *
281     		 * Linux MIPS branch emulator operates on context, updating the
282     		 * cp0_epc.
283     		 */
284     		emulpc = REG_TO_VA(xcp->cp0_epc + 4);	/* Snapshot emulation target */
285     
286     		if (__compute_return_epc(xcp)) {
287     #ifdef CP1DBG
288     			printk("failed to emulate branch at %p\n",
289     				    REG_TO_VA(xcp->cp0_epc));
290     #endif
291     			return SIGILL;;
292     		}
293     		ir = mips_get_word(xcp, emulpc, &err);
294     		if (err) {
295     			fpuemuprivate.stats.errors++;
296     			return SIGBUS;
297     		}
298     		contpc = REG_TO_VA xcp->cp0_epc;
299     	} else {
300     		emulpc = REG_TO_VA xcp->cp0_epc;
301     		contpc = REG_TO_VA xcp->cp0_epc + 4;
302     	}
303     
304           emul:
305     	fpuemuprivate.stats.emulated++;
306     	switch (MIPSInst_OPCODE(ir)) {
307     #ifdef CP0_STATUS_FR_SUPPORT
308     		/* R4000+ 64-bit fpu registers */
309     #ifndef SINGLE_ONLY_FPU
310     	case ldc1_op:
311     		{
312     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
313     			    + MIPSInst_SIMM(ir);
314     			int ft = MIPSInst_RT(ir);
315     			if (!(xcp->cp0_status & ST0_FR))
316     				ft &= ~1;
317     			ctx->regs[ft] = mips_get_dword(xcp, va, &err);
318     			fpuemuprivate.stats.loads++;
319     			if (err) {
320     				fpuemuprivate.stats.errors++;
321     				return SIGBUS;
322     			}
323     		}
324     		break;
325     
326     	case sdc1_op:
327     		{
328     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
329     			    + MIPSInst_SIMM(ir);
330     			int ft = MIPSInst_RT(ir);
331     			if (!(xcp->cp0_status & ST0_FR))
332     				ft &= ~1;
333     			fpuemuprivate.stats.stores++;
334     			if (mips_put_dword(xcp, va, ctx->regs[ft])) {
335     				fpuemuprivate.stats.errors++;
336     				return SIGBUS;
337     			}
338     		}
339     		break;
340     #endif
341     
342     	case lwc1_op:
343     		{
344     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
345     			    + MIPSInst_SIMM(ir);
346     			fpureg_t val;
347     			int ft = MIPSInst_RT(ir);
348     			fpuemuprivate.stats.loads++;
349     			val = mips_get_word(xcp, va, &err);
350     			if (err) {
351     				fpuemuprivate.stats.errors++;
352     				return SIGBUS;
353     			}
354     			if (xcp->cp0_status & ST0_FR) {
355     				/* load whole register */
356     				ctx->regs[ft] = val;
357     			} else if (ft & 1) {
358     				/* load to m.s. 32 bits */
359     #ifdef SINGLE_ONLY_FPU
360     				/* illegal register in single-float mode */
361     				return SIGILL;
362     #else
363     				ctx->regs[(ft & ~1)] &= 0xffffffff;
364     				ctx->regs[(ft & ~1)] |= val << 32;
365     #endif
366     			} else {
367     				/* load to l.s. 32 bits */
368     				ctx->regs[ft] &= ~0xffffffffLL;
369     				ctx->regs[ft] |= val;
370     			}
371     		}
372     		break;
373     
374     	case swc1_op:
375     		{
376     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
377     			    + MIPSInst_SIMM(ir);
378     			unsigned int val;
379     			int ft = MIPSInst_RT(ir);
380     			fpuemuprivate.stats.stores++;
381     			if (xcp->cp0_status & ST0_FR) {
382     				/* store whole register */
383     				val = ctx->regs[ft];
384     			} else if (ft & 1) {
385     #ifdef SINGLE_ONLY_FPU
386     				/* illegal register in single-float mode */
387     				return SIGILL;
388     #else
389     				/* store from m.s. 32 bits */
390     				val = ctx->regs[(ft & ~1)] >> 32;
391     #endif
392     			} else {
393     				/* store from l.s. 32 bits */
394     				val = ctx->regs[ft];
395     			}
396     			if (mips_put_word(xcp, va, val)) {
397     				fpuemuprivate.stats.errors++;
398     				return SIGBUS;
399     			}
400     		}
401     		break;
402     #else				/* old 32-bit fpu registers */
403     	case lwc1_op:
404     		{
405     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
406     			    + MIPSInst_SIMM(ir);
407     			ctx->regs[MIPSInst_RT(ir)] =
408     			    mips_get_word(xcp, va, &err);
409     			fpuemuprivate.stats.loads++;
410     			if (err) {
411     				fpuemuprivate.stats.errors++;
412     				return SIGBUS;
413     			}
414     		}
415     		break;
416     
417     	case swc1_op:
418     		{
419     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
420     			    + MIPSInst_SIMM(ir);
421     			fpuemuprivate.stats.stores++;
422     			if (mips_put_word
423     			    (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
424     				fpuemuprivate.stats.errors++;
425     				return SIGBUS;
426     			}
427     		}
428     		break;
429     	case ldc1_op:
430     		{
431     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
432     			    + MIPSInst_SIMM(ir);
433     			unsigned int rt = MIPSInst_RT(ir) & ~1;
434     			int errs = 0;
435     			fpuemuprivate.stats.loads++;
436     #if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
437     			ctx->regs[rt + 1] =
438     			    mips_get_word(xcp, va + 0, &err);
439     			errs += err;
440     			ctx->regs[rt + 0] =
441     			    mips_get_word(xcp, va + 4, &err);
442     			errs += err;
443     #else
444     			ctx->regs[rt + 0] =
445     			    mips_get_word(xcp, va + 0, &err);
446     			errs += err;
447     			ctx->regs[rt + 1] =
448     			    mips_get_word(xcp, va + 4, &err);
449     			errs += err;
450     #endif
451     			if (err)
452     				return SIGBUS;
453     		}
454     		break;
455     
456     	case sdc1_op:
457     		{
458     			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
459     			    + MIPSInst_SIMM(ir);
460     			unsigned int rt = MIPSInst_RT(ir) & ~1;
461     			fpuemuprivate.stats.stores++;
462     #if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
463     			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
464     				return SIGBUS;
465     			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
466     				return SIGBUS;
467     #else
468     			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
469     				return SIGBUS;
470     			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
471     				return SIGBUS;
472     #endif
473     		}
474     		break;
475     #endif
476     
477     	case cop1_op:
478     		switch (MIPSInst_RS(ir)) {
479     
480     #ifdef CP0_STATUS_FR_SUPPORT
481     #if __mips64 && !defined(SINGLE_ONLY_FPU)
482     		case dmfc_op:
483     			/* copregister fs -> gpr[rt] */
484     			if (MIPSInst_RT(ir) != 0) {
485     				int fs = MIPSInst_RD(ir);
486     				if (!(xcp->cp0_status & ST0_FR))
487     					fs &= ~1;
488     				xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
489     			}
490     			break;
491     
492     		case dmtc_op:
493     			/* copregister fs <- rt */
494     			{
495     				fpureg_t value;
496     				int fs = MIPSInst_RD(ir);
497     				if (!(xcp->cp0_status & ST0_FR))
498     					fs &= ~1;
499     				value =
500     				    (MIPSInst_RT(ir) ==
501     				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
502     				ctx->regs[fs] = value;
503     			}
504     			break;
505     #endif
506     
507     		case mfc_op:
508     			/* copregister rd -> gpr[rt] */
509     			if (MIPSInst_RT(ir) != 0) {
510     				/* default value from l.s. 32 bits */
511     				int value = ctx->regs[MIPSInst_RD(ir)];
512     				if (MIPSInst_RD(ir) & 1) {
513     #ifdef SINGLE_ONLY_FPU
514     					/* illegal register in single-float mode */
515     					return SIGILL;
516     #else
517     					if (!(xcp->cp0_status & ST0_FR)) {
518     						/* move from m.s. 32 bits */
519     						value =
520     						    ctx->
521     						    regs[MIPSInst_RD(ir) &
522     							 ~1] >> 32;
523     					}
524     #endif
525     				}
526     				xcp->regs[MIPSInst_RT(ir)] = value;
527     			}
528     			break;
529     
530     		case mtc_op:
531     			/* copregister rd <- rt */
532     			{
533     				fpureg_t value;
534     				if (MIPSInst_RT(ir) == 0)
535     					value = 0;
536     				else
537     					value =
538     					    (unsigned int) xcp->
539     					    regs[MIPSInst_RT(ir)];
540     				if (MIPSInst_RD(ir) & 1) {
541     #ifdef SINGLE_ONLY_FPU
542     					/* illegal register in single-float mode */
543     					return SIGILL;
544     #else
545     					if (!(xcp->cp0_status & ST0_FR)) {
546     						/* move to m.s. 32 bits */
547     						ctx->
548     						    regs[
549     							 (MIPSInst_RD(ir) &
550     							  ~1)] &=
551     						    0xffffffff;
552     						ctx->
553     						    regs[
554     							 (MIPSInst_RD(ir) &
555     							  ~1)] |=
556     						    value << 32;
557     						break;
558     					}
559     #endif
560     				}
561     				/* move to l.s. 32 bits */
562     				ctx->regs[MIPSInst_RD(ir)] &=
563     				    ~0xffffffffLL;
564     				ctx->regs[MIPSInst_RD(ir)] |= value;
565     			}
566     			break;
567     #else
568     
569     		case mfc_op:
570     			/* copregister rd -> gpr[rt] */
571     			if (MIPSInst_RT(ir) != 0) {
572     				unsigned value =
573     				    ctx->regs[MIPSInst_RD(ir)];
574     				xcp->regs[MIPSInst_RT(ir)] = value;
575     			}
576     			break;
577     
578     		case mtc_op:
579     			/* copregister rd <- rt */
580     			{
581     				unsigned value;
582     				value =
583     				    (MIPSInst_RT(ir) ==
584     				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
585     				ctx->regs[MIPSInst_RD(ir)] = value;
586     			}
587     			break;
588     #endif
589     
590     		case cfc_op:
591     			/* cop control register rd -> gpr[rt] */
592     			{
593     				unsigned value;
594     
595     				if (MIPSInst_RD(ir) == FPCREG_CSR) {
596     					value = ctx->sr;
597     #ifdef CSRTRACE
598     					printk
599     					    ("%p gpr[%d]<-csr=%08x\n",
600     					     REG_TO_VA(xcp->cp0_epc),
601     					     MIPSInst_RT(ir), value);
602     #endif
603     				} else if (MIPSInst_RD(ir) == FPCREG_RID)
604     					value = 0;
605     				else
606     					value = 0;
607     				if (MIPSInst_RT(ir))
608     					xcp->regs[MIPSInst_RT(ir)] = value;
609     			}
610     			break;
611     
612     		case ctc_op:
613     			/* copregister rd <- rt */
614     			{
615     				unsigned value;
616     
617     				if (MIPSInst_RT(ir) == 0)
618     					value = 0;
619     				else
620     					value = xcp->regs[MIPSInst_RT(ir)];
621     
622     				/* we only have one writable control reg
623     				 */
624     				if (MIPSInst_RD(ir) == FPCREG_CSR) {
625     #ifdef CSRTRACE
626     					printk
627     					    ("%p gpr[%d]->csr=%08x\n",
628     					     REG_TO_VA(xcp->cp0_epc),
629     					     MIPSInst_RT(ir), value);
630     #endif
631     					ctx->sr = value;
632     					/* copy new rounding mode to ieee library state! */
633     					ieee754_csr.rm =
634     					    ieee_rm[value & 0x3];
635     				}
636     			}
637     			break;
638     
639     		case bc_op:
640     			if (xcp->cp0_cause & CAUSEF_BD) {
641     				return SIGILL;
642     			}
643     			{
644     				int likely = 0;
645     
646     #if __mips >= 4
647     				cond =
648     				    ctx->
649     				    sr & fpucondbit[MIPSInst_RT(ir) >> 2];
650     #else
651     				cond = ctx->sr & FPU_CSR_COND;
652     #endif
653     				switch (MIPSInst_RT(ir) & 3) {
654     				case bcfl_op:
655     					likely = 1;
656     				case bcf_op:
657     					cond = !cond;
658     					break;
659     				case bctl_op:
660     					likely = 1;
661     				case bct_op:
662     					break;
663     				default:
664     					/* thats an illegal instruction */
665     					return SIGILL;
666     				}
667     
668     				xcp->cp0_cause |= CAUSEF_BD;
669     				if (cond) {
670     					/* branch taken: emulate dslot instruction */
671     					xcp->cp0_epc += 4;
672     					contpc =
673     					    REG_TO_VA xcp->cp0_epc +
674     					    (MIPSInst_SIMM(ir) << 2);
675     
676     					ir =
677     					    mips_get_word(xcp,
678     							  REG_TO_VA(xcp->
679     								    cp0_epc),
680     							  &err);
681     					if (err) {
682     						fpuemuprivate.stats.
683     						    errors++;
684     						return SIGBUS;
685     					}
686     
687     					switch (MIPSInst_OPCODE(ir)) {
688     					case lwc1_op:
689     					case swc1_op:
690     #if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
691     					case ldc1_op:
692     					case sdc1_op:
693     #endif
694     					case cop1_op:
695     #if __mips >= 4 && __mips != 32
696     					case cop1x_op:
697     #endif
698     						/* its one of ours */
699     						goto emul;
700     #if __mips >= 4
701     					case spec_op:
702     						if (MIPSInst_FUNC(ir) ==
703     						    movc_op) goto emul;
704     						break;
705     #endif
706     					}
707     
708     					/* single step the non-cp1 instruction in the dslot */
709     					return mips_dsemul(xcp, ir, contpc);
710     				} else {
711     					/* branch not taken */
712     					if (likely)
713     						/* branch likely nullifies dslot if not taken */
714     						xcp->cp0_epc += 4;
715     					/* else continue & execute dslot as normal insn */
716     				}
717     			}
718     			break;
719     
720     		default:
721     			if (!(MIPSInst_RS(ir) & 0x10)) {
722     				return SIGILL;
723     			}
724     			/* a real fpu computation instruction */
725     			{
726     				int sig;
727     				if ((sig = fpu_emu(xcp, ctx, ir)))
728     					return sig;
729     			}
730     		}
731     		break;
732     
733     #if __mips >= 4 && __mips != 32
734     	case cop1x_op:
735     		{
736     			int sig;
737     			if ((sig = fpux_emu(xcp, ctx, ir)))
738     				return sig;
739     		}
740     		break;
741     #endif
742     
743     #if __mips >= 4
744     	case spec_op:
745     		if (MIPSInst_FUNC(ir) != movc_op)
746     			return SIGILL;
747     		cond = fpucondbit[MIPSInst_RT(ir) >> 2];
748     		if (((ctx->sr & cond) != 0) !=
749     		    ((MIPSInst_RT(ir) & 1) != 0)) return 0;
750     		xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
751     		break;
752     #endif
753     
754     	default:
755     		return SIGILL;
756     	}
757     
758     	/* we did it !! */
759     	xcp->cp0_epc = VA_TO_REG(contpc);
760     	xcp->cp0_cause &= ~CAUSEF_BD;
761     	return 0;
762     }
763     
764     /*
765      * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
766      * we have to emulate the instruction in a COP1 branch delay slot.  Do
767      * not change cp0_epc due to the instruction
768      *
769      * According to the spec:
770      * 1) it shouldnt be a branch :-)
771      * 2) it can be a COP instruction :-(
772      * 3) if we are tring to run a protected memory space we must take
773      *    special care on memory access instructions :-(
774      */
775     
776     /*
777      * "Trampoline" return routine to catch exception following
778      *  execution of delay-slot instruction execution.
779      */
780     
781     int do_dsemulret(struct pt_regs *xcp)
782     {
783     #ifdef DSEMUL_TRACE
784     	printk("desemulret\n");
785     #endif
786     	/* Set EPC to return to post-branch instruction */
787     	xcp->cp0_epc = current->thread.dsemul_epc;
788     	/*
789     	 * Clear the state that got us here.
790     	 */
791     	current->thread.dsemul_aerpc = (unsigned long) 0;
792     
793     	return 0;
794     }
795     
796     
797     #define AdELOAD 0x8c000001	/* lw $0,1($0) */
798     
799     static int
800     mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
801     {
802     	mips_instruction *dsemul_insns;
803     	mips_instruction forcetrap;
804     	extern asmlinkage void handle_dsemulret(void);
805     
806     	if (ir == 0) {		/* a nop is easy */
807     		xcp->cp0_epc = VA_TO_REG(cpc);
808     		return 0;
809     	}
810     #ifdef DSEMUL_TRACE
811     	printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc);
812     #endif
813     
814     	/* 
815     	 * The strategy is to push the instruction onto the user stack 
816     	 * and put a trap after it which we can catch and jump to 
817     	 * the required address any alternative apart from full 
818     	 * instruction emulation!!.
819     	 */
820     	dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
821     	dsemul_insns -= 3;	/* Two instructions, plus one for luck ;-) */
822     	/* Verify that the stack pointer is not competely insane */
823     	if (verify_area
824     	    (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2))
825     		return SIGBUS;
826     
827     	if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
828     		fpuemuprivate.stats.errors++;
829     		return (SIGBUS);
830     	}
831     
832     	/* 
833     	 * Algorithmics used a system call instruction, and
834     	 * borrowed that vector.  MIPS/Linux version is a bit
835     	 * more heavyweight in the interests of portability and
836     	 * multiprocessor support.  We flag the thread for special
837     	 * handling in the unaligned access handler and force an
838     	 * address error excpetion.
839     	 */
840     
841     	/* If one is *really* paranoid, one tests for a bad stack pointer */
842     	if ((xcp->regs[29] & 0x3) == 0x3)
843     		forcetrap = AdELOAD - 1;
844     	else
845     		forcetrap = AdELOAD;
846     
847     	if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
848     		fpuemuprivate.stats.errors++;
849     		return (SIGBUS);
850     	}
851     
852     	/* Set thread state to catch and handle the exception */
853     	current->thread.dsemul_epc = (unsigned long) cpc;
854     	current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
855     	xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
856     	flush_cache_sigtramp((unsigned long) dsemul_insns);
857     
858     	return SIGILL;		/* force out of emulation loop */
859     }
860     
861     /* 
862      * Conversion table from MIPS compare ops 48-63
863      * cond = ieee754dp_cmp(x,y,IEEE754_UN);
864      */
865     static const unsigned char cmptab[8] = {
866     	0,					/* cmp_0 (sig) cmp_sf */
867     	IEEE754_CUN,				/* cmp_un (sig) cmp_ngle */
868     	IEEE754_CEQ,				/* cmp_eq (sig) cmp_seq */
869     	IEEE754_CEQ | IEEE754_CUN,		/* cmp_ueq (sig) cmp_ngl  */
870     	IEEE754_CLT,				/* cmp_olt (sig) cmp_lt */
871     	IEEE754_CLT | IEEE754_CUN,		/* cmp_ult (sig) cmp_nge */
872     	IEEE754_CLT | IEEE754_CEQ,		/* cmp_ole (sig) cmp_le */
873     	IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
874     };
875     
876     #define SIFROMREG(si,x)	((si) = ctx->regs[x])
877     #define SITOREG(si,x)	(ctx->regs[x] = (int)(si))
878     
879     #if __mips64 && !defined(SINGLE_ONLY_FPU)
880     #define DIFROMREG(di,x)	((di) = ctx->regs[x])
881     #define DITOREG(di,x)	(ctx->regs[x] = (di))
882     #endif
883     
884     #define SPFROMREG(sp,x)	((sp).bits = ctx->regs[x])
885     #define SPTOREG(sp,x)	(ctx->regs[x] = (sp).bits)
886     
887     #ifdef CP0_STATUS_FR_SUPPORT
888     #define DPFROMREG(dp,x)	((dp).bits = \
889     			ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
890     #define DPTOREG(dp,x)	(ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\
891     			= (dp).bits)
892     #else
893     /* Beware: MIPS COP1 doubles are always little_word endian in registers */
894     #define DPFROMREG(dp,x)	\
895       ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
896     #define DPTOREG(dp,x) \
897       (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
898     #endif
899     
900     #if __mips >= 4 && __mips != 32
901     
902     /*
903      * Additional MIPS4 instructions
904      */
905     
906     static ieee754dp fpemu_dp_recip(ieee754dp d)
907     {
908     	return ieee754dp_div(ieee754dp_one(0), d);
909     }
910     
911     static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
912     {
913     	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
914     }
915     
916     static ieee754sp fpemu_sp_recip(ieee754sp s)
917     {
918     	return ieee754sp_div(ieee754sp_one(0), s);
919     }
920     
921     static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
922     {
923     	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
924     }
925     
926     
927     static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
928     {
929     	return ieee754dp_add(ieee754dp_mul(s, t), r);
930     }
931     
932     static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
933     {
934     	return ieee754dp_sub(ieee754dp_mul(s, t), r);
935     }
936     
937     static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
938     {
939     	return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
940     }
941     
942     static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
943     {
944     	return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
945     }
946     
947     
948     static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
949     {
950     	return ieee754sp_add(ieee754sp_mul(s, t), r);
951     }
952     
953     static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
954     {
955     	return ieee754sp_sub(ieee754sp_mul(s, t), r);
956     }
957     
958     static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
959     {
960     	return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
961     }
962     
963     static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
964     {
965     	return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
966     }
967     
968     static int
969     fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
970     	 mips_instruction ir)
971     {
972     	unsigned rcsr = 0;	/* resulting csr */
973     
974     	fpuemuprivate.stats.cp1xops++;
975     
976     	switch (MIPSInst_FMA_FFMT(ir)) {
977     	case s_fmt:		/* 0 */
978     		{
979     			ieee754sp(*handler) (ieee754sp, ieee754sp,
980     					     ieee754sp);
981     			ieee754sp fd, fr, fs, ft;
982     
983     			switch (MIPSInst_FUNC(ir)) {
984     			case lwxc1_op:
985     				{
986     					void *va =
987     					    REG_TO_VA(xcp->
988     						      regs[MIPSInst_FR(ir)]
989     						      +
990     						      xcp->
991     						      regs[MIPSInst_FT
992     							   (ir)]);
993     					fpureg_t val;
994     					int err = 0;
995     					val = mips_get_word(xcp, va, &err);
996     					if (err) {
997     						fpuemuprivate.stats.
998     						    errors++;
999     						return SIGBUS;
1000     					}
1001     					if (xcp->cp0_status & ST0_FR) {
1002     						/* load whole register */
1003     						ctx->
1004     						    regs[MIPSInst_FD(ir)] =
1005     						    val;
1006     					} else if (MIPSInst_FD(ir) & 1) {
1007     						/* load to m.s. 32 bits */
1008     #if defined(SINGLE_ONLY_FPU)
1009     						/* illegal register in single-float mode */
1010     						return SIGILL;
1011     #else
1012     						ctx->
1013     						    regs[
1014     							 (MIPSInst_FD(ir) &
1015     							  ~1)] &=
1016     						    0xffffffff;
1017     						ctx->
1018     						    regs[
1019     							 (MIPSInst_FD(ir) &
1020     							  ~1)] |=
1021     						    val << 32;
1022     #endif
1023     					} else {
1024     						/* load to l.s. 32 bits */
1025     						ctx->
1026     						    regs[MIPSInst_FD(ir)]
1027     						    &= ~0xffffffffLL;
1028     						ctx->
1029     						    regs[MIPSInst_FD(ir)]
1030     						    |= val;
1031     					}
1032     				}
1033     				break;
1034     
1035     			case swxc1_op:
1036     				{
1037     					void *va =
1038     					    REG_TO_VA(xcp->
1039     						      regs[MIPSInst_FR(ir)]
1040     						      +
1041     						      xcp->
1042     						      regs[MIPSInst_FT
1043     							   (ir)]);
1044     					unsigned int val;
1045     					if (xcp->cp0_status & ST0_FR) {
1046     						/* store whole register */
1047     						val =
1048     						    ctx->
1049     						    regs[MIPSInst_FS(ir)];
1050     					} else if (MIPSInst_FS(ir) & 1) {
1051     #if defined(SINGLE_ONLY_FPU)
1052     						/* illegal register in single-float mode */
1053     						return SIGILL;
1054     #else
1055     						/* store from m.s. 32 bits */
1056     						val =
1057     						    ctx->
1058     						    regs[
1059     							 (MIPSInst_FS(ir) &
1060     							  ~1)] >> 32;
1061     #endif
1062     					} else {
1063     						/* store from l.s. 32 bits */
1064     						val =
1065     						    ctx->
1066     						    regs[MIPSInst_FS(ir)];
1067     					}
1068     					if (mips_put_word(xcp, va, val)) {
1069     						fpuemuprivate.stats.
1070     						    errors++;
1071     						return SIGBUS;
1072     					}
1073     				}
1074     				break;
1075     
1076     			case madd_s_op:
1077     				handler = fpemu_sp_madd;
1078     				goto scoptop;
1079     			case msub_s_op:
1080     				handler = fpemu_sp_msub;
1081     				goto scoptop;
1082     			case nmadd_s_op:
1083     				handler = fpemu_sp_nmadd;
1084     				goto scoptop;
1085     			case nmsub_s_op:
1086     				handler = fpemu_sp_nmsub;
1087     				goto scoptop;
1088     
1089     			      scoptop:
1090     				SPFROMREG(fr, MIPSInst_FR(ir));
1091     				SPFROMREG(fs, MIPSInst_FS(ir));
1092     				SPFROMREG(ft, MIPSInst_FT(ir));
1093     				fd = (*handler) (fr, fs, ft);
1094     				SPTOREG(fd, MIPSInst_FD(ir));
1095     
1096     			      copcsr:
1097     				if (ieee754_cxtest(IEEE754_INEXACT))
1098     					rcsr |=
1099     					    FPU_CSR_INE_X | FPU_CSR_INE_S;
1100     				if (ieee754_cxtest(IEEE754_UNDERFLOW))
1101     					rcsr |=
1102     					    FPU_CSR_UDF_X | FPU_CSR_UDF_S;
1103     				if (ieee754_cxtest(IEEE754_OVERFLOW))
1104     					rcsr |=
1105     					    FPU_CSR_OVF_X | FPU_CSR_OVF_S;
1106     				if (ieee754_cxtest
1107     				    (IEEE754_INVALID_OPERATION)) rcsr |=
1108     					    FPU_CSR_INV_X | FPU_CSR_INV_S;
1109     
1110     				ctx->sr =
1111     				    (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
1112     				if ((ctx->sr >> 5) & ctx->
1113     				    sr & FPU_CSR_ALL_E) {
1114     		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
1115     					return SIGFPE;
1116     				}
1117     
1118     				break;
1119     
1120     			default:
1121     				return SIGILL;
1122     			}
1123     		}
1124     		break;
1125     
1126     #if !defined(SINGLE_ONLY_FPU)
1127     	case d_fmt:		/* 1 */
1128     		{
1129     			ieee754dp(*handler) (ieee754dp, ieee754dp,
1130     					     ieee754dp);
1131     			ieee754dp fd, fr, fs, ft;
1132     
1133     			switch (MIPSInst_FUNC(ir)) {
1134     			case ldxc1_op:
1135     				{
1136     					void *va =
1137     					    REG_TO_VA(xcp->
1138     						      regs[MIPSInst_FR(ir)]
1139     						      +
1140     						      xcp->
1141     						      regs[MIPSInst_FT
1142     							   (ir)]);
1143     					int err = 0;
1144     					ctx->regs[MIPSInst_FD(ir)] =
1145     					    mips_get_dword(xcp, va, &err);
1146     					if (err) {
1147     						fpuemuprivate.stats.
1148     						    errors++;
1149     						return SIGBUS;
1150     					}
1151     				}
1152     				break;
1153     
1154     			case sdxc1_op:
1155     				{
1156     					void *va =
1157     					    REG_TO_VA(xcp->
1158     						      regs[MIPSInst_FR(ir)]
1159     						      +
1160     						      xcp->
1161     						      regs[MIPSInst_FT
1162     							   (ir)]);
1163     					if (mips_put_dword
1164     					    (xcp, va,
1165     					     ctx->regs[MIPSInst_FS(ir)])) {
1166     						fpuemuprivate.stats.
1167     						    errors++;
1168     						return SIGBUS;
1169     					}
1170     				}
1171     				break;
1172     
1173     			case madd_d_op:
1174     				handler = fpemu_dp_madd;
1175     				goto dcoptop;
1176     			case msub_d_op:
1177     				handler = fpemu_dp_msub;
1178     				goto dcoptop;
1179     			case nmadd_d_op:
1180     				handler = fpemu_dp_nmadd;
1181     				goto dcoptop;
1182     			case nmsub_d_op:
1183     				handler = fpemu_dp_nmsub;
1184     				goto dcoptop;
1185     
1186     			      dcoptop:
1187     				DPFROMREG(fr, MIPSInst_FR(ir));
1188     				DPFROMREG(fs, MIPSInst_FS(ir));
1189     				DPFROMREG(ft, MIPSInst_FT(ir));
1190     				fd = (*handler) (fr, fs, ft);
1191     				DPTOREG(fd, MIPSInst_FD(ir));
1192     				goto copcsr;
1193     
1194     			default:
1195     				return SIGILL;
1196     			}
1197     		}
1198     		break;
1199     #endif
1200     
1201     	case 0x7:		/* 7 */
1202     		{
1203     			if (MIPSInst_FUNC(ir) != pfetch_op) {
1204     				return SIGILL;
1205     			}
1206     			/* ignore prefx operation */
1207     		}
1208     		break;
1209     
1210     	default:
1211     		return SIGILL;
1212     	}
1213     
1214     	return 0;
1215     }
1216     #endif
1217     
1218     
1219     
1220     /*
1221      * Emulate a single COP1 arithmetic instruction.
1222      */
1223     static int
1224     fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
1225     	mips_instruction ir)
1226     {
1227     	int rfmt;		/* resulting format */
1228     	unsigned rcsr = 0;	/* resulting csr */
1229     	unsigned cond;
1230     	union {
1231     		ieee754dp d;
1232     		ieee754sp s;
1233     		int w;
1234     #if __mips64
1235     		long long l;
1236     #endif
1237     	} rv;			/* resulting value */
1238     
1239     	fpuemuprivate.stats.cp1ops++;
1240     	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
1241     
1242     	case s_fmt:{		/* 0 */
1243     		ieee754sp(*handler) ();
1244     
1245     		switch (MIPSInst_FUNC(ir)) {
1246     			/* binary ops */
1247     		case fadd_op:
1248     			handler = ieee754sp_add;
1249     			goto scopbop;
1250     		case fsub_op:
1251     			handler = ieee754sp_sub;
1252     			goto scopbop;
1253     		case fmul_op:
1254     			handler = ieee754sp_mul;
1255     			goto scopbop;
1256     		case fdiv_op:
1257     			handler = ieee754sp_div;
1258     			goto scopbop;
1259     
1260     			/* unary  ops */
1261     #if __mips >= 2 || __mips64
1262     		case fsqrt_op:
1263     			handler = ieee754sp_sqrt;
1264     			goto scopuop;
1265     #endif
1266     #if __mips >= 4 && __mips != 32
1267     		case frsqrt_op:
1268     			handler = fpemu_sp_rsqrt;
1269     			goto scopuop;
1270     		case frecip_op:
1271     			handler = fpemu_sp_recip;
1272     			goto scopuop;
1273     #endif
1274     #if __mips >= 4
1275     		case fmovc_op:
1276     			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
1277     			if (((ctx->sr & cond) != 0) !=
1278     			    ((MIPSInst_FT(ir) & 1) != 0))
1279     				return 0;
1280     			SPFROMREG(rv.s, MIPSInst_FS(ir));
1281     			break;
1282     		case fmovz_op:
1283     			if (xcp->regs[MIPSInst_FT(ir)] != 0)
1284     				return 0;
1285     			SPFROMREG(rv.s, MIPSInst_FS(ir));
1286     			break;
1287     		case fmovn_op:
1288     			if (xcp->regs[MIPSInst_FT(ir)] == 0)
1289     				return 0;
1290     			SPFROMREG(rv.s, MIPSInst_FS(ir));
1291     			break;
1292     #endif
1293     		case fabs_op:
1294     			handler = ieee754sp_abs;
1295     			goto scopuop;
1296     		case fneg_op:
1297     			handler = ieee754sp_neg;
1298     			goto scopuop;
1299     		case fmov_op:
1300     			/* an easy one */
1301     			SPFROMREG(rv.s, MIPSInst_FS(ir));
1302     			break;
1303     			/* binary op on handler */
1304     scopbop:
1305     			{
1306     				ieee754sp fs, ft;
1307     
1308     				SPFROMREG(fs, MIPSInst_FS(ir));
1309     				SPFROMREG(ft, MIPSInst_FT(ir));
1310     
1311     				rv.s = (*handler) (fs, ft);
1312     				goto copcsr;
1313     			}
1314     scopuop:
1315     			{
1316     				ieee754sp fs;
1317     
1318     				SPFROMREG(fs, MIPSInst_FS(ir));
1319     				rv.s = (*handler) (fs);
1320     				goto copcsr;
1321     			}
1322     copcsr:
1323     			if (ieee754_cxtest(IEEE754_INEXACT))
1324     				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
1325     			if (ieee754_cxtest(IEEE754_UNDERFLOW))
1326     				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
1327     			if (ieee754_cxtest(IEEE754_OVERFLOW))
1328     				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
1329     			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
1330     				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
1331     			if (ieee754_cxtest
1332     				(IEEE754_INVALID_OPERATION)) rcsr |=
1333     					    FPU_CSR_INV_X | FPU_CSR_INV_S;
1334     				break;
1335     
1336     				/* unary conv ops */
1337     		case fcvts_op:
1338     			return SIGILL;	/* not defined */
1339     		case fcvtd_op:
1340     #if defined(SINGLE_ONLY_FPU)
1341     			return SIGILL;	/* not defined */
1342     #else
1343     			{
1344     				ieee754sp fs;
1345     
1346     				SPFROMREG(fs, MIPSInst_FS(ir));
1347     				rv.d = ieee754dp_fsp(fs);
1348     				rfmt = d_fmt;
1349     				goto copcsr;
1350     			}
1351     #endif
1352     		case fcvtw_op:
1353     			{
1354     				ieee754sp fs;
1355     
1356     				SPFROMREG(fs, MIPSInst_FS(ir));
1357     				rv.w = ieee754sp_tint(fs);
1358     				rfmt = w_fmt;
1359     				goto copcsr;
1360     			}
1361     
1362     #if __mips >= 2 || __mips64
1363     		case fround_op:
1364     		case ftrunc_op:
1365     		case fceil_op:
1366     		case ffloor_op:
1367     			{
1368     				unsigned int oldrm = ieee754_csr.rm;
1369     				ieee754sp fs;
1370     
1371     				SPFROMREG(fs, MIPSInst_FS(ir));
1372     				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
1373     				rv.w = ieee754sp_tint(fs);
1374     				ieee754_csr.rm = oldrm;
1375     				rfmt = w_fmt;
1376     				goto copcsr;
1377     			}
1378     #endif			/* __mips >= 2 */
1379     
1380     #if __mips64 && !defined(SINGLE_ONLY_FPU)
1381     		case fcvtl_op:
1382     			{
1383     				ieee754sp fs;
1384     
1385     				SPFROMREG(fs, MIPSInst_FS(ir));
1386     				rv.l = ieee754sp_tlong(fs);
1387     				rfmt = l_fmt;
1388     				goto copcsr;
1389     			}
1390     
1391     		case froundl_op:
1392     		case ftruncl_op:
1393     		case fceill_op:
1394     		case ffloorl_op:
1395     			{
1396     				unsigned int oldrm = ieee754_csr.rm;
1397     				ieee754sp fs;
1398     
1399     				SPFROMREG(fs, MIPSInst_FS(ir));
1400     				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
1401     				rv.l = ieee754sp_tlong(fs);
1402     				ieee754_csr.rm = oldrm;
1403     				rfmt = l_fmt;
1404     				goto copcsr;
1405     			}
1406     #endif /* __mips64 && !fpu(single) */
1407     
1408     		default:
1409     			if (MIPSInst_FUNC(ir) >= fcmp_op) {
1410     				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
1411     				ieee754sp fs, ft;
1412     
1413     				SPFROMREG(fs, MIPSInst_FS(ir));
1414     				SPFROMREG(ft, MIPSInst_FT(ir));
1415     				rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
1416     				rfmt = -1;
1417     				if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
1418     					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
1419     				} else {
1420     					return SIGILL;
1421     				}
1422     				break;
1423     			}
1424     			break;
1425     		}
1426     
1427     #if !defined(SINGLE_ONLY_FPU)
1428     	case d_fmt: {
1429     		ieee754dp(*handler) ();
1430     
1431     		switch (MIPSInst_FUNC(ir)) {
1432     			/* binary ops */
1433     		case fadd_op:
1434     			handler = ieee754dp_add;
1435     			goto dcopbop;
1436     		case fsub_op:
1437     			handler = ieee754dp_sub;
1438     			goto dcopbop;
1439     		case fmul_op:
1440     			handler = ieee754dp_mul;
1441     			goto dcopbop;
1442     		case fdiv_op:
1443     			handler = ieee754dp_div;
1444     			goto dcopbop;
1445     
1446     			/* unary  ops */
1447     #if __mips >= 2 || __mips64
1448     		case fsqrt_op:
1449     			handler = ieee754dp_sqrt;
1450     			goto dcopuop;
1451     #endif
1452     #if __mips >= 4 && __mips != 32
1453     		case frsqrt_op:
1454     			handler = fpemu_dp_rsqrt;
1455     			goto dcopuop;
1456     		case frecip_op:
1457     			handler = fpemu_dp_recip;
1458     			goto dcopuop;
1459     #endif
1460     #if __mips >= 4
1461     		case fmovc_op:
1462     			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
1463     			if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
1464     				return 0;
1465     			DPFROMREG(rv.d, MIPSInst_FS(ir));
1466     			break;
1467     		case fmovz_op:
1468     			if (xcp->regs[MIPSInst_FT(ir)] != 0)
1469     				return 0;
1470     			DPFROMREG(rv.d, MIPSInst_FS(ir));
1471     			break;
1472     		case fmovn_op:
1473     			if (xcp->regs[MIPSInst_FT(ir)] == 0)
1474     				return 0;
1475     			DPFROMREG(rv.d, MIPSInst_FS(ir));
1476     			break;
1477     #endif
1478     		case fabs_op:
1479     			handler = ieee754dp_abs;
1480     			goto dcopuop;
1481     		case fneg_op:
1482     			handler = ieee754dp_neg;
1483     			goto dcopuop;
1484     		case fmov_op:
1485     			/* an easy one */
1486     			DPFROMREG(rv.d, MIPSInst_FS(ir));
1487     			break;
1488     
1489     			/* binary op on handler */
1490     dcopbop:
1491     			{
1492     				ieee754dp fs, ft;
1493     
1494     				DPFROMREG(fs, MIPSInst_FS(ir));
1495     				DPFROMREG(ft, MIPSInst_FT(ir));
1496     
1497     				rv.d = (*handler) (fs, ft);
1498     				goto copcsr;
1499     			}
1500     dcopuop:
1501     			{
1502     				ieee754dp fs;
1503     
1504     				DPFROMREG(fs, MIPSInst_FS(ir));
1505     				rv.d = (*handler) (fs);
1506     				goto copcsr;
1507     			}
1508     
1509     		/* unary conv ops */
1510     		case fcvts_op:
1511     			{
1512     				ieee754dp fs;
1513     
1514     				DPFROMREG(fs, MIPSInst_FS(ir));
1515     				rv.s = ieee754sp_fdp(fs);
1516     				rfmt = s_fmt;
1517     				goto copcsr;
1518     			}
1519     		case fcvtd_op:
1520     			return SIGILL;	/* not defined */
1521     		case fcvtw_op:
1522     			{
1523     				ieee754dp fs;
1524     
1525     				DPFROMREG(fs, MIPSInst_FS(ir));
1526     				rv.w = ieee754dp_tint(fs);	/* wrong */
1527     				rfmt = w_fmt;
1528     				goto copcsr;
1529     			}
1530     
1531     #if __mips >= 2 || __mips64
1532     		case fround_op:
1533     		case ftrunc_op:
1534     		case fceil_op:
1535     		case ffloor_op:
1536     			{
1537     				unsigned int oldrm = ieee754_csr.rm;
1538     				ieee754dp fs;
1539     
1540     				DPFROMREG(fs, MIPSInst_FS(ir));
1541     				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
1542     				rv.w = ieee754dp_tint(fs);
1543     				ieee754_csr.rm = oldrm;
1544     				rfmt = w_fmt;
1545     				goto copcsr;
1546     			}
1547     #endif
1548     
1549     #if __mips64 && !defined(SINGLE_ONLY_FPU)
1550     		case fcvtl_op:
1551     			{
1552     				ieee754dp fs;
1553     
1554     				DPFROMREG(fs, MIPSInst_FS(ir));
1555     				rv.l = ieee754dp_tlong(fs);
1556     				rfmt = l_fmt;
1557     				goto copcsr;
1558     			}
1559     
1560     		case froundl_op:
1561     		case ftruncl_op:
1562     		case fceill_op:
1563     		case ffloorl_op:
1564     			{
1565     				unsigned int oldrm = ieee754_csr.rm;
1566     				ieee754dp fs;
1567     
1568     				DPFROMREG(fs, MIPSInst_FS(ir));
1569     				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
1570     				rv.l = ieee754dp_tlong(fs);
1571     				ieee754_csr.rm = oldrm;
1572     				rfmt = l_fmt;
1573     				goto copcsr;
1574     			}
1575     #endif /* __mips >= 3 && !fpu(single) */
1576     
1577     		default:
1578     			if (MIPSInst_FUNC(ir) >= fcmp_op) {
1579     				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
1580     				ieee754dp fs, ft;
1581     
1582     				DPFROMREG(fs, MIPSInst_FS(ir));
1583     				DPFROMREG(ft, MIPSInst_FT(ir));
1584     				rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
1585     				rfmt = -1;
1586     				if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
1587     					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
1588     			} else {
1589     				return SIGILL;
1590     			}
1591     			break;
1592     		}
1593     		break;
1594     	}
1595     #endif				/* !defined(SINGLE_ONLY_FPU) */
1596     
1597     	case w_fmt: {
1598     		switch (MIPSInst_FUNC(ir)) {
1599     		case fcvts_op:
1600     			/* convert word to single precision real */
1601     			rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
1602     			rfmt = s_fmt;
1603     			goto copcsr;
1604     #if !defined(SINGLE_ONLY_FPU)
1605     		case fcvtd_op:
1606     			/* convert word to double precision real */
1607     			rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
1608     			rfmt = d_fmt;
1609     			goto copcsr;
1610     #endif
1611     		default:
1612     			return SIGILL;
1613     		}
1614     		break;
1615     	}
1616     
1617     #if __mips64 && !defined(SINGLE_ONLY_FPU)
1618     	case l_fmt: {
1619     		switch (MIPSInst_FUNC(ir)) {
1620     		case fcvts_op:
1621     			/* convert long to single precision real */
1622     			rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
1623     			rfmt = s_fmt;
1624     			goto copcsr;
1625     		case fcvtd_op:
1626     			/* convert long to double precision real */
1627     			rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
1628     			rfmt = d_fmt;
1629     			goto copcsr;
1630     		default:
1631     			return SIGILL;
1632     		}
1633     		break;
1634     	}
1635     #endif
1636     
1637     	default:
1638     		return SIGILL;
1639     	}
1640     
1641     	/*
1642     	 * Update the fpu CSR register for this operation.
1643     	 * If an exception is required, generate a tidy SIGFPE exception,
1644     	 * without updating the result register.
1645     	 * Note: cause exception bits do not accumulate, they are rewritten
1646     	 * for each op; only the flag/sticky bits accumulate.
1647     	 */
1648     	ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
1649     	if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
1650     		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
1651     		return SIGFPE;
1652     	}
1653     
1654     	/* 
1655     	 * Now we can safely write the result back to the register file.
1656     	 */
1657     	switch (rfmt) {
1658     	case -1: {
1659     #if __mips >= 4
1660     		cond = fpucondbit[MIPSInst_FD(ir) >> 2];
1661     #else
1662     		cond = FPU_CSR_COND;
1663     #endif
1664     		if (rv.w)
1665     			ctx->sr |= cond;
1666     		else
1667     			ctx->sr &= ~cond;
1668     		break;
1669     	}
1670     #if !defined(SINGLE_ONLY_FPU)
1671     	case d_fmt:
1672     		DPTOREG(rv.d, MIPSInst_FD(ir));
1673     		break;
1674     #endif
1675     	case s_fmt:
1676     		SPTOREG(rv.s, MIPSInst_FD(ir));
1677     		break;
1678     	case w_fmt:
1679     		SITOREG(rv.w, MIPSInst_FD(ir));
1680     		break;
1681     #if __mips64 && !defined(SINGLE_ONLY_FPU)
1682     	case l_fmt:
1683     		DITOREG(rv.l, MIPSInst_FD(ir));
1684     		break;
1685     #endif
1686     	default:
1687     		return SIGILL;
1688     	}
1689     
1690     	return 0;
1691     }
1692     
1693     
1694     /*
1695      * Emulate the floating point instruction at EPC, and continue
1696      * to run until we hit a non-fp instruction, or a backward
1697      * branch.  This cuts down dramatically on the per instruction 
1698      * exception overhead.
1699      */
1700     int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp)
1701     {
1702     	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
1703     	unsigned long oldepc, prevepc;
1704     	unsigned int insn;
1705     	int sig = 0;
1706     	int err = 0;
1707     
1708     	oldepc = xcp->cp0_epc;
1709     	do {
1710     		if (current->need_resched)
1711     			schedule();
1712     
1713     		prevepc = xcp->cp0_epc;
1714     		insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
1715     		if (err) {
1716     			fpuemuprivate.stats.errors++;
1717     			return SIGBUS;
1718     		}
1719     		if (insn != 0)
1720     			sig = cop1Emulate(xcptno, xcp, ctx);
1721     		else
1722     			xcp->cp0_epc += 4;	/* skip nops */
1723     
1724     		if (mips_cpu.options & MIPS_CPU_FPU)
1725     			break;
1726     	} while (xcp->cp0_epc > prevepc && sig == 0);
1727     
1728     	/* SIGILL indicates a non-fpu instruction */
1729     	if (sig == SIGILL && xcp->cp0_epc != oldepc)
1730     		/* but if epc has advanced, then ignore it */
1731     		sig = 0;
1732     
1733     	return sig;
1734     }
1735     
1736     
1737     #ifdef NOTDEF
1738     /*
1739      * Patch up the hardware fpu state when an f.p. exception occurs.  
1740      */
1741     static int cop1Patcher(int xcptno, struct pt_regs *xcp)
1742     {
1743     	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
1744     	unsigned sr;
1745     	int sig;
1746     
1747     	/* reenable Cp1, else fpe_save() will get nested exception */
1748     	sr = mips_bissr(ST0_CU1);
1749     
1750     	/* get fpu registers and status, then clear pending exceptions */
1751     	fpe_save(ctx);
1752     	fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
1753     
1754     	/* get current rounding mode for IEEE library, and emulate insn */
1755     	ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
1756     	sig = cop1Emulate(xcptno, xcp, ctx);
1757     
1758     	/* don't return with f.p. exceptions pending */
1759     	ctx->sr &= ~FPU_CSR_ALL_X;
1760     	fpe_restore(ctx);
1761     
1762     	mips_setsr(sr);
1763     	return sig;
1764     }
1765     
1766     void _cop1_init(int emulate)
1767     {
1768     	extern int _nofpu;
1769     
1770     	if (emulate) {
1771     		/* 
1772     		 * Install cop1 emulator to handle "coprocessor unusable" exception
1773     		 */
1774     		xcption(XCPTCPU, cop1Handler);
1775     		fpuemuactive = 1;	/* tell dbg.c that we are in charge */
1776     		_nofpu = 0;	/* tell setjmp() it "has" an fpu */
1777     	} else {
1778     		/* 
1779     		 * Install cop1 emulator for floating point exceptions only,
1780     		 * i.e. denormalised results, underflow, overflow etc, which
1781     		 * must be emulated in s/w.
1782     		 */
1783     #ifdef 1
1784     		/* r4000 or above use dedicate exception */
1785     		xcption(XCPTFPE, cop1Patcher);
1786     #else
1787     		/* r3000 et al use interrupt */
1788     		extern int _sbd_getfpuintr(void);
1789     		int intno = _sbd_getfpuintr();
1790     		intrupt(intno, cop1Patcher, 0);
1791     		mips_bissr(SR_IM0 << intno);
1792     #endif
1793     
1794     #if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
1795     		/* For R4640/R4650 compiled *without* the -msingle-float flag,
1796     		   then we share responsibility: the h/w handles the single
1797     		   precision operations, and the trap emulator handles the
1798     		   double precision. We set fpuemuactive so that dbg.c first
1799     		   fetches the s/w state before saving the h/w state. */
1800     		fpuemuactive = 1;
1801     		{
1802     			int i;
1803     			/* initialise the unused d.p high order words to be NaN */
1804     			for (i = 0; i < 32; i++)
1805     				current->thread.fpu.soft.regs[i] =
1806     				    0x7ff80bad00000000LL;
1807     		}
1808     #endif				/* (r4640 || r4650) && !fpu(single) */
1809     	}
1810     }
1811     #endif
1812     
1813