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