xref: /openbmc/linux/arch/mips/math-emu/cp1emu.c (revision 64c70b1c)
1 /*
2  * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
3  *
4  * MIPS floating point support
5  * Copyright (C) 1994-2000 Algorithmics Ltd.
6  * http://www.algor.co.uk
7  *
8  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
9  * Copyright (C) 2000  MIPS Technologies, Inc.
10  *
11  *  This program is free software; you can distribute it and/or modify it
12  *  under the terms of the GNU General Public License (Version 2) as
13  *  published by the Free Software Foundation.
14  *
15  *  This program is distributed in the hope it will be useful, but WITHOUT
16  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  *  for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with this program; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
23  *
24  * A complete emulator for MIPS coprocessor 1 instructions.  This is
25  * required for #float(switch) or #float(trap), where it catches all
26  * COP1 instructions via the "CoProcessor Unusable" exception.
27  *
28  * More surprisingly it is also required for #float(ieee), to help out
29  * the hardware fpu at the boundaries of the IEEE-754 representation
30  * (denormalised values, infinities, underflow, etc).  It is made
31  * quite nasty because emulation of some non-COP1 instructions is
32  * required, e.g. in branch delay slots.
33  *
34  * Note if you know that you won't have an fpu, then you'll get much
35  * better performance by compiling with -msoft-float!
36  */
37 #include <linux/sched.h>
38 #include <linux/debugfs.h>
39 
40 #include <asm/inst.h>
41 #include <asm/bootinfo.h>
42 #include <asm/processor.h>
43 #include <asm/ptrace.h>
44 #include <asm/signal.h>
45 #include <asm/mipsregs.h>
46 #include <asm/fpu_emulator.h>
47 #include <asm/uaccess.h>
48 #include <asm/branch.h>
49 
50 #include "ieee754.h"
51 #include "dsemul.h"
52 
53 /* Strap kernel emulator for full MIPS IV emulation */
54 
55 #ifdef __mips
56 #undef __mips
57 #endif
58 #define __mips 4
59 
60 /* Function which emulates a floating point instruction. */
61 
62 static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
63 	mips_instruction);
64 
65 #if __mips >= 4 && __mips != 32
66 static int fpux_emu(struct pt_regs *,
67 	struct mips_fpu_struct *, mips_instruction);
68 #endif
69 
70 /* Further private data for which no space exists in mips_fpu_struct */
71 
72 struct mips_fpu_emulator_stats fpuemustats;
73 
74 /* Control registers */
75 
76 #define FPCREG_RID	0	/* $0  = revision id */
77 #define FPCREG_CSR	31	/* $31 = csr */
78 
79 /* Convert Mips rounding mode (0..3) to IEEE library modes. */
80 static const unsigned char ieee_rm[4] = {
81 	[FPU_CSR_RN] = IEEE754_RN,
82 	[FPU_CSR_RZ] = IEEE754_RZ,
83 	[FPU_CSR_RU] = IEEE754_RU,
84 	[FPU_CSR_RD] = IEEE754_RD,
85 };
86 /* Convert IEEE library modes to Mips rounding mode (0..3). */
87 static const unsigned char mips_rm[4] = {
88 	[IEEE754_RN] = FPU_CSR_RN,
89 	[IEEE754_RZ] = FPU_CSR_RZ,
90 	[IEEE754_RD] = FPU_CSR_RD,
91 	[IEEE754_RU] = FPU_CSR_RU,
92 };
93 
94 #if __mips >= 4
95 /* convert condition code register number to csr bit */
96 static const unsigned int fpucondbit[8] = {
97 	FPU_CSR_COND0,
98 	FPU_CSR_COND1,
99 	FPU_CSR_COND2,
100 	FPU_CSR_COND3,
101 	FPU_CSR_COND4,
102 	FPU_CSR_COND5,
103 	FPU_CSR_COND6,
104 	FPU_CSR_COND7
105 };
106 #endif
107 
108 
109 /*
110  * Redundant with logic already in kernel/branch.c,
111  * embedded in compute_return_epc.  At some point,
112  * a single subroutine should be used across both
113  * modules.
114  */
115 static int isBranchInstr(mips_instruction * i)
116 {
117 	switch (MIPSInst_OPCODE(*i)) {
118 	case spec_op:
119 		switch (MIPSInst_FUNC(*i)) {
120 		case jalr_op:
121 		case jr_op:
122 			return 1;
123 		}
124 		break;
125 
126 	case bcond_op:
127 		switch (MIPSInst_RT(*i)) {
128 		case bltz_op:
129 		case bgez_op:
130 		case bltzl_op:
131 		case bgezl_op:
132 		case bltzal_op:
133 		case bgezal_op:
134 		case bltzall_op:
135 		case bgezall_op:
136 			return 1;
137 		}
138 		break;
139 
140 	case j_op:
141 	case jal_op:
142 	case jalx_op:
143 	case beq_op:
144 	case bne_op:
145 	case blez_op:
146 	case bgtz_op:
147 	case beql_op:
148 	case bnel_op:
149 	case blezl_op:
150 	case bgtzl_op:
151 		return 1;
152 
153 	case cop0_op:
154 	case cop1_op:
155 	case cop2_op:
156 	case cop1x_op:
157 		if (MIPSInst_RS(*i) == bc_op)
158 			return 1;
159 		break;
160 	}
161 
162 	return 0;
163 }
164 
165 /*
166  * In the Linux kernel, we support selection of FPR format on the
167  * basis of the Status.FR bit.  This does imply that, if a full 32
168  * FPRs are desired, there needs to be a flip-flop that can be written
169  * to one at that bit position.  In any case, O32 MIPS ABI uses
170  * only the even FPRs (Status.FR = 0).
171  */
172 
173 #define CP0_STATUS_FR_SUPPORT
174 
175 #ifdef CP0_STATUS_FR_SUPPORT
176 #define FR_BIT ST0_FR
177 #else
178 #define FR_BIT 0
179 #endif
180 
181 #define SIFROMREG(si,x)	((si) = \
182 			(xcp->cp0_status & FR_BIT) || !(x & 1) ? \
183 			(int)ctx->fpr[x] : \
184 			(int)(ctx->fpr[x & ~1] >> 32 ))
185 #define SITOREG(si,x)	(ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \
186 			(xcp->cp0_status & FR_BIT) || !(x & 1) ? \
187 			ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
188 			ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
189 
190 #define DIFROMREG(di,x)	((di) = \
191 			ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)])
192 #define DITOREG(di,x)	(ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \
193 			= (di))
194 
195 #define SPFROMREG(sp,x)	SIFROMREG((sp).bits,x)
196 #define SPTOREG(sp,x)	SITOREG((sp).bits,x)
197 #define DPFROMREG(dp,x)	DIFROMREG((dp).bits,x)
198 #define DPTOREG(dp,x)	DITOREG((dp).bits,x)
199 
200 /*
201  * Emulate the single floating point instruction pointed at by EPC.
202  * Two instructions if the instruction is in a branch delay slot.
203  */
204 
205 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
206 {
207 	mips_instruction ir;
208 	void * emulpc, *contpc;
209 	unsigned int cond;
210 
211 	if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
212 		fpuemustats.errors++;
213 		return SIGBUS;
214 	}
215 
216 	/* XXX NEC Vr54xx bug workaround */
217 	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
218 		xcp->cp0_cause &= ~CAUSEF_BD;
219 
220 	if (xcp->cp0_cause & CAUSEF_BD) {
221 		/*
222 		 * The instruction to be emulated is in a branch delay slot
223 		 * which means that we have to  emulate the branch instruction
224 		 * BEFORE we do the cop1 instruction.
225 		 *
226 		 * This branch could be a COP1 branch, but in that case we
227 		 * would have had a trap for that instruction, and would not
228 		 * come through this route.
229 		 *
230 		 * Linux MIPS branch emulator operates on context, updating the
231 		 * cp0_epc.
232 		 */
233 		emulpc = (void *) (xcp->cp0_epc + 4);	/* Snapshot emulation target */
234 
235 		if (__compute_return_epc(xcp)) {
236 #ifdef CP1DBG
237 			printk("failed to emulate branch at %p\n",
238 				(void *) (xcp->cp0_epc));
239 #endif
240 			return SIGILL;
241 		}
242 		if (get_user(ir, (mips_instruction __user *) emulpc)) {
243 			fpuemustats.errors++;
244 			return SIGBUS;
245 		}
246 		/* __compute_return_epc() will have updated cp0_epc */
247 		contpc = (void *)  xcp->cp0_epc;
248 		/* In order not to confuse ptrace() et al, tweak context */
249 		xcp->cp0_epc = (unsigned long) emulpc - 4;
250 	} else {
251 		emulpc = (void *)  xcp->cp0_epc;
252 		contpc = (void *) (xcp->cp0_epc + 4);
253 	}
254 
255       emul:
256 	fpuemustats.emulated++;
257 	switch (MIPSInst_OPCODE(ir)) {
258 	case ldc1_op:{
259 		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
260 			MIPSInst_SIMM(ir));
261 		u64 val;
262 
263 		fpuemustats.loads++;
264 		if (get_user(val, va)) {
265 			fpuemustats.errors++;
266 			return SIGBUS;
267 		}
268 		DITOREG(val, MIPSInst_RT(ir));
269 		break;
270 	}
271 
272 	case sdc1_op:{
273 		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
274 			MIPSInst_SIMM(ir));
275 		u64 val;
276 
277 		fpuemustats.stores++;
278 		DIFROMREG(val, MIPSInst_RT(ir));
279 		if (put_user(val, va)) {
280 			fpuemustats.errors++;
281 			return SIGBUS;
282 		}
283 		break;
284 	}
285 
286 	case lwc1_op:{
287 		u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
288 			MIPSInst_SIMM(ir));
289 		u32 val;
290 
291 		fpuemustats.loads++;
292 		if (get_user(val, va)) {
293 			fpuemustats.errors++;
294 			return SIGBUS;
295 		}
296 		SITOREG(val, MIPSInst_RT(ir));
297 		break;
298 	}
299 
300 	case swc1_op:{
301 		u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
302 			MIPSInst_SIMM(ir));
303 		u32 val;
304 
305 		fpuemustats.stores++;
306 		SIFROMREG(val, MIPSInst_RT(ir));
307 		if (put_user(val, va)) {
308 			fpuemustats.errors++;
309 			return SIGBUS;
310 		}
311 		break;
312 	}
313 
314 	case cop1_op:
315 		switch (MIPSInst_RS(ir)) {
316 
317 #if defined(__mips64)
318 		case dmfc_op:
319 			/* copregister fs -> gpr[rt] */
320 			if (MIPSInst_RT(ir) != 0) {
321 				DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
322 					MIPSInst_RD(ir));
323 			}
324 			break;
325 
326 		case dmtc_op:
327 			/* copregister fs <- rt */
328 			DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
329 			break;
330 #endif
331 
332 		case mfc_op:
333 			/* copregister rd -> gpr[rt] */
334 			if (MIPSInst_RT(ir) != 0) {
335 				SIFROMREG(xcp->regs[MIPSInst_RT(ir)],
336 					MIPSInst_RD(ir));
337 			}
338 			break;
339 
340 		case mtc_op:
341 			/* copregister rd <- rt */
342 			SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
343 			break;
344 
345 		case cfc_op:{
346 			/* cop control register rd -> gpr[rt] */
347 			u32 value;
348 
349 			if (ir == CP1UNDEF) {
350 				return do_dsemulret(xcp);
351 			}
352 			if (MIPSInst_RD(ir) == FPCREG_CSR) {
353 				value = ctx->fcr31;
354 				value = (value & ~0x3) | mips_rm[value & 0x3];
355 #ifdef CSRTRACE
356 				printk("%p gpr[%d]<-csr=%08x\n",
357 					(void *) (xcp->cp0_epc),
358 					MIPSInst_RT(ir), value);
359 #endif
360 			}
361 			else if (MIPSInst_RD(ir) == FPCREG_RID)
362 				value = 0;
363 			else
364 				value = 0;
365 			if (MIPSInst_RT(ir))
366 				xcp->regs[MIPSInst_RT(ir)] = value;
367 			break;
368 		}
369 
370 		case ctc_op:{
371 			/* copregister rd <- rt */
372 			u32 value;
373 
374 			if (MIPSInst_RT(ir) == 0)
375 				value = 0;
376 			else
377 				value = xcp->regs[MIPSInst_RT(ir)];
378 
379 			/* we only have one writable control reg
380 			 */
381 			if (MIPSInst_RD(ir) == FPCREG_CSR) {
382 #ifdef CSRTRACE
383 				printk("%p gpr[%d]->csr=%08x\n",
384 					(void *) (xcp->cp0_epc),
385 					MIPSInst_RT(ir), value);
386 #endif
387 				value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
388 				ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
389 				/* convert to ieee library modes */
390 				ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3];
391 			}
392 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
393 				return SIGFPE;
394 			}
395 			break;
396 		}
397 
398 		case bc_op:{
399 			int likely = 0;
400 
401 			if (xcp->cp0_cause & CAUSEF_BD)
402 				return SIGILL;
403 
404 #if __mips >= 4
405 			cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2];
406 #else
407 			cond = ctx->fcr31 & FPU_CSR_COND;
408 #endif
409 			switch (MIPSInst_RT(ir) & 3) {
410 			case bcfl_op:
411 				likely = 1;
412 			case bcf_op:
413 				cond = !cond;
414 				break;
415 			case bctl_op:
416 				likely = 1;
417 			case bct_op:
418 				break;
419 			default:
420 				/* thats an illegal instruction */
421 				return SIGILL;
422 			}
423 
424 			xcp->cp0_cause |= CAUSEF_BD;
425 			if (cond) {
426 				/* branch taken: emulate dslot
427 				 * instruction
428 				 */
429 				xcp->cp0_epc += 4;
430 				contpc = (void *)
431 					(xcp->cp0_epc +
432 					(MIPSInst_SIMM(ir) << 2));
433 
434 				if (get_user(ir,
435 				    (mips_instruction __user *) xcp->cp0_epc)) {
436 					fpuemustats.errors++;
437 					return SIGBUS;
438 				}
439 
440 				switch (MIPSInst_OPCODE(ir)) {
441 				case lwc1_op:
442 				case swc1_op:
443 #if (__mips >= 2 || defined(__mips64))
444 				case ldc1_op:
445 				case sdc1_op:
446 #endif
447 				case cop1_op:
448 #if __mips >= 4 && __mips != 32
449 				case cop1x_op:
450 #endif
451 					/* its one of ours */
452 					goto emul;
453 #if __mips >= 4
454 				case spec_op:
455 					if (MIPSInst_FUNC(ir) == movc_op)
456 						goto emul;
457 					break;
458 #endif
459 				}
460 
461 				/*
462 				 * Single step the non-cp1
463 				 * instruction in the dslot
464 				 */
465 				return mips_dsemul(xcp, ir, (unsigned long) contpc);
466 			}
467 			else {
468 				/* branch not taken */
469 				if (likely) {
470 					/*
471 					 * branch likely nullifies
472 					 * dslot if not taken
473 					 */
474 					xcp->cp0_epc += 4;
475 					contpc += 4;
476 					/*
477 					 * else continue & execute
478 					 * dslot as normal insn
479 					 */
480 				}
481 			}
482 			break;
483 		}
484 
485 		default:
486 			if (!(MIPSInst_RS(ir) & 0x10))
487 				return SIGILL;
488 			{
489 				int sig;
490 
491 				/* a real fpu computation instruction */
492 				if ((sig = fpu_emu(xcp, ctx, ir)))
493 					return sig;
494 			}
495 		}
496 		break;
497 
498 #if __mips >= 4 && __mips != 32
499 	case cop1x_op:{
500 		int sig;
501 
502 		if ((sig = fpux_emu(xcp, ctx, ir)))
503 			return sig;
504 		break;
505 	}
506 #endif
507 
508 #if __mips >= 4
509 	case spec_op:
510 		if (MIPSInst_FUNC(ir) != movc_op)
511 			return SIGILL;
512 		cond = fpucondbit[MIPSInst_RT(ir) >> 2];
513 		if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0))
514 			xcp->regs[MIPSInst_RD(ir)] =
515 				xcp->regs[MIPSInst_RS(ir)];
516 		break;
517 #endif
518 
519 	default:
520 		return SIGILL;
521 	}
522 
523 	/* we did it !! */
524 	xcp->cp0_epc = (unsigned long) contpc;
525 	xcp->cp0_cause &= ~CAUSEF_BD;
526 
527 	return 0;
528 }
529 
530 /*
531  * Conversion table from MIPS compare ops 48-63
532  * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig);
533  */
534 static const unsigned char cmptab[8] = {
535 	0,			/* cmp_0 (sig) cmp_sf */
536 	IEEE754_CUN,		/* cmp_un (sig) cmp_ngle */
537 	IEEE754_CEQ,		/* cmp_eq (sig) cmp_seq */
538 	IEEE754_CEQ | IEEE754_CUN,	/* cmp_ueq (sig) cmp_ngl  */
539 	IEEE754_CLT,		/* cmp_olt (sig) cmp_lt */
540 	IEEE754_CLT | IEEE754_CUN,	/* cmp_ult (sig) cmp_nge */
541 	IEEE754_CLT | IEEE754_CEQ,	/* cmp_ole (sig) cmp_le */
542 	IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN,	/* cmp_ule (sig) cmp_ngt */
543 };
544 
545 
546 #if __mips >= 4 && __mips != 32
547 
548 /*
549  * Additional MIPS4 instructions
550  */
551 
552 #define DEF3OP(name, p, f1, f2, f3) \
553 static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \
554     ieee754##p t) \
555 { \
556 	struct _ieee754_csr ieee754_csr_save; \
557 	s = f1 (s, t); \
558 	ieee754_csr_save = ieee754_csr; \
559 	s = f2 (s, r); \
560 	ieee754_csr_save.cx |= ieee754_csr.cx; \
561 	ieee754_csr_save.sx |= ieee754_csr.sx; \
562 	s = f3 (s); \
563 	ieee754_csr.cx |= ieee754_csr_save.cx; \
564 	ieee754_csr.sx |= ieee754_csr_save.sx; \
565 	return s; \
566 }
567 
568 static ieee754dp fpemu_dp_recip(ieee754dp d)
569 {
570 	return ieee754dp_div(ieee754dp_one(0), d);
571 }
572 
573 static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
574 {
575 	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
576 }
577 
578 static ieee754sp fpemu_sp_recip(ieee754sp s)
579 {
580 	return ieee754sp_div(ieee754sp_one(0), s);
581 }
582 
583 static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
584 {
585 	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
586 }
587 
588 DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,);
589 DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,);
590 DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
591 DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
592 DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,);
593 DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,);
594 DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
595 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
596 
597 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
598 	mips_instruction ir)
599 {
600 	unsigned rcsr = 0;	/* resulting csr */
601 
602 	fpuemustats.cp1xops++;
603 
604 	switch (MIPSInst_FMA_FFMT(ir)) {
605 	case s_fmt:{		/* 0 */
606 
607 		ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
608 		ieee754sp fd, fr, fs, ft;
609 		u32 __user *va;
610 		u32 val;
611 
612 		switch (MIPSInst_FUNC(ir)) {
613 		case lwxc1_op:
614 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
615 				xcp->regs[MIPSInst_FT(ir)]);
616 
617 			fpuemustats.loads++;
618 			if (get_user(val, va)) {
619 				fpuemustats.errors++;
620 				return SIGBUS;
621 			}
622 			SITOREG(val, MIPSInst_FD(ir));
623 			break;
624 
625 		case swxc1_op:
626 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
627 				xcp->regs[MIPSInst_FT(ir)]);
628 
629 			fpuemustats.stores++;
630 
631 			SIFROMREG(val, MIPSInst_FS(ir));
632 			if (put_user(val, va)) {
633 				fpuemustats.errors++;
634 				return SIGBUS;
635 			}
636 			break;
637 
638 		case madd_s_op:
639 			handler = fpemu_sp_madd;
640 			goto scoptop;
641 		case msub_s_op:
642 			handler = fpemu_sp_msub;
643 			goto scoptop;
644 		case nmadd_s_op:
645 			handler = fpemu_sp_nmadd;
646 			goto scoptop;
647 		case nmsub_s_op:
648 			handler = fpemu_sp_nmsub;
649 			goto scoptop;
650 
651 		      scoptop:
652 			SPFROMREG(fr, MIPSInst_FR(ir));
653 			SPFROMREG(fs, MIPSInst_FS(ir));
654 			SPFROMREG(ft, MIPSInst_FT(ir));
655 			fd = (*handler) (fr, fs, ft);
656 			SPTOREG(fd, MIPSInst_FD(ir));
657 
658 		      copcsr:
659 			if (ieee754_cxtest(IEEE754_INEXACT))
660 				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
661 			if (ieee754_cxtest(IEEE754_UNDERFLOW))
662 				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
663 			if (ieee754_cxtest(IEEE754_OVERFLOW))
664 				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
665 			if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
666 				rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
667 
668 			ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
669 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
670 				/*printk ("SIGFPE: fpu csr = %08x\n",
671 				   ctx->fcr31); */
672 				return SIGFPE;
673 			}
674 
675 			break;
676 
677 		default:
678 			return SIGILL;
679 		}
680 		break;
681 	}
682 
683 	case d_fmt:{		/* 1 */
684 		ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
685 		ieee754dp fd, fr, fs, ft;
686 		u64 __user *va;
687 		u64 val;
688 
689 		switch (MIPSInst_FUNC(ir)) {
690 		case ldxc1_op:
691 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
692 				xcp->regs[MIPSInst_FT(ir)]);
693 
694 			fpuemustats.loads++;
695 			if (get_user(val, va)) {
696 				fpuemustats.errors++;
697 				return SIGBUS;
698 			}
699 			DITOREG(val, MIPSInst_FD(ir));
700 			break;
701 
702 		case sdxc1_op:
703 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
704 				xcp->regs[MIPSInst_FT(ir)]);
705 
706 			fpuemustats.stores++;
707 			DIFROMREG(val, MIPSInst_FS(ir));
708 			if (put_user(val, va)) {
709 				fpuemustats.errors++;
710 				return SIGBUS;
711 			}
712 			break;
713 
714 		case madd_d_op:
715 			handler = fpemu_dp_madd;
716 			goto dcoptop;
717 		case msub_d_op:
718 			handler = fpemu_dp_msub;
719 			goto dcoptop;
720 		case nmadd_d_op:
721 			handler = fpemu_dp_nmadd;
722 			goto dcoptop;
723 		case nmsub_d_op:
724 			handler = fpemu_dp_nmsub;
725 			goto dcoptop;
726 
727 		      dcoptop:
728 			DPFROMREG(fr, MIPSInst_FR(ir));
729 			DPFROMREG(fs, MIPSInst_FS(ir));
730 			DPFROMREG(ft, MIPSInst_FT(ir));
731 			fd = (*handler) (fr, fs, ft);
732 			DPTOREG(fd, MIPSInst_FD(ir));
733 			goto copcsr;
734 
735 		default:
736 			return SIGILL;
737 		}
738 		break;
739 	}
740 
741 	case 0x7:		/* 7 */
742 		if (MIPSInst_FUNC(ir) != pfetch_op) {
743 			return SIGILL;
744 		}
745 		/* ignore prefx operation */
746 		break;
747 
748 	default:
749 		return SIGILL;
750 	}
751 
752 	return 0;
753 }
754 #endif
755 
756 
757 
758 /*
759  * Emulate a single COP1 arithmetic instruction.
760  */
761 static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
762 	mips_instruction ir)
763 {
764 	int rfmt;		/* resulting format */
765 	unsigned rcsr = 0;	/* resulting csr */
766 	unsigned cond;
767 	union {
768 		ieee754dp d;
769 		ieee754sp s;
770 		int w;
771 #ifdef __mips64
772 		s64 l;
773 #endif
774 	} rv;			/* resulting value */
775 
776 	fpuemustats.cp1ops++;
777 	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
778 	case s_fmt:{		/* 0 */
779 		union {
780 			ieee754sp(*b) (ieee754sp, ieee754sp);
781 			ieee754sp(*u) (ieee754sp);
782 		} handler;
783 
784 		switch (MIPSInst_FUNC(ir)) {
785 			/* binary ops */
786 		case fadd_op:
787 			handler.b = ieee754sp_add;
788 			goto scopbop;
789 		case fsub_op:
790 			handler.b = ieee754sp_sub;
791 			goto scopbop;
792 		case fmul_op:
793 			handler.b = ieee754sp_mul;
794 			goto scopbop;
795 		case fdiv_op:
796 			handler.b = ieee754sp_div;
797 			goto scopbop;
798 
799 			/* unary  ops */
800 #if __mips >= 2 || defined(__mips64)
801 		case fsqrt_op:
802 			handler.u = ieee754sp_sqrt;
803 			goto scopuop;
804 #endif
805 #if __mips >= 4 && __mips != 32
806 		case frsqrt_op:
807 			handler.u = fpemu_sp_rsqrt;
808 			goto scopuop;
809 		case frecip_op:
810 			handler.u = fpemu_sp_recip;
811 			goto scopuop;
812 #endif
813 #if __mips >= 4
814 		case fmovc_op:
815 			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
816 			if (((ctx->fcr31 & cond) != 0) !=
817 				((MIPSInst_FT(ir) & 1) != 0))
818 				return 0;
819 			SPFROMREG(rv.s, MIPSInst_FS(ir));
820 			break;
821 		case fmovz_op:
822 			if (xcp->regs[MIPSInst_FT(ir)] != 0)
823 				return 0;
824 			SPFROMREG(rv.s, MIPSInst_FS(ir));
825 			break;
826 		case fmovn_op:
827 			if (xcp->regs[MIPSInst_FT(ir)] == 0)
828 				return 0;
829 			SPFROMREG(rv.s, MIPSInst_FS(ir));
830 			break;
831 #endif
832 		case fabs_op:
833 			handler.u = ieee754sp_abs;
834 			goto scopuop;
835 		case fneg_op:
836 			handler.u = ieee754sp_neg;
837 			goto scopuop;
838 		case fmov_op:
839 			/* an easy one */
840 			SPFROMREG(rv.s, MIPSInst_FS(ir));
841 			goto copcsr;
842 
843 			/* binary op on handler */
844 		      scopbop:
845 			{
846 				ieee754sp fs, ft;
847 
848 				SPFROMREG(fs, MIPSInst_FS(ir));
849 				SPFROMREG(ft, MIPSInst_FT(ir));
850 
851 				rv.s = (*handler.b) (fs, ft);
852 				goto copcsr;
853 			}
854 		      scopuop:
855 			{
856 				ieee754sp fs;
857 
858 				SPFROMREG(fs, MIPSInst_FS(ir));
859 				rv.s = (*handler.u) (fs);
860 				goto copcsr;
861 			}
862 		      copcsr:
863 			if (ieee754_cxtest(IEEE754_INEXACT))
864 				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
865 			if (ieee754_cxtest(IEEE754_UNDERFLOW))
866 				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
867 			if (ieee754_cxtest(IEEE754_OVERFLOW))
868 				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
869 			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
870 				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
871 			if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
872 				rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
873 			break;
874 
875 			/* unary conv ops */
876 		case fcvts_op:
877 			return SIGILL;	/* not defined */
878 		case fcvtd_op:{
879 			ieee754sp fs;
880 
881 			SPFROMREG(fs, MIPSInst_FS(ir));
882 			rv.d = ieee754dp_fsp(fs);
883 			rfmt = d_fmt;
884 			goto copcsr;
885 		}
886 		case fcvtw_op:{
887 			ieee754sp fs;
888 
889 			SPFROMREG(fs, MIPSInst_FS(ir));
890 			rv.w = ieee754sp_tint(fs);
891 			rfmt = w_fmt;
892 			goto copcsr;
893 		}
894 
895 #if __mips >= 2 || defined(__mips64)
896 		case fround_op:
897 		case ftrunc_op:
898 		case fceil_op:
899 		case ffloor_op:{
900 			unsigned int oldrm = ieee754_csr.rm;
901 			ieee754sp fs;
902 
903 			SPFROMREG(fs, MIPSInst_FS(ir));
904 			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
905 			rv.w = ieee754sp_tint(fs);
906 			ieee754_csr.rm = oldrm;
907 			rfmt = w_fmt;
908 			goto copcsr;
909 		}
910 #endif /* __mips >= 2 */
911 
912 #if defined(__mips64)
913 		case fcvtl_op:{
914 			ieee754sp fs;
915 
916 			SPFROMREG(fs, MIPSInst_FS(ir));
917 			rv.l = ieee754sp_tlong(fs);
918 			rfmt = l_fmt;
919 			goto copcsr;
920 		}
921 
922 		case froundl_op:
923 		case ftruncl_op:
924 		case fceill_op:
925 		case ffloorl_op:{
926 			unsigned int oldrm = ieee754_csr.rm;
927 			ieee754sp fs;
928 
929 			SPFROMREG(fs, MIPSInst_FS(ir));
930 			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
931 			rv.l = ieee754sp_tlong(fs);
932 			ieee754_csr.rm = oldrm;
933 			rfmt = l_fmt;
934 			goto copcsr;
935 		}
936 #endif /* defined(__mips64) */
937 
938 		default:
939 			if (MIPSInst_FUNC(ir) >= fcmp_op) {
940 				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
941 				ieee754sp fs, ft;
942 
943 				SPFROMREG(fs, MIPSInst_FS(ir));
944 				SPFROMREG(ft, MIPSInst_FT(ir));
945 				rv.w = ieee754sp_cmp(fs, ft,
946 					cmptab[cmpop & 0x7], cmpop & 0x8);
947 				rfmt = -1;
948 				if ((cmpop & 0x8) && ieee754_cxtest
949 					(IEEE754_INVALID_OPERATION))
950 					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
951 				else
952 					goto copcsr;
953 
954 			}
955 			else {
956 				return SIGILL;
957 			}
958 			break;
959 		}
960 		break;
961 	}
962 
963 	case d_fmt:{
964 		union {
965 			ieee754dp(*b) (ieee754dp, ieee754dp);
966 			ieee754dp(*u) (ieee754dp);
967 		} handler;
968 
969 		switch (MIPSInst_FUNC(ir)) {
970 			/* binary ops */
971 		case fadd_op:
972 			handler.b = ieee754dp_add;
973 			goto dcopbop;
974 		case fsub_op:
975 			handler.b = ieee754dp_sub;
976 			goto dcopbop;
977 		case fmul_op:
978 			handler.b = ieee754dp_mul;
979 			goto dcopbop;
980 		case fdiv_op:
981 			handler.b = ieee754dp_div;
982 			goto dcopbop;
983 
984 			/* unary  ops */
985 #if __mips >= 2 || defined(__mips64)
986 		case fsqrt_op:
987 			handler.u = ieee754dp_sqrt;
988 			goto dcopuop;
989 #endif
990 #if __mips >= 4 && __mips != 32
991 		case frsqrt_op:
992 			handler.u = fpemu_dp_rsqrt;
993 			goto dcopuop;
994 		case frecip_op:
995 			handler.u = fpemu_dp_recip;
996 			goto dcopuop;
997 #endif
998 #if __mips >= 4
999 		case fmovc_op:
1000 			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
1001 			if (((ctx->fcr31 & cond) != 0) !=
1002 				((MIPSInst_FT(ir) & 1) != 0))
1003 				return 0;
1004 			DPFROMREG(rv.d, MIPSInst_FS(ir));
1005 			break;
1006 		case fmovz_op:
1007 			if (xcp->regs[MIPSInst_FT(ir)] != 0)
1008 				return 0;
1009 			DPFROMREG(rv.d, MIPSInst_FS(ir));
1010 			break;
1011 		case fmovn_op:
1012 			if (xcp->regs[MIPSInst_FT(ir)] == 0)
1013 				return 0;
1014 			DPFROMREG(rv.d, MIPSInst_FS(ir));
1015 			break;
1016 #endif
1017 		case fabs_op:
1018 			handler.u = ieee754dp_abs;
1019 			goto dcopuop;
1020 
1021 		case fneg_op:
1022 			handler.u = ieee754dp_neg;
1023 			goto dcopuop;
1024 
1025 		case fmov_op:
1026 			/* an easy one */
1027 			DPFROMREG(rv.d, MIPSInst_FS(ir));
1028 			goto copcsr;
1029 
1030 			/* binary op on handler */
1031 		      dcopbop:{
1032 				ieee754dp fs, ft;
1033 
1034 				DPFROMREG(fs, MIPSInst_FS(ir));
1035 				DPFROMREG(ft, MIPSInst_FT(ir));
1036 
1037 				rv.d = (*handler.b) (fs, ft);
1038 				goto copcsr;
1039 			}
1040 		      dcopuop:{
1041 				ieee754dp fs;
1042 
1043 				DPFROMREG(fs, MIPSInst_FS(ir));
1044 				rv.d = (*handler.u) (fs);
1045 				goto copcsr;
1046 			}
1047 
1048 			/* unary conv ops */
1049 		case fcvts_op:{
1050 			ieee754dp fs;
1051 
1052 			DPFROMREG(fs, MIPSInst_FS(ir));
1053 			rv.s = ieee754sp_fdp(fs);
1054 			rfmt = s_fmt;
1055 			goto copcsr;
1056 		}
1057 		case fcvtd_op:
1058 			return SIGILL;	/* not defined */
1059 
1060 		case fcvtw_op:{
1061 			ieee754dp fs;
1062 
1063 			DPFROMREG(fs, MIPSInst_FS(ir));
1064 			rv.w = ieee754dp_tint(fs);	/* wrong */
1065 			rfmt = w_fmt;
1066 			goto copcsr;
1067 		}
1068 
1069 #if __mips >= 2 || defined(__mips64)
1070 		case fround_op:
1071 		case ftrunc_op:
1072 		case fceil_op:
1073 		case ffloor_op:{
1074 			unsigned int oldrm = ieee754_csr.rm;
1075 			ieee754dp fs;
1076 
1077 			DPFROMREG(fs, MIPSInst_FS(ir));
1078 			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
1079 			rv.w = ieee754dp_tint(fs);
1080 			ieee754_csr.rm = oldrm;
1081 			rfmt = w_fmt;
1082 			goto copcsr;
1083 		}
1084 #endif
1085 
1086 #if defined(__mips64)
1087 		case fcvtl_op:{
1088 			ieee754dp fs;
1089 
1090 			DPFROMREG(fs, MIPSInst_FS(ir));
1091 			rv.l = ieee754dp_tlong(fs);
1092 			rfmt = l_fmt;
1093 			goto copcsr;
1094 		}
1095 
1096 		case froundl_op:
1097 		case ftruncl_op:
1098 		case fceill_op:
1099 		case ffloorl_op:{
1100 			unsigned int oldrm = ieee754_csr.rm;
1101 			ieee754dp fs;
1102 
1103 			DPFROMREG(fs, MIPSInst_FS(ir));
1104 			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
1105 			rv.l = ieee754dp_tlong(fs);
1106 			ieee754_csr.rm = oldrm;
1107 			rfmt = l_fmt;
1108 			goto copcsr;
1109 		}
1110 #endif /* __mips >= 3 */
1111 
1112 		default:
1113 			if (MIPSInst_FUNC(ir) >= fcmp_op) {
1114 				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
1115 				ieee754dp fs, ft;
1116 
1117 				DPFROMREG(fs, MIPSInst_FS(ir));
1118 				DPFROMREG(ft, MIPSInst_FT(ir));
1119 				rv.w = ieee754dp_cmp(fs, ft,
1120 					cmptab[cmpop & 0x7], cmpop & 0x8);
1121 				rfmt = -1;
1122 				if ((cmpop & 0x8)
1123 					&&
1124 					ieee754_cxtest
1125 					(IEEE754_INVALID_OPERATION))
1126 					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
1127 				else
1128 					goto copcsr;
1129 
1130 			}
1131 			else {
1132 				return SIGILL;
1133 			}
1134 			break;
1135 		}
1136 		break;
1137 	}
1138 
1139 	case w_fmt:{
1140 		ieee754sp fs;
1141 
1142 		switch (MIPSInst_FUNC(ir)) {
1143 		case fcvts_op:
1144 			/* convert word to single precision real */
1145 			SPFROMREG(fs, MIPSInst_FS(ir));
1146 			rv.s = ieee754sp_fint(fs.bits);
1147 			rfmt = s_fmt;
1148 			goto copcsr;
1149 		case fcvtd_op:
1150 			/* convert word to double precision real */
1151 			SPFROMREG(fs, MIPSInst_FS(ir));
1152 			rv.d = ieee754dp_fint(fs.bits);
1153 			rfmt = d_fmt;
1154 			goto copcsr;
1155 		default:
1156 			return SIGILL;
1157 		}
1158 		break;
1159 	}
1160 
1161 #if defined(__mips64)
1162 	case l_fmt:{
1163 		switch (MIPSInst_FUNC(ir)) {
1164 		case fcvts_op:
1165 			/* convert long to single precision real */
1166 			rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]);
1167 			rfmt = s_fmt;
1168 			goto copcsr;
1169 		case fcvtd_op:
1170 			/* convert long to double precision real */
1171 			rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]);
1172 			rfmt = d_fmt;
1173 			goto copcsr;
1174 		default:
1175 			return SIGILL;
1176 		}
1177 		break;
1178 	}
1179 #endif
1180 
1181 	default:
1182 		return SIGILL;
1183 	}
1184 
1185 	/*
1186 	 * Update the fpu CSR register for this operation.
1187 	 * If an exception is required, generate a tidy SIGFPE exception,
1188 	 * without updating the result register.
1189 	 * Note: cause exception bits do not accumulate, they are rewritten
1190 	 * for each op; only the flag/sticky bits accumulate.
1191 	 */
1192 	ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
1193 	if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
1194 		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */
1195 		return SIGFPE;
1196 	}
1197 
1198 	/*
1199 	 * Now we can safely write the result back to the register file.
1200 	 */
1201 	switch (rfmt) {
1202 	case -1:{
1203 #if __mips >= 4
1204 		cond = fpucondbit[MIPSInst_FD(ir) >> 2];
1205 #else
1206 		cond = FPU_CSR_COND;
1207 #endif
1208 		if (rv.w)
1209 			ctx->fcr31 |= cond;
1210 		else
1211 			ctx->fcr31 &= ~cond;
1212 		break;
1213 	}
1214 	case d_fmt:
1215 		DPTOREG(rv.d, MIPSInst_FD(ir));
1216 		break;
1217 	case s_fmt:
1218 		SPTOREG(rv.s, MIPSInst_FD(ir));
1219 		break;
1220 	case w_fmt:
1221 		SITOREG(rv.w, MIPSInst_FD(ir));
1222 		break;
1223 #if defined(__mips64)
1224 	case l_fmt:
1225 		DITOREG(rv.l, MIPSInst_FD(ir));
1226 		break;
1227 #endif
1228 	default:
1229 		return SIGILL;
1230 	}
1231 
1232 	return 0;
1233 }
1234 
1235 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1236 	int has_fpu)
1237 {
1238 	unsigned long oldepc, prevepc;
1239 	mips_instruction insn;
1240 	int sig = 0;
1241 
1242 	oldepc = xcp->cp0_epc;
1243 	do {
1244 		prevepc = xcp->cp0_epc;
1245 
1246 		if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
1247 			fpuemustats.errors++;
1248 			return SIGBUS;
1249 		}
1250 		if (insn == 0)
1251 			xcp->cp0_epc += 4;	/* skip nops */
1252 		else {
1253 			/*
1254 			 * The 'ieee754_csr' is an alias of
1255 			 * ctx->fcr31.  No need to copy ctx->fcr31 to
1256 			 * ieee754_csr.  But ieee754_csr.rm is ieee
1257 			 * library modes. (not mips rounding mode)
1258 			 */
1259 			/* convert to ieee library modes */
1260 			ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
1261 			sig = cop1Emulate(xcp, ctx);
1262 			/* revert to mips rounding mode */
1263 			ieee754_csr.rm = mips_rm[ieee754_csr.rm];
1264 		}
1265 
1266 		if (has_fpu)
1267 			break;
1268 		if (sig)
1269 			break;
1270 
1271 		cond_resched();
1272 	} while (xcp->cp0_epc > prevepc);
1273 
1274 	/* SIGILL indicates a non-fpu instruction */
1275 	if (sig == SIGILL && xcp->cp0_epc != oldepc)
1276 		/* but if epc has advanced, then ignore it */
1277 		sig = 0;
1278 
1279 	return sig;
1280 }
1281 
1282 #ifdef CONFIG_DEBUG_FS
1283 extern struct dentry *mips_debugfs_dir;
1284 static int __init debugfs_fpuemu(void)
1285 {
1286 	struct dentry *d, *dir;
1287 	int i;
1288 	static struct {
1289 		const char *name;
1290 		unsigned int *v;
1291 	} vars[] __initdata = {
1292 		{ "emulated", &fpuemustats.emulated },
1293 		{ "loads",    &fpuemustats.loads },
1294 		{ "stores",   &fpuemustats.stores },
1295 		{ "cp1ops",   &fpuemustats.cp1ops },
1296 		{ "cp1xops",  &fpuemustats.cp1xops },
1297 		{ "errors",   &fpuemustats.errors },
1298 	};
1299 
1300 	if (!mips_debugfs_dir)
1301 		return -ENODEV;
1302 	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
1303 	if (IS_ERR(dir))
1304 		return PTR_ERR(dir);
1305 	for (i = 0; i < ARRAY_SIZE(vars); i++) {
1306 		d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
1307 		if (IS_ERR(d))
1308 			return PTR_ERR(d);
1309 	}
1310 	return 0;
1311 }
1312 __initcall(debugfs_fpuemu);
1313 #endif
1314