cp1emu.c (12616ed202ba66af6e1386df02d06c72d7386339) cp1emu.c (3fccc0150e720ff344b5f9c5f8dd23778139018e)
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

--- 195 unchanged lines hidden (view full) ---

204 */
205
206static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
207{
208 mips_instruction ir;
209 void * emulpc, *contpc;
210 unsigned int cond;
211
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

--- 195 unchanged lines hidden (view full) ---

204 */
205
206static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
207{
208 mips_instruction ir;
209 void * emulpc, *contpc;
210 unsigned int cond;
211
212 if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
212 if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
213 fpuemustats.errors++;
214 return SIGBUS;
215 }
216
217 /* XXX NEC Vr54xx bug workaround */
218 if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
219 xcp->cp0_cause &= ~CAUSEF_BD;
220

--- 14 unchanged lines hidden (view full) ---

235
236 if (__compute_return_epc(xcp)) {
237#ifdef CP1DBG
238 printk("failed to emulate branch at %p\n",
239 (void *) (xcp->cp0_epc));
240#endif
241 return SIGILL;
242 }
213 fpuemustats.errors++;
214 return SIGBUS;
215 }
216
217 /* XXX NEC Vr54xx bug workaround */
218 if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
219 xcp->cp0_cause &= ~CAUSEF_BD;
220

--- 14 unchanged lines hidden (view full) ---

235
236 if (__compute_return_epc(xcp)) {
237#ifdef CP1DBG
238 printk("failed to emulate branch at %p\n",
239 (void *) (xcp->cp0_epc));
240#endif
241 return SIGILL;
242 }
243 if (get_user(ir, (mips_instruction *) emulpc)) {
243 if (get_user(ir, (mips_instruction __user *) emulpc)) {
244 fpuemustats.errors++;
245 return SIGBUS;
246 }
247 /* __compute_return_epc() will have updated cp0_epc */
248 contpc = (void *) xcp->cp0_epc;
249 /* In order not to confuse ptrace() et al, tweak context */
250 xcp->cp0_epc = (unsigned long) emulpc - 4;
251 } else {
252 emulpc = (void *) xcp->cp0_epc;
253 contpc = (void *) (xcp->cp0_epc + 4);
254 }
255
256 emul:
257 fpuemustats.emulated++;
258 switch (MIPSInst_OPCODE(ir)) {
259#ifndef SINGLE_ONLY_FPU
260 case ldc1_op:{
244 fpuemustats.errors++;
245 return SIGBUS;
246 }
247 /* __compute_return_epc() will have updated cp0_epc */
248 contpc = (void *) xcp->cp0_epc;
249 /* In order not to confuse ptrace() et al, tweak context */
250 xcp->cp0_epc = (unsigned long) emulpc - 4;
251 } else {
252 emulpc = (void *) xcp->cp0_epc;
253 contpc = (void *) (xcp->cp0_epc + 4);
254 }
255
256 emul:
257 fpuemustats.emulated++;
258 switch (MIPSInst_OPCODE(ir)) {
259#ifndef SINGLE_ONLY_FPU
260 case ldc1_op:{
261 u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
261 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
262 MIPSInst_SIMM(ir));
263 u64 val;
264
265 fpuemustats.loads++;
266 if (get_user(val, va)) {
267 fpuemustats.errors++;
268 return SIGBUS;
269 }
270 DITOREG(val, MIPSInst_RT(ir));
271 break;
272 }
273
274 case sdc1_op:{
262 MIPSInst_SIMM(ir));
263 u64 val;
264
265 fpuemustats.loads++;
266 if (get_user(val, va)) {
267 fpuemustats.errors++;
268 return SIGBUS;
269 }
270 DITOREG(val, MIPSInst_RT(ir));
271 break;
272 }
273
274 case sdc1_op:{
275 u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
275 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
276 MIPSInst_SIMM(ir));
277 u64 val;
278
279 fpuemustats.stores++;
280 DIFROMREG(val, MIPSInst_RT(ir));
281 if (put_user(val, va)) {
282 fpuemustats.errors++;
283 return SIGBUS;
284 }
285 break;
286 }
287#endif
288
289 case lwc1_op:{
276 MIPSInst_SIMM(ir));
277 u64 val;
278
279 fpuemustats.stores++;
280 DIFROMREG(val, MIPSInst_RT(ir));
281 if (put_user(val, va)) {
282 fpuemustats.errors++;
283 return SIGBUS;
284 }
285 break;
286 }
287#endif
288
289 case lwc1_op:{
290 u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
290 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
291 MIPSInst_SIMM(ir));
292 u32 val;
293
294 fpuemustats.loads++;
295 if (get_user(val, va)) {
296 fpuemustats.errors++;
297 return SIGBUS;
298 }
299#ifdef SINGLE_ONLY_FPU
300 if (MIPSInst_RT(ir) & 1) {
301 /* illegal register in single-float mode */
302 return SIGILL;
303 }
304#endif
305 SITOREG(val, MIPSInst_RT(ir));
306 break;
307 }
308
309 case swc1_op:{
291 MIPSInst_SIMM(ir));
292 u32 val;
293
294 fpuemustats.loads++;
295 if (get_user(val, va)) {
296 fpuemustats.errors++;
297 return SIGBUS;
298 }
299#ifdef SINGLE_ONLY_FPU
300 if (MIPSInst_RT(ir) & 1) {
301 /* illegal register in single-float mode */
302 return SIGILL;
303 }
304#endif
305 SITOREG(val, MIPSInst_RT(ir));
306 break;
307 }
308
309 case swc1_op:{
310 u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
310 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
311 MIPSInst_SIMM(ir));
312 u32 val;
313
314 fpuemustats.stores++;
315#ifdef SINGLE_ONLY_FPU
316 if (MIPSInst_RT(ir) & 1) {
317 /* illegal register in single-float mode */
318 return SIGILL;

--- 134 unchanged lines hidden (view full) ---

453 /* branch taken: emulate dslot
454 * instruction
455 */
456 xcp->cp0_epc += 4;
457 contpc = (void *)
458 (xcp->cp0_epc +
459 (MIPSInst_SIMM(ir) << 2));
460
311 MIPSInst_SIMM(ir));
312 u32 val;
313
314 fpuemustats.stores++;
315#ifdef SINGLE_ONLY_FPU
316 if (MIPSInst_RT(ir) & 1) {
317 /* illegal register in single-float mode */
318 return SIGILL;

--- 134 unchanged lines hidden (view full) ---

453 /* branch taken: emulate dslot
454 * instruction
455 */
456 xcp->cp0_epc += 4;
457 contpc = (void *)
458 (xcp->cp0_epc +
459 (MIPSInst_SIMM(ir) << 2));
460
461 if (get_user(ir, (mips_instruction *)
462 (void *) xcp->cp0_epc)) {
461 if (get_user(ir,
462 (mips_instruction __user *) xcp->cp0_epc)) {
463 fpuemustats.errors++;
464 return SIGBUS;
465 }
466
467 switch (MIPSInst_OPCODE(ir)) {
468 case lwc1_op:
469 case swc1_op:
470#if (__mips >= 2 || defined(__mips64)) && !defined(SINGLE_ONLY_FPU)

--- 157 unchanged lines hidden (view full) ---

628
629 fpuemustats.cp1xops++;
630
631 switch (MIPSInst_FMA_FFMT(ir)) {
632 case s_fmt:{ /* 0 */
633
634 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
635 ieee754sp fd, fr, fs, ft;
463 fpuemustats.errors++;
464 return SIGBUS;
465 }
466
467 switch (MIPSInst_OPCODE(ir)) {
468 case lwc1_op:
469 case swc1_op:
470#if (__mips >= 2 || defined(__mips64)) && !defined(SINGLE_ONLY_FPU)

--- 157 unchanged lines hidden (view full) ---

628
629 fpuemustats.cp1xops++;
630
631 switch (MIPSInst_FMA_FFMT(ir)) {
632 case s_fmt:{ /* 0 */
633
634 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
635 ieee754sp fd, fr, fs, ft;
636 u32 *va;
636 u32 __user *va;
637 u32 val;
638
639 switch (MIPSInst_FUNC(ir)) {
640 case lwxc1_op:
637 u32 val;
638
639 switch (MIPSInst_FUNC(ir)) {
640 case lwxc1_op:
641 va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
641 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
642 xcp->regs[MIPSInst_FT(ir)]);
643
644 fpuemustats.loads++;
645 if (get_user(val, va)) {
646 fpuemustats.errors++;
647 return SIGBUS;
648 }
649#ifdef SINGLE_ONLY_FPU
650 if (MIPSInst_FD(ir) & 1) {
651 /* illegal register in single-float
652 * mode
653 */
654 return SIGILL;
655 }
656#endif
657 SITOREG(val, MIPSInst_FD(ir));
658 break;
659
660 case swxc1_op:
642 xcp->regs[MIPSInst_FT(ir)]);
643
644 fpuemustats.loads++;
645 if (get_user(val, va)) {
646 fpuemustats.errors++;
647 return SIGBUS;
648 }
649#ifdef SINGLE_ONLY_FPU
650 if (MIPSInst_FD(ir) & 1) {
651 /* illegal register in single-float
652 * mode
653 */
654 return SIGILL;
655 }
656#endif
657 SITOREG(val, MIPSInst_FD(ir));
658 break;
659
660 case swxc1_op:
661 va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
661 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
662 xcp->regs[MIPSInst_FT(ir)]);
663
664 fpuemustats.stores++;
665#ifdef SINGLE_ONLY_FPU
666 if (MIPSInst_FS(ir) & 1) {
667 /* illegal register in single-float
668 * mode
669 */

--- 52 unchanged lines hidden (view full) ---

722 }
723 break;
724 }
725
726#ifndef SINGLE_ONLY_FPU
727 case d_fmt:{ /* 1 */
728 ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
729 ieee754dp fd, fr, fs, ft;
662 xcp->regs[MIPSInst_FT(ir)]);
663
664 fpuemustats.stores++;
665#ifdef SINGLE_ONLY_FPU
666 if (MIPSInst_FS(ir) & 1) {
667 /* illegal register in single-float
668 * mode
669 */

--- 52 unchanged lines hidden (view full) ---

722 }
723 break;
724 }
725
726#ifndef SINGLE_ONLY_FPU
727 case d_fmt:{ /* 1 */
728 ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
729 ieee754dp fd, fr, fs, ft;
730 u64 *va;
730 u64 __user *va;
731 u64 val;
732
733 switch (MIPSInst_FUNC(ir)) {
734 case ldxc1_op:
731 u64 val;
732
733 switch (MIPSInst_FUNC(ir)) {
734 case ldxc1_op:
735 va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
735 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
736 xcp->regs[MIPSInst_FT(ir)]);
737
738 fpuemustats.loads++;
739 if (get_user(val, va)) {
740 fpuemustats.errors++;
741 return SIGBUS;
742 }
743 DITOREG(val, MIPSInst_FD(ir));
744 break;
745
746 case sdxc1_op:
736 xcp->regs[MIPSInst_FT(ir)]);
737
738 fpuemustats.loads++;
739 if (get_user(val, va)) {
740 fpuemustats.errors++;
741 return SIGBUS;
742 }
743 DITOREG(val, MIPSInst_FD(ir));
744 break;
745
746 case sdxc1_op:
747 va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
747 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
748 xcp->regs[MIPSInst_FT(ir)]);
749
750 fpuemustats.stores++;
751 DIFROMREG(val, MIPSInst_FS(ir));
752 if (put_user(val, va)) {
753 fpuemustats.errors++;
754 return SIGBUS;
755 }

--- 537 unchanged lines hidden (view full) ---

1293 unsigned long oldepc, prevepc;
1294 mips_instruction insn;
1295 int sig = 0;
1296
1297 oldepc = xcp->cp0_epc;
1298 do {
1299 prevepc = xcp->cp0_epc;
1300
748 xcp->regs[MIPSInst_FT(ir)]);
749
750 fpuemustats.stores++;
751 DIFROMREG(val, MIPSInst_FS(ir));
752 if (put_user(val, va)) {
753 fpuemustats.errors++;
754 return SIGBUS;
755 }

--- 537 unchanged lines hidden (view full) ---

1293 unsigned long oldepc, prevepc;
1294 mips_instruction insn;
1295 int sig = 0;
1296
1297 oldepc = xcp->cp0_epc;
1298 do {
1299 prevepc = xcp->cp0_epc;
1300
1301 if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) {
1301 if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
1302 fpuemustats.errors++;
1303 return SIGBUS;
1304 }
1305 if (insn == 0)
1306 xcp->cp0_epc += 4; /* skip nops */
1307 else {
1308 /*
1309 * The 'ieee754_csr' is an alias of

--- 26 unchanged lines hidden ---
1302 fpuemustats.errors++;
1303 return SIGBUS;
1304 }
1305 if (insn == 0)
1306 xcp->cp0_epc += 4; /* skip nops */
1307 else {
1308 /*
1309 * The 'ieee754_csr' is an alias of

--- 26 unchanged lines hidden ---