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