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 --- |