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