1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * arch/powerpc/math-emu/math_efp.c 4 * 5 * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc. 6 * 7 * Author: Ebony Zhu, <ebony.zhu@freescale.com> 8 * Yu Liu, <yu.liu@freescale.com> 9 * 10 * Derived from arch/alpha/math-emu/math.c 11 * arch/powerpc/math-emu/math.c 12 * 13 * Description: 14 * This file is the exception handler to make E500 SPE instructions 15 * fully comply with IEEE-754 floating point standard. 16 */ 17 18 #include <linux/types.h> 19 #include <linux/prctl.h> 20 #include <linux/module.h> 21 22 #include <linux/uaccess.h> 23 #include <asm/reg.h> 24 25 #define FP_EX_BOOKE_E500_SPE 26 #include <asm/sfp-machine.h> 27 28 #include <math-emu/soft-fp.h> 29 #include <math-emu/single.h> 30 #include <math-emu/double.h> 31 32 #define EFAPU 0x4 33 34 #define VCT 0x4 35 #define SPFP 0x6 36 #define DPFP 0x7 37 38 #define EFSADD 0x2c0 39 #define EFSSUB 0x2c1 40 #define EFSABS 0x2c4 41 #define EFSNABS 0x2c5 42 #define EFSNEG 0x2c6 43 #define EFSMUL 0x2c8 44 #define EFSDIV 0x2c9 45 #define EFSCMPGT 0x2cc 46 #define EFSCMPLT 0x2cd 47 #define EFSCMPEQ 0x2ce 48 #define EFSCFD 0x2cf 49 #define EFSCFSI 0x2d1 50 #define EFSCTUI 0x2d4 51 #define EFSCTSI 0x2d5 52 #define EFSCTUF 0x2d6 53 #define EFSCTSF 0x2d7 54 #define EFSCTUIZ 0x2d8 55 #define EFSCTSIZ 0x2da 56 57 #define EVFSADD 0x280 58 #define EVFSSUB 0x281 59 #define EVFSABS 0x284 60 #define EVFSNABS 0x285 61 #define EVFSNEG 0x286 62 #define EVFSMUL 0x288 63 #define EVFSDIV 0x289 64 #define EVFSCMPGT 0x28c 65 #define EVFSCMPLT 0x28d 66 #define EVFSCMPEQ 0x28e 67 #define EVFSCTUI 0x294 68 #define EVFSCTSI 0x295 69 #define EVFSCTUF 0x296 70 #define EVFSCTSF 0x297 71 #define EVFSCTUIZ 0x298 72 #define EVFSCTSIZ 0x29a 73 74 #define EFDADD 0x2e0 75 #define EFDSUB 0x2e1 76 #define EFDABS 0x2e4 77 #define EFDNABS 0x2e5 78 #define EFDNEG 0x2e6 79 #define EFDMUL 0x2e8 80 #define EFDDIV 0x2e9 81 #define EFDCTUIDZ 0x2ea 82 #define EFDCTSIDZ 0x2eb 83 #define EFDCMPGT 0x2ec 84 #define EFDCMPLT 0x2ed 85 #define EFDCMPEQ 0x2ee 86 #define EFDCFS 0x2ef 87 #define EFDCTUI 0x2f4 88 #define EFDCTSI 0x2f5 89 #define EFDCTUF 0x2f6 90 #define EFDCTSF 0x2f7 91 #define EFDCTUIZ 0x2f8 92 #define EFDCTSIZ 0x2fa 93 94 #define AB 2 95 #define XA 3 96 #define XB 4 97 #define XCR 5 98 #define NOTYPE 0 99 100 #define SIGN_BIT_S (1UL << 31) 101 #define SIGN_BIT_D (1ULL << 63) 102 #define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \ 103 FP_EX_UNDERFLOW | FP_EX_OVERFLOW) 104 105 static int have_e500_cpu_a005_erratum; 106 107 union dw_union { 108 u64 dp[1]; 109 u32 wp[2]; 110 }; 111 112 static unsigned long insn_type(unsigned long speinsn) 113 { 114 unsigned long ret = NOTYPE; 115 116 switch (speinsn & 0x7ff) { 117 case EFSABS: ret = XA; break; 118 case EFSADD: ret = AB; break; 119 case EFSCFD: ret = XB; break; 120 case EFSCMPEQ: ret = XCR; break; 121 case EFSCMPGT: ret = XCR; break; 122 case EFSCMPLT: ret = XCR; break; 123 case EFSCTSF: ret = XB; break; 124 case EFSCTSI: ret = XB; break; 125 case EFSCTSIZ: ret = XB; break; 126 case EFSCTUF: ret = XB; break; 127 case EFSCTUI: ret = XB; break; 128 case EFSCTUIZ: ret = XB; break; 129 case EFSDIV: ret = AB; break; 130 case EFSMUL: ret = AB; break; 131 case EFSNABS: ret = XA; break; 132 case EFSNEG: ret = XA; break; 133 case EFSSUB: ret = AB; break; 134 case EFSCFSI: ret = XB; break; 135 136 case EVFSABS: ret = XA; break; 137 case EVFSADD: ret = AB; break; 138 case EVFSCMPEQ: ret = XCR; break; 139 case EVFSCMPGT: ret = XCR; break; 140 case EVFSCMPLT: ret = XCR; break; 141 case EVFSCTSF: ret = XB; break; 142 case EVFSCTSI: ret = XB; break; 143 case EVFSCTSIZ: ret = XB; break; 144 case EVFSCTUF: ret = XB; break; 145 case EVFSCTUI: ret = XB; break; 146 case EVFSCTUIZ: ret = XB; break; 147 case EVFSDIV: ret = AB; break; 148 case EVFSMUL: ret = AB; break; 149 case EVFSNABS: ret = XA; break; 150 case EVFSNEG: ret = XA; break; 151 case EVFSSUB: ret = AB; break; 152 153 case EFDABS: ret = XA; break; 154 case EFDADD: ret = AB; break; 155 case EFDCFS: ret = XB; break; 156 case EFDCMPEQ: ret = XCR; break; 157 case EFDCMPGT: ret = XCR; break; 158 case EFDCMPLT: ret = XCR; break; 159 case EFDCTSF: ret = XB; break; 160 case EFDCTSI: ret = XB; break; 161 case EFDCTSIDZ: ret = XB; break; 162 case EFDCTSIZ: ret = XB; break; 163 case EFDCTUF: ret = XB; break; 164 case EFDCTUI: ret = XB; break; 165 case EFDCTUIDZ: ret = XB; break; 166 case EFDCTUIZ: ret = XB; break; 167 case EFDDIV: ret = AB; break; 168 case EFDMUL: ret = AB; break; 169 case EFDNABS: ret = XA; break; 170 case EFDNEG: ret = XA; break; 171 case EFDSUB: ret = AB; break; 172 } 173 174 return ret; 175 } 176 177 int do_spe_mathemu(struct pt_regs *regs) 178 { 179 FP_DECL_EX; 180 int IR, cmp; 181 182 unsigned long type, func, fc, fa, fb, src, speinsn; 183 union dw_union vc, va, vb; 184 185 if (get_user(speinsn, (unsigned int __user *) regs->nip)) 186 return -EFAULT; 187 if ((speinsn >> 26) != EFAPU) 188 return -EINVAL; /* not an spe instruction */ 189 190 type = insn_type(speinsn); 191 if (type == NOTYPE) 192 goto illegal; 193 194 func = speinsn & 0x7ff; 195 fc = (speinsn >> 21) & 0x1f; 196 fa = (speinsn >> 16) & 0x1f; 197 fb = (speinsn >> 11) & 0x1f; 198 src = (speinsn >> 5) & 0x7; 199 200 vc.wp[0] = current->thread.evr[fc]; 201 vc.wp[1] = regs->gpr[fc]; 202 va.wp[0] = current->thread.evr[fa]; 203 va.wp[1] = regs->gpr[fa]; 204 vb.wp[0] = current->thread.evr[fb]; 205 vb.wp[1] = regs->gpr[fb]; 206 207 __FPU_FPSCR = mfspr(SPRN_SPEFSCR); 208 209 pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); 210 pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); 211 pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]); 212 pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); 213 214 switch (src) { 215 case SPFP: { 216 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 217 218 switch (type) { 219 case AB: 220 case XCR: 221 FP_UNPACK_SP(SA, va.wp + 1); 222 fallthrough; 223 case XB: 224 FP_UNPACK_SP(SB, vb.wp + 1); 225 break; 226 case XA: 227 FP_UNPACK_SP(SA, va.wp + 1); 228 break; 229 } 230 231 pr_debug("SA: %d %08x %d (%d)\n", SA_s, SA_f, SA_e, SA_c); 232 pr_debug("SB: %d %08x %d (%d)\n", SB_s, SB_f, SB_e, SB_c); 233 234 switch (func) { 235 case EFSABS: 236 vc.wp[1] = va.wp[1] & ~SIGN_BIT_S; 237 goto update_regs; 238 239 case EFSNABS: 240 vc.wp[1] = va.wp[1] | SIGN_BIT_S; 241 goto update_regs; 242 243 case EFSNEG: 244 vc.wp[1] = va.wp[1] ^ SIGN_BIT_S; 245 goto update_regs; 246 247 case EFSADD: 248 FP_ADD_S(SR, SA, SB); 249 goto pack_s; 250 251 case EFSSUB: 252 FP_SUB_S(SR, SA, SB); 253 goto pack_s; 254 255 case EFSMUL: 256 FP_MUL_S(SR, SA, SB); 257 goto pack_s; 258 259 case EFSDIV: 260 FP_DIV_S(SR, SA, SB); 261 goto pack_s; 262 263 case EFSCMPEQ: 264 cmp = 0; 265 goto cmp_s; 266 267 case EFSCMPGT: 268 cmp = 1; 269 goto cmp_s; 270 271 case EFSCMPLT: 272 cmp = -1; 273 goto cmp_s; 274 275 case EFSCTSF: 276 case EFSCTUF: 277 if (SB_c == FP_CLS_NAN) { 278 vc.wp[1] = 0; 279 FP_SET_EXCEPTION(FP_EX_INVALID); 280 } else { 281 SB_e += (func == EFSCTSF ? 31 : 32); 282 FP_TO_INT_ROUND_S(vc.wp[1], SB, 32, 283 (func == EFSCTSF) ? 1 : 0); 284 } 285 goto update_regs; 286 287 case EFSCFD: { 288 FP_DECL_D(DB); 289 FP_CLEAR_EXCEPTIONS; 290 FP_UNPACK_DP(DB, vb.dp); 291 292 pr_debug("DB: %d %08x %08x %d (%d)\n", 293 DB_s, DB_f1, DB_f0, DB_e, DB_c); 294 295 FP_CONV(S, D, 1, 2, SR, DB); 296 goto pack_s; 297 } 298 299 case EFSCTSI: 300 case EFSCTUI: 301 if (SB_c == FP_CLS_NAN) { 302 vc.wp[1] = 0; 303 FP_SET_EXCEPTION(FP_EX_INVALID); 304 } else { 305 FP_TO_INT_ROUND_S(vc.wp[1], SB, 32, 306 ((func & 0x3) != 0) ? 1 : 0); 307 } 308 goto update_regs; 309 310 case EFSCTSIZ: 311 case EFSCTUIZ: 312 if (SB_c == FP_CLS_NAN) { 313 vc.wp[1] = 0; 314 FP_SET_EXCEPTION(FP_EX_INVALID); 315 } else { 316 FP_TO_INT_S(vc.wp[1], SB, 32, 317 ((func & 0x3) != 0) ? 1 : 0); 318 } 319 goto update_regs; 320 321 default: 322 goto illegal; 323 } 324 break; 325 326 pack_s: 327 pr_debug("SR: %d %08x %d (%d)\n", SR_s, SR_f, SR_e, SR_c); 328 329 FP_PACK_SP(vc.wp + 1, SR); 330 goto update_regs; 331 332 cmp_s: 333 FP_CMP_S(IR, SA, SB, 3); 334 if (IR == 3 && (FP_ISSIGNAN_S(SA) || FP_ISSIGNAN_S(SB))) 335 FP_SET_EXCEPTION(FP_EX_INVALID); 336 if (IR == cmp) { 337 IR = 0x4; 338 } else { 339 IR = 0; 340 } 341 goto update_ccr; 342 } 343 344 case DPFP: { 345 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 346 347 switch (type) { 348 case AB: 349 case XCR: 350 FP_UNPACK_DP(DA, va.dp); 351 fallthrough; 352 case XB: 353 FP_UNPACK_DP(DB, vb.dp); 354 break; 355 case XA: 356 FP_UNPACK_DP(DA, va.dp); 357 break; 358 } 359 360 pr_debug("DA: %d %08x %08x %d (%d)\n", 361 DA_s, DA_f1, DA_f0, DA_e, DA_c); 362 pr_debug("DB: %d %08x %08x %d (%d)\n", 363 DB_s, DB_f1, DB_f0, DB_e, DB_c); 364 365 switch (func) { 366 case EFDABS: 367 vc.dp[0] = va.dp[0] & ~SIGN_BIT_D; 368 goto update_regs; 369 370 case EFDNABS: 371 vc.dp[0] = va.dp[0] | SIGN_BIT_D; 372 goto update_regs; 373 374 case EFDNEG: 375 vc.dp[0] = va.dp[0] ^ SIGN_BIT_D; 376 goto update_regs; 377 378 case EFDADD: 379 FP_ADD_D(DR, DA, DB); 380 goto pack_d; 381 382 case EFDSUB: 383 FP_SUB_D(DR, DA, DB); 384 goto pack_d; 385 386 case EFDMUL: 387 FP_MUL_D(DR, DA, DB); 388 goto pack_d; 389 390 case EFDDIV: 391 FP_DIV_D(DR, DA, DB); 392 goto pack_d; 393 394 case EFDCMPEQ: 395 cmp = 0; 396 goto cmp_d; 397 398 case EFDCMPGT: 399 cmp = 1; 400 goto cmp_d; 401 402 case EFDCMPLT: 403 cmp = -1; 404 goto cmp_d; 405 406 case EFDCTSF: 407 case EFDCTUF: 408 if (DB_c == FP_CLS_NAN) { 409 vc.wp[1] = 0; 410 FP_SET_EXCEPTION(FP_EX_INVALID); 411 } else { 412 DB_e += (func == EFDCTSF ? 31 : 32); 413 FP_TO_INT_ROUND_D(vc.wp[1], DB, 32, 414 (func == EFDCTSF) ? 1 : 0); 415 } 416 goto update_regs; 417 418 case EFDCFS: { 419 FP_DECL_S(SB); 420 FP_CLEAR_EXCEPTIONS; 421 FP_UNPACK_SP(SB, vb.wp + 1); 422 423 pr_debug("SB: %d %08x %d (%d)\n", 424 SB_s, SB_f, SB_e, SB_c); 425 426 FP_CONV(D, S, 2, 1, DR, SB); 427 goto pack_d; 428 } 429 430 case EFDCTUIDZ: 431 case EFDCTSIDZ: 432 if (DB_c == FP_CLS_NAN) { 433 vc.dp[0] = 0; 434 FP_SET_EXCEPTION(FP_EX_INVALID); 435 } else { 436 FP_TO_INT_D(vc.dp[0], DB, 64, 437 ((func & 0x1) == 0) ? 1 : 0); 438 } 439 goto update_regs; 440 441 case EFDCTUI: 442 case EFDCTSI: 443 if (DB_c == FP_CLS_NAN) { 444 vc.wp[1] = 0; 445 FP_SET_EXCEPTION(FP_EX_INVALID); 446 } else { 447 FP_TO_INT_ROUND_D(vc.wp[1], DB, 32, 448 ((func & 0x3) != 0) ? 1 : 0); 449 } 450 goto update_regs; 451 452 case EFDCTUIZ: 453 case EFDCTSIZ: 454 if (DB_c == FP_CLS_NAN) { 455 vc.wp[1] = 0; 456 FP_SET_EXCEPTION(FP_EX_INVALID); 457 } else { 458 FP_TO_INT_D(vc.wp[1], DB, 32, 459 ((func & 0x3) != 0) ? 1 : 0); 460 } 461 goto update_regs; 462 463 default: 464 goto illegal; 465 } 466 break; 467 468 pack_d: 469 pr_debug("DR: %d %08x %08x %d (%d)\n", 470 DR_s, DR_f1, DR_f0, DR_e, DR_c); 471 472 FP_PACK_DP(vc.dp, DR); 473 goto update_regs; 474 475 cmp_d: 476 FP_CMP_D(IR, DA, DB, 3); 477 if (IR == 3 && (FP_ISSIGNAN_D(DA) || FP_ISSIGNAN_D(DB))) 478 FP_SET_EXCEPTION(FP_EX_INVALID); 479 if (IR == cmp) { 480 IR = 0x4; 481 } else { 482 IR = 0; 483 } 484 goto update_ccr; 485 486 } 487 488 case VCT: { 489 FP_DECL_S(SA0); FP_DECL_S(SB0); FP_DECL_S(SR0); 490 FP_DECL_S(SA1); FP_DECL_S(SB1); FP_DECL_S(SR1); 491 int IR0, IR1; 492 493 switch (type) { 494 case AB: 495 case XCR: 496 FP_UNPACK_SP(SA0, va.wp); 497 FP_UNPACK_SP(SA1, va.wp + 1); 498 fallthrough; 499 case XB: 500 FP_UNPACK_SP(SB0, vb.wp); 501 FP_UNPACK_SP(SB1, vb.wp + 1); 502 break; 503 case XA: 504 FP_UNPACK_SP(SA0, va.wp); 505 FP_UNPACK_SP(SA1, va.wp + 1); 506 break; 507 } 508 509 pr_debug("SA0: %d %08x %d (%d)\n", 510 SA0_s, SA0_f, SA0_e, SA0_c); 511 pr_debug("SA1: %d %08x %d (%d)\n", 512 SA1_s, SA1_f, SA1_e, SA1_c); 513 pr_debug("SB0: %d %08x %d (%d)\n", 514 SB0_s, SB0_f, SB0_e, SB0_c); 515 pr_debug("SB1: %d %08x %d (%d)\n", 516 SB1_s, SB1_f, SB1_e, SB1_c); 517 518 switch (func) { 519 case EVFSABS: 520 vc.wp[0] = va.wp[0] & ~SIGN_BIT_S; 521 vc.wp[1] = va.wp[1] & ~SIGN_BIT_S; 522 goto update_regs; 523 524 case EVFSNABS: 525 vc.wp[0] = va.wp[0] | SIGN_BIT_S; 526 vc.wp[1] = va.wp[1] | SIGN_BIT_S; 527 goto update_regs; 528 529 case EVFSNEG: 530 vc.wp[0] = va.wp[0] ^ SIGN_BIT_S; 531 vc.wp[1] = va.wp[1] ^ SIGN_BIT_S; 532 goto update_regs; 533 534 case EVFSADD: 535 FP_ADD_S(SR0, SA0, SB0); 536 FP_ADD_S(SR1, SA1, SB1); 537 goto pack_vs; 538 539 case EVFSSUB: 540 FP_SUB_S(SR0, SA0, SB0); 541 FP_SUB_S(SR1, SA1, SB1); 542 goto pack_vs; 543 544 case EVFSMUL: 545 FP_MUL_S(SR0, SA0, SB0); 546 FP_MUL_S(SR1, SA1, SB1); 547 goto pack_vs; 548 549 case EVFSDIV: 550 FP_DIV_S(SR0, SA0, SB0); 551 FP_DIV_S(SR1, SA1, SB1); 552 goto pack_vs; 553 554 case EVFSCMPEQ: 555 cmp = 0; 556 goto cmp_vs; 557 558 case EVFSCMPGT: 559 cmp = 1; 560 goto cmp_vs; 561 562 case EVFSCMPLT: 563 cmp = -1; 564 goto cmp_vs; 565 566 case EVFSCTUF: 567 case EVFSCTSF: 568 if (SB0_c == FP_CLS_NAN) { 569 vc.wp[0] = 0; 570 FP_SET_EXCEPTION(FP_EX_INVALID); 571 } else { 572 SB0_e += (func == EVFSCTSF ? 31 : 32); 573 FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32, 574 (func == EVFSCTSF) ? 1 : 0); 575 } 576 if (SB1_c == FP_CLS_NAN) { 577 vc.wp[1] = 0; 578 FP_SET_EXCEPTION(FP_EX_INVALID); 579 } else { 580 SB1_e += (func == EVFSCTSF ? 31 : 32); 581 FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32, 582 (func == EVFSCTSF) ? 1 : 0); 583 } 584 goto update_regs; 585 586 case EVFSCTUI: 587 case EVFSCTSI: 588 if (SB0_c == FP_CLS_NAN) { 589 vc.wp[0] = 0; 590 FP_SET_EXCEPTION(FP_EX_INVALID); 591 } else { 592 FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32, 593 ((func & 0x3) != 0) ? 1 : 0); 594 } 595 if (SB1_c == FP_CLS_NAN) { 596 vc.wp[1] = 0; 597 FP_SET_EXCEPTION(FP_EX_INVALID); 598 } else { 599 FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32, 600 ((func & 0x3) != 0) ? 1 : 0); 601 } 602 goto update_regs; 603 604 case EVFSCTUIZ: 605 case EVFSCTSIZ: 606 if (SB0_c == FP_CLS_NAN) { 607 vc.wp[0] = 0; 608 FP_SET_EXCEPTION(FP_EX_INVALID); 609 } else { 610 FP_TO_INT_S(vc.wp[0], SB0, 32, 611 ((func & 0x3) != 0) ? 1 : 0); 612 } 613 if (SB1_c == FP_CLS_NAN) { 614 vc.wp[1] = 0; 615 FP_SET_EXCEPTION(FP_EX_INVALID); 616 } else { 617 FP_TO_INT_S(vc.wp[1], SB1, 32, 618 ((func & 0x3) != 0) ? 1 : 0); 619 } 620 goto update_regs; 621 622 default: 623 goto illegal; 624 } 625 break; 626 627 pack_vs: 628 pr_debug("SR0: %d %08x %d (%d)\n", 629 SR0_s, SR0_f, SR0_e, SR0_c); 630 pr_debug("SR1: %d %08x %d (%d)\n", 631 SR1_s, SR1_f, SR1_e, SR1_c); 632 633 FP_PACK_SP(vc.wp, SR0); 634 FP_PACK_SP(vc.wp + 1, SR1); 635 goto update_regs; 636 637 cmp_vs: 638 { 639 int ch, cl; 640 641 FP_CMP_S(IR0, SA0, SB0, 3); 642 FP_CMP_S(IR1, SA1, SB1, 3); 643 if (IR0 == 3 && (FP_ISSIGNAN_S(SA0) || FP_ISSIGNAN_S(SB0))) 644 FP_SET_EXCEPTION(FP_EX_INVALID); 645 if (IR1 == 3 && (FP_ISSIGNAN_S(SA1) || FP_ISSIGNAN_S(SB1))) 646 FP_SET_EXCEPTION(FP_EX_INVALID); 647 ch = (IR0 == cmp) ? 1 : 0; 648 cl = (IR1 == cmp) ? 1 : 0; 649 IR = (ch << 3) | (cl << 2) | ((ch | cl) << 1) | 650 ((ch & cl) << 0); 651 goto update_ccr; 652 } 653 } 654 default: 655 return -EINVAL; 656 } 657 658 update_ccr: 659 regs->ccr &= ~(15 << ((7 - ((speinsn >> 23) & 0x7)) << 2)); 660 regs->ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2)); 661 662 update_regs: 663 /* 664 * If the "invalid" exception sticky bit was set by the 665 * processor for non-finite input, but was not set before the 666 * instruction being emulated, clear it. Likewise for the 667 * "underflow" bit, which may have been set by the processor 668 * for exact underflow, not just inexact underflow when the 669 * flag should be set for IEEE 754 semantics. Other sticky 670 * exceptions will only be set by the processor when they are 671 * correct according to IEEE 754 semantics, and we must not 672 * clear sticky bits that were already set before the emulated 673 * instruction as they represent the user-visible sticky 674 * exception status. "inexact" traps to kernel are not 675 * required for IEEE semantics and are not enabled by default, 676 * so the "inexact" sticky bit may have been set by a previous 677 * instruction without the kernel being aware of it. 678 */ 679 __FPU_FPSCR 680 &= ~(FP_EX_INVALID | FP_EX_UNDERFLOW) | current->thread.spefscr_last; 681 __FPU_FPSCR |= (FP_CUR_EXCEPTIONS & FP_EX_MASK); 682 mtspr(SPRN_SPEFSCR, __FPU_FPSCR); 683 current->thread.spefscr_last = __FPU_FPSCR; 684 685 current->thread.evr[fc] = vc.wp[0]; 686 regs->gpr[fc] = vc.wp[1]; 687 688 pr_debug("ccr = %08lx\n", regs->ccr); 689 pr_debug("cur exceptions = %08x spefscr = %08lx\n", 690 FP_CUR_EXCEPTIONS, __FPU_FPSCR); 691 pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); 692 pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]); 693 pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); 694 695 if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) { 696 if ((FP_CUR_EXCEPTIONS & FP_EX_DIVZERO) 697 && (current->thread.fpexc_mode & PR_FP_EXC_DIV)) 698 return 1; 699 if ((FP_CUR_EXCEPTIONS & FP_EX_OVERFLOW) 700 && (current->thread.fpexc_mode & PR_FP_EXC_OVF)) 701 return 1; 702 if ((FP_CUR_EXCEPTIONS & FP_EX_UNDERFLOW) 703 && (current->thread.fpexc_mode & PR_FP_EXC_UND)) 704 return 1; 705 if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) 706 && (current->thread.fpexc_mode & PR_FP_EXC_RES)) 707 return 1; 708 if ((FP_CUR_EXCEPTIONS & FP_EX_INVALID) 709 && (current->thread.fpexc_mode & PR_FP_EXC_INV)) 710 return 1; 711 } 712 return 0; 713 714 illegal: 715 if (have_e500_cpu_a005_erratum) { 716 /* according to e500 cpu a005 erratum, reissue efp inst */ 717 regs_add_return_ip(regs, -4); 718 pr_debug("re-issue efp inst: %08lx\n", speinsn); 719 return 0; 720 } 721 722 printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn); 723 return -ENOSYS; 724 } 725 726 int speround_handler(struct pt_regs *regs) 727 { 728 union dw_union fgpr; 729 int s_lo, s_hi; 730 int lo_inexact, hi_inexact; 731 int fp_result; 732 unsigned long speinsn, type, fb, fc, fptype, func; 733 734 if (get_user(speinsn, (unsigned int __user *) regs->nip)) 735 return -EFAULT; 736 if ((speinsn >> 26) != 4) 737 return -EINVAL; /* not an spe instruction */ 738 739 func = speinsn & 0x7ff; 740 type = insn_type(func); 741 if (type == XCR) return -ENOSYS; 742 743 __FPU_FPSCR = mfspr(SPRN_SPEFSCR); 744 pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); 745 746 fptype = (speinsn >> 5) & 0x7; 747 748 /* No need to round if the result is exact */ 749 lo_inexact = __FPU_FPSCR & (SPEFSCR_FG | SPEFSCR_FX); 750 hi_inexact = __FPU_FPSCR & (SPEFSCR_FGH | SPEFSCR_FXH); 751 if (!(lo_inexact || (hi_inexact && fptype == VCT))) 752 return 0; 753 754 fc = (speinsn >> 21) & 0x1f; 755 s_lo = regs->gpr[fc] & SIGN_BIT_S; 756 s_hi = current->thread.evr[fc] & SIGN_BIT_S; 757 fgpr.wp[0] = current->thread.evr[fc]; 758 fgpr.wp[1] = regs->gpr[fc]; 759 760 fb = (speinsn >> 11) & 0x1f; 761 switch (func) { 762 case EFSCTUIZ: 763 case EFSCTSIZ: 764 case EVFSCTUIZ: 765 case EVFSCTSIZ: 766 case EFDCTUIDZ: 767 case EFDCTSIDZ: 768 case EFDCTUIZ: 769 case EFDCTSIZ: 770 /* 771 * These instructions always round to zero, 772 * independent of the rounding mode. 773 */ 774 return 0; 775 776 case EFSCTUI: 777 case EFSCTUF: 778 case EVFSCTUI: 779 case EVFSCTUF: 780 case EFDCTUI: 781 case EFDCTUF: 782 fp_result = 0; 783 s_lo = 0; 784 s_hi = 0; 785 break; 786 787 case EFSCTSI: 788 case EFSCTSF: 789 fp_result = 0; 790 /* Recover the sign of a zero result if possible. */ 791 if (fgpr.wp[1] == 0) 792 s_lo = regs->gpr[fb] & SIGN_BIT_S; 793 break; 794 795 case EVFSCTSI: 796 case EVFSCTSF: 797 fp_result = 0; 798 /* Recover the sign of a zero result if possible. */ 799 if (fgpr.wp[1] == 0) 800 s_lo = regs->gpr[fb] & SIGN_BIT_S; 801 if (fgpr.wp[0] == 0) 802 s_hi = current->thread.evr[fb] & SIGN_BIT_S; 803 break; 804 805 case EFDCTSI: 806 case EFDCTSF: 807 fp_result = 0; 808 s_hi = s_lo; 809 /* Recover the sign of a zero result if possible. */ 810 if (fgpr.wp[1] == 0) 811 s_hi = current->thread.evr[fb] & SIGN_BIT_S; 812 break; 813 814 default: 815 fp_result = 1; 816 break; 817 } 818 819 pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); 820 821 switch (fptype) { 822 /* Since SPE instructions on E500 core can handle round to nearest 823 * and round toward zero with IEEE-754 complied, we just need 824 * to handle round toward +Inf and round toward -Inf by software. 825 */ 826 case SPFP: 827 if ((FP_ROUNDMODE) == FP_RND_PINF) { 828 if (!s_lo) fgpr.wp[1]++; /* Z > 0, choose Z1 */ 829 } else { /* round to -Inf */ 830 if (s_lo) { 831 if (fp_result) 832 fgpr.wp[1]++; /* Z < 0, choose Z2 */ 833 else 834 fgpr.wp[1]--; /* Z < 0, choose Z2 */ 835 } 836 } 837 break; 838 839 case DPFP: 840 if (FP_ROUNDMODE == FP_RND_PINF) { 841 if (!s_hi) { 842 if (fp_result) 843 fgpr.dp[0]++; /* Z > 0, choose Z1 */ 844 else 845 fgpr.wp[1]++; /* Z > 0, choose Z1 */ 846 } 847 } else { /* round to -Inf */ 848 if (s_hi) { 849 if (fp_result) 850 fgpr.dp[0]++; /* Z < 0, choose Z2 */ 851 else 852 fgpr.wp[1]--; /* Z < 0, choose Z2 */ 853 } 854 } 855 break; 856 857 case VCT: 858 if (FP_ROUNDMODE == FP_RND_PINF) { 859 if (lo_inexact && !s_lo) 860 fgpr.wp[1]++; /* Z_low > 0, choose Z1 */ 861 if (hi_inexact && !s_hi) 862 fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */ 863 } else { /* round to -Inf */ 864 if (lo_inexact && s_lo) { 865 if (fp_result) 866 fgpr.wp[1]++; /* Z_low < 0, choose Z2 */ 867 else 868 fgpr.wp[1]--; /* Z_low < 0, choose Z2 */ 869 } 870 if (hi_inexact && s_hi) { 871 if (fp_result) 872 fgpr.wp[0]++; /* Z_high < 0, choose Z2 */ 873 else 874 fgpr.wp[0]--; /* Z_high < 0, choose Z2 */ 875 } 876 } 877 break; 878 879 default: 880 return -EINVAL; 881 } 882 883 current->thread.evr[fc] = fgpr.wp[0]; 884 regs->gpr[fc] = fgpr.wp[1]; 885 886 pr_debug(" to fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); 887 888 if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) 889 return (current->thread.fpexc_mode & PR_FP_EXC_RES) ? 1 : 0; 890 return 0; 891 } 892 893 static int __init spe_mathemu_init(void) 894 { 895 u32 pvr, maj, min; 896 897 pvr = mfspr(SPRN_PVR); 898 899 if ((PVR_VER(pvr) == PVR_VER_E500V1) || 900 (PVR_VER(pvr) == PVR_VER_E500V2)) { 901 maj = PVR_MAJ(pvr); 902 min = PVR_MIN(pvr); 903 904 /* 905 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1 906 * need cpu a005 errata workaround 907 */ 908 switch (maj) { 909 case 1: 910 if (min < 1) 911 have_e500_cpu_a005_erratum = 1; 912 break; 913 case 2: 914 if (min < 3) 915 have_e500_cpu_a005_erratum = 1; 916 break; 917 case 3: 918 case 4: 919 case 5: 920 if (min < 1) 921 have_e500_cpu_a005_erratum = 1; 922 break; 923 default: 924 break; 925 } 926 } 927 928 return 0; 929 } 930 931 module_init(spe_mathemu_init); 932