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