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