1 /* 2 * PowerPC floating point and SPE emulation helpers for QEMU. 3 * 4 * Copyright (c) 2003-2007 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #include "qemu/osdep.h" 20 #include "cpu.h" 21 #include "exec/helper-proto.h" 22 #include "exec/exec-all.h" 23 #include "internal.h" 24 #include "fpu/softfloat.h" 25 26 static inline float128 float128_snan_to_qnan(float128 x) 27 { 28 float128 r; 29 30 r.high = x.high | 0x0000800000000000; 31 r.low = x.low; 32 return r; 33 } 34 35 #define float64_snan_to_qnan(x) ((x) | 0x0008000000000000ULL) 36 #define float32_snan_to_qnan(x) ((x) | 0x00400000) 37 #define float16_snan_to_qnan(x) ((x) | 0x0200) 38 39 /*****************************************************************************/ 40 /* Floating point operations helpers */ 41 uint64_t helper_float32_to_float64(CPUPPCState *env, uint32_t arg) 42 { 43 CPU_FloatU f; 44 CPU_DoubleU d; 45 46 f.l = arg; 47 d.d = float32_to_float64(f.f, &env->fp_status); 48 return d.ll; 49 } 50 51 uint32_t helper_float64_to_float32(CPUPPCState *env, uint64_t arg) 52 { 53 CPU_FloatU f; 54 CPU_DoubleU d; 55 56 d.ll = arg; 57 f.f = float64_to_float32(d.d, &env->fp_status); 58 return f.l; 59 } 60 61 static inline int ppc_float32_get_unbiased_exp(float32 f) 62 { 63 return ((f >> 23) & 0xFF) - 127; 64 } 65 66 static inline int ppc_float64_get_unbiased_exp(float64 f) 67 { 68 return ((f >> 52) & 0x7FF) - 1023; 69 } 70 71 #define COMPUTE_FPRF(tp) \ 72 void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \ 73 { \ 74 int isneg; \ 75 int fprf; \ 76 \ 77 isneg = tp##_is_neg(arg); \ 78 if (unlikely(tp##_is_any_nan(arg))) { \ 79 if (tp##_is_signaling_nan(arg, &env->fp_status)) { \ 80 /* Signaling NaN: flags are undefined */ \ 81 fprf = 0x00; \ 82 } else { \ 83 /* Quiet NaN */ \ 84 fprf = 0x11; \ 85 } \ 86 } else if (unlikely(tp##_is_infinity(arg))) { \ 87 /* +/- infinity */ \ 88 if (isneg) { \ 89 fprf = 0x09; \ 90 } else { \ 91 fprf = 0x05; \ 92 } \ 93 } else { \ 94 if (tp##_is_zero(arg)) { \ 95 /* +/- zero */ \ 96 if (isneg) { \ 97 fprf = 0x12; \ 98 } else { \ 99 fprf = 0x02; \ 100 } \ 101 } else { \ 102 if (tp##_is_zero_or_denormal(arg)) { \ 103 /* Denormalized numbers */ \ 104 fprf = 0x10; \ 105 } else { \ 106 /* Normalized numbers */ \ 107 fprf = 0x00; \ 108 } \ 109 if (isneg) { \ 110 fprf |= 0x08; \ 111 } else { \ 112 fprf |= 0x04; \ 113 } \ 114 } \ 115 } \ 116 /* We update FPSCR_FPRF */ \ 117 env->fpscr &= ~(0x1F << FPSCR_FPRF); \ 118 env->fpscr |= fprf << FPSCR_FPRF; \ 119 } 120 121 COMPUTE_FPRF(float16) 122 COMPUTE_FPRF(float32) 123 COMPUTE_FPRF(float64) 124 COMPUTE_FPRF(float128) 125 126 /* Floating-point invalid operations exception */ 127 static inline __attribute__((__always_inline__)) 128 uint64_t float_invalid_op_excp(CPUPPCState *env, int op, int set_fpcc) 129 { 130 CPUState *cs = CPU(ppc_env_get_cpu(env)); 131 uint64_t ret = 0; 132 int ve; 133 134 ve = fpscr_ve; 135 switch (op) { 136 case POWERPC_EXCP_FP_VXSNAN: 137 env->fpscr |= 1 << FPSCR_VXSNAN; 138 break; 139 case POWERPC_EXCP_FP_VXSOFT: 140 env->fpscr |= 1 << FPSCR_VXSOFT; 141 break; 142 case POWERPC_EXCP_FP_VXISI: 143 /* Magnitude subtraction of infinities */ 144 env->fpscr |= 1 << FPSCR_VXISI; 145 goto update_arith; 146 case POWERPC_EXCP_FP_VXIDI: 147 /* Division of infinity by infinity */ 148 env->fpscr |= 1 << FPSCR_VXIDI; 149 goto update_arith; 150 case POWERPC_EXCP_FP_VXZDZ: 151 /* Division of zero by zero */ 152 env->fpscr |= 1 << FPSCR_VXZDZ; 153 goto update_arith; 154 case POWERPC_EXCP_FP_VXIMZ: 155 /* Multiplication of zero by infinity */ 156 env->fpscr |= 1 << FPSCR_VXIMZ; 157 goto update_arith; 158 case POWERPC_EXCP_FP_VXVC: 159 /* Ordered comparison of NaN */ 160 env->fpscr |= 1 << FPSCR_VXVC; 161 if (set_fpcc) { 162 env->fpscr &= ~(0xF << FPSCR_FPCC); 163 env->fpscr |= 0x11 << FPSCR_FPCC; 164 } 165 /* We must update the target FPR before raising the exception */ 166 if (ve != 0) { 167 cs->exception_index = POWERPC_EXCP_PROGRAM; 168 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC; 169 /* Update the floating-point enabled exception summary */ 170 env->fpscr |= 1 << FPSCR_FEX; 171 /* Exception is differed */ 172 ve = 0; 173 } 174 break; 175 case POWERPC_EXCP_FP_VXSQRT: 176 /* Square root of a negative number */ 177 env->fpscr |= 1 << FPSCR_VXSQRT; 178 update_arith: 179 env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI)); 180 if (ve == 0) { 181 /* Set the result to quiet NaN */ 182 ret = 0x7FF8000000000000ULL; 183 if (set_fpcc) { 184 env->fpscr &= ~(0xF << FPSCR_FPCC); 185 env->fpscr |= 0x11 << FPSCR_FPCC; 186 } 187 } 188 break; 189 case POWERPC_EXCP_FP_VXCVI: 190 /* Invalid conversion */ 191 env->fpscr |= 1 << FPSCR_VXCVI; 192 env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI)); 193 if (ve == 0) { 194 /* Set the result to quiet NaN */ 195 ret = 0x7FF8000000000000ULL; 196 if (set_fpcc) { 197 env->fpscr &= ~(0xF << FPSCR_FPCC); 198 env->fpscr |= 0x11 << FPSCR_FPCC; 199 } 200 } 201 break; 202 } 203 /* Update the floating-point invalid operation summary */ 204 env->fpscr |= 1 << FPSCR_VX; 205 /* Update the floating-point exception summary */ 206 env->fpscr |= FP_FX; 207 if (ve != 0) { 208 /* Update the floating-point enabled exception summary */ 209 env->fpscr |= 1 << FPSCR_FEX; 210 if (msr_fe0 != 0 || msr_fe1 != 0) { 211 /* GETPC() works here because this is inline */ 212 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 213 POWERPC_EXCP_FP | op, GETPC()); 214 } 215 } 216 return ret; 217 } 218 219 static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr) 220 { 221 env->fpscr |= 1 << FPSCR_ZX; 222 env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI)); 223 /* Update the floating-point exception summary */ 224 env->fpscr |= FP_FX; 225 if (fpscr_ze != 0) { 226 /* Update the floating-point enabled exception summary */ 227 env->fpscr |= 1 << FPSCR_FEX; 228 if (msr_fe0 != 0 || msr_fe1 != 0) { 229 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 230 POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX, 231 raddr); 232 } 233 } 234 } 235 236 static inline void float_overflow_excp(CPUPPCState *env) 237 { 238 CPUState *cs = CPU(ppc_env_get_cpu(env)); 239 240 env->fpscr |= 1 << FPSCR_OX; 241 /* Update the floating-point exception summary */ 242 env->fpscr |= FP_FX; 243 if (fpscr_oe != 0) { 244 /* XXX: should adjust the result */ 245 /* Update the floating-point enabled exception summary */ 246 env->fpscr |= 1 << FPSCR_FEX; 247 /* We must update the target FPR before raising the exception */ 248 cs->exception_index = POWERPC_EXCP_PROGRAM; 249 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX; 250 } else { 251 env->fpscr |= 1 << FPSCR_XX; 252 env->fpscr |= 1 << FPSCR_FI; 253 } 254 } 255 256 static inline void float_underflow_excp(CPUPPCState *env) 257 { 258 CPUState *cs = CPU(ppc_env_get_cpu(env)); 259 260 env->fpscr |= 1 << FPSCR_UX; 261 /* Update the floating-point exception summary */ 262 env->fpscr |= FP_FX; 263 if (fpscr_ue != 0) { 264 /* XXX: should adjust the result */ 265 /* Update the floating-point enabled exception summary */ 266 env->fpscr |= 1 << FPSCR_FEX; 267 /* We must update the target FPR before raising the exception */ 268 cs->exception_index = POWERPC_EXCP_PROGRAM; 269 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX; 270 } 271 } 272 273 static inline void float_inexact_excp(CPUPPCState *env) 274 { 275 CPUState *cs = CPU(ppc_env_get_cpu(env)); 276 277 env->fpscr |= 1 << FPSCR_FI; 278 env->fpscr |= 1 << FPSCR_XX; 279 /* Update the floating-point exception summary */ 280 env->fpscr |= FP_FX; 281 if (fpscr_xe != 0) { 282 /* Update the floating-point enabled exception summary */ 283 env->fpscr |= 1 << FPSCR_FEX; 284 /* We must update the target FPR before raising the exception */ 285 cs->exception_index = POWERPC_EXCP_PROGRAM; 286 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX; 287 } 288 } 289 290 static inline void fpscr_set_rounding_mode(CPUPPCState *env) 291 { 292 int rnd_type; 293 294 /* Set rounding mode */ 295 switch (fpscr_rn) { 296 case 0: 297 /* Best approximation (round to nearest) */ 298 rnd_type = float_round_nearest_even; 299 break; 300 case 1: 301 /* Smaller magnitude (round toward zero) */ 302 rnd_type = float_round_to_zero; 303 break; 304 case 2: 305 /* Round toward +infinite */ 306 rnd_type = float_round_up; 307 break; 308 default: 309 case 3: 310 /* Round toward -infinite */ 311 rnd_type = float_round_down; 312 break; 313 } 314 set_float_rounding_mode(rnd_type, &env->fp_status); 315 } 316 317 void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit) 318 { 319 int prev; 320 321 prev = (env->fpscr >> bit) & 1; 322 env->fpscr &= ~(1 << bit); 323 if (prev == 1) { 324 switch (bit) { 325 case FPSCR_RN1: 326 case FPSCR_RN: 327 fpscr_set_rounding_mode(env); 328 break; 329 case FPSCR_VXSNAN: 330 case FPSCR_VXISI: 331 case FPSCR_VXIDI: 332 case FPSCR_VXZDZ: 333 case FPSCR_VXIMZ: 334 case FPSCR_VXVC: 335 case FPSCR_VXSOFT: 336 case FPSCR_VXSQRT: 337 case FPSCR_VXCVI: 338 if (!fpscr_ix) { 339 /* Set VX bit to zero */ 340 env->fpscr &= ~(1 << FPSCR_VX); 341 } 342 break; 343 case FPSCR_OX: 344 case FPSCR_UX: 345 case FPSCR_ZX: 346 case FPSCR_XX: 347 case FPSCR_VE: 348 case FPSCR_OE: 349 case FPSCR_UE: 350 case FPSCR_ZE: 351 case FPSCR_XE: 352 if (!fpscr_eex) { 353 /* Set the FEX bit */ 354 env->fpscr &= ~(1 << FPSCR_FEX); 355 } 356 break; 357 default: 358 break; 359 } 360 } 361 } 362 363 void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit) 364 { 365 CPUState *cs = CPU(ppc_env_get_cpu(env)); 366 int prev; 367 368 prev = (env->fpscr >> bit) & 1; 369 env->fpscr |= 1 << bit; 370 if (prev == 0) { 371 switch (bit) { 372 case FPSCR_VX: 373 env->fpscr |= FP_FX; 374 if (fpscr_ve) { 375 goto raise_ve; 376 } 377 break; 378 case FPSCR_OX: 379 env->fpscr |= FP_FX; 380 if (fpscr_oe) { 381 goto raise_oe; 382 } 383 break; 384 case FPSCR_UX: 385 env->fpscr |= FP_FX; 386 if (fpscr_ue) { 387 goto raise_ue; 388 } 389 break; 390 case FPSCR_ZX: 391 env->fpscr |= FP_FX; 392 if (fpscr_ze) { 393 goto raise_ze; 394 } 395 break; 396 case FPSCR_XX: 397 env->fpscr |= FP_FX; 398 if (fpscr_xe) { 399 goto raise_xe; 400 } 401 break; 402 case FPSCR_VXSNAN: 403 case FPSCR_VXISI: 404 case FPSCR_VXIDI: 405 case FPSCR_VXZDZ: 406 case FPSCR_VXIMZ: 407 case FPSCR_VXVC: 408 case FPSCR_VXSOFT: 409 case FPSCR_VXSQRT: 410 case FPSCR_VXCVI: 411 env->fpscr |= 1 << FPSCR_VX; 412 env->fpscr |= FP_FX; 413 if (fpscr_ve != 0) { 414 goto raise_ve; 415 } 416 break; 417 case FPSCR_VE: 418 if (fpscr_vx != 0) { 419 raise_ve: 420 env->error_code = POWERPC_EXCP_FP; 421 if (fpscr_vxsnan) { 422 env->error_code |= POWERPC_EXCP_FP_VXSNAN; 423 } 424 if (fpscr_vxisi) { 425 env->error_code |= POWERPC_EXCP_FP_VXISI; 426 } 427 if (fpscr_vxidi) { 428 env->error_code |= POWERPC_EXCP_FP_VXIDI; 429 } 430 if (fpscr_vxzdz) { 431 env->error_code |= POWERPC_EXCP_FP_VXZDZ; 432 } 433 if (fpscr_vximz) { 434 env->error_code |= POWERPC_EXCP_FP_VXIMZ; 435 } 436 if (fpscr_vxvc) { 437 env->error_code |= POWERPC_EXCP_FP_VXVC; 438 } 439 if (fpscr_vxsoft) { 440 env->error_code |= POWERPC_EXCP_FP_VXSOFT; 441 } 442 if (fpscr_vxsqrt) { 443 env->error_code |= POWERPC_EXCP_FP_VXSQRT; 444 } 445 if (fpscr_vxcvi) { 446 env->error_code |= POWERPC_EXCP_FP_VXCVI; 447 } 448 goto raise_excp; 449 } 450 break; 451 case FPSCR_OE: 452 if (fpscr_ox != 0) { 453 raise_oe: 454 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX; 455 goto raise_excp; 456 } 457 break; 458 case FPSCR_UE: 459 if (fpscr_ux != 0) { 460 raise_ue: 461 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX; 462 goto raise_excp; 463 } 464 break; 465 case FPSCR_ZE: 466 if (fpscr_zx != 0) { 467 raise_ze: 468 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX; 469 goto raise_excp; 470 } 471 break; 472 case FPSCR_XE: 473 if (fpscr_xx != 0) { 474 raise_xe: 475 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX; 476 goto raise_excp; 477 } 478 break; 479 case FPSCR_RN1: 480 case FPSCR_RN: 481 fpscr_set_rounding_mode(env); 482 break; 483 default: 484 break; 485 raise_excp: 486 /* Update the floating-point enabled exception summary */ 487 env->fpscr |= 1 << FPSCR_FEX; 488 /* We have to update Rc1 before raising the exception */ 489 cs->exception_index = POWERPC_EXCP_PROGRAM; 490 break; 491 } 492 } 493 } 494 495 void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask) 496 { 497 CPUState *cs = CPU(ppc_env_get_cpu(env)); 498 target_ulong prev, new; 499 int i; 500 501 prev = env->fpscr; 502 new = (target_ulong)arg; 503 new &= ~0x60000000LL; 504 new |= prev & 0x60000000LL; 505 for (i = 0; i < sizeof(target_ulong) * 2; i++) { 506 if (mask & (1 << i)) { 507 env->fpscr &= ~(0xFLL << (4 * i)); 508 env->fpscr |= new & (0xFLL << (4 * i)); 509 } 510 } 511 /* Update VX and FEX */ 512 if (fpscr_ix != 0) { 513 env->fpscr |= 1 << FPSCR_VX; 514 } else { 515 env->fpscr &= ~(1 << FPSCR_VX); 516 } 517 if ((fpscr_ex & fpscr_eex) != 0) { 518 env->fpscr |= 1 << FPSCR_FEX; 519 cs->exception_index = POWERPC_EXCP_PROGRAM; 520 /* XXX: we should compute it properly */ 521 env->error_code = POWERPC_EXCP_FP; 522 } else { 523 env->fpscr &= ~(1 << FPSCR_FEX); 524 } 525 fpscr_set_rounding_mode(env); 526 } 527 528 void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask) 529 { 530 helper_store_fpscr(env, arg, mask); 531 } 532 533 static void do_float_check_status(CPUPPCState *env, uintptr_t raddr) 534 { 535 CPUState *cs = CPU(ppc_env_get_cpu(env)); 536 int status = get_float_exception_flags(&env->fp_status); 537 bool inexact_happened = false; 538 539 if (status & float_flag_divbyzero) { 540 float_zero_divide_excp(env, raddr); 541 } else if (status & float_flag_overflow) { 542 float_overflow_excp(env); 543 } else if (status & float_flag_underflow) { 544 float_underflow_excp(env); 545 } else if (status & float_flag_inexact) { 546 float_inexact_excp(env); 547 inexact_happened = true; 548 } 549 550 /* if the inexact flag was not set */ 551 if (inexact_happened == false) { 552 env->fpscr &= ~(1 << FPSCR_FI); /* clear the FPSCR[FI] bit */ 553 } 554 555 if (cs->exception_index == POWERPC_EXCP_PROGRAM && 556 (env->error_code & POWERPC_EXCP_FP)) { 557 /* Differred floating-point exception after target FPR update */ 558 if (msr_fe0 != 0 || msr_fe1 != 0) { 559 raise_exception_err_ra(env, cs->exception_index, 560 env->error_code, raddr); 561 } 562 } 563 } 564 565 static inline __attribute__((__always_inline__)) 566 void float_check_status(CPUPPCState *env) 567 { 568 /* GETPC() works here because this is inline */ 569 do_float_check_status(env, GETPC()); 570 } 571 572 void helper_float_check_status(CPUPPCState *env) 573 { 574 do_float_check_status(env, GETPC()); 575 } 576 577 void helper_reset_fpstatus(CPUPPCState *env) 578 { 579 set_float_exception_flags(0, &env->fp_status); 580 } 581 582 /* fadd - fadd. */ 583 uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2) 584 { 585 CPU_DoubleU farg1, farg2; 586 587 farg1.ll = arg1; 588 farg2.ll = arg2; 589 590 if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) && 591 float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) { 592 /* Magnitude subtraction of infinities */ 593 farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); 594 } else { 595 if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || 596 float64_is_signaling_nan(farg2.d, &env->fp_status))) { 597 /* sNaN addition */ 598 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 599 } 600 farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); 601 } 602 603 return farg1.ll; 604 } 605 606 /* fsub - fsub. */ 607 uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2) 608 { 609 CPU_DoubleU farg1, farg2; 610 611 farg1.ll = arg1; 612 farg2.ll = arg2; 613 614 if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) && 615 float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) { 616 /* Magnitude subtraction of infinities */ 617 farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); 618 } else { 619 if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || 620 float64_is_signaling_nan(farg2.d, &env->fp_status))) { 621 /* sNaN subtraction */ 622 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 623 } 624 farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status); 625 } 626 627 return farg1.ll; 628 } 629 630 /* fmul - fmul. */ 631 uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2) 632 { 633 CPU_DoubleU farg1, farg2; 634 635 farg1.ll = arg1; 636 farg2.ll = arg2; 637 638 if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) || 639 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { 640 /* Multiplication of zero by infinity */ 641 farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); 642 } else { 643 if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || 644 float64_is_signaling_nan(farg2.d, &env->fp_status))) { 645 /* sNaN multiplication */ 646 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 647 } 648 farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); 649 } 650 651 return farg1.ll; 652 } 653 654 /* fdiv - fdiv. */ 655 uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2) 656 { 657 CPU_DoubleU farg1, farg2; 658 659 farg1.ll = arg1; 660 farg2.ll = arg2; 661 662 if (unlikely(float64_is_infinity(farg1.d) && 663 float64_is_infinity(farg2.d))) { 664 /* Division of infinity by infinity */ 665 farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1); 666 } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) { 667 /* Division of zero by zero */ 668 farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1); 669 } else { 670 if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || 671 float64_is_signaling_nan(farg2.d, &env->fp_status))) { 672 /* sNaN division */ 673 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 674 } 675 farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status); 676 } 677 678 return farg1.ll; 679 } 680 681 682 #define FPU_FCTI(op, cvt, nanval) \ 683 uint64_t helper_##op(CPUPPCState *env, uint64_t arg) \ 684 { \ 685 CPU_DoubleU farg; \ 686 \ 687 farg.ll = arg; \ 688 farg.ll = float64_to_##cvt(farg.d, &env->fp_status); \ 689 \ 690 if (unlikely(env->fp_status.float_exception_flags)) { \ 691 if (float64_is_any_nan(arg)) { \ 692 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1); \ 693 if (float64_is_signaling_nan(arg, &env->fp_status)) { \ 694 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \ 695 } \ 696 farg.ll = nanval; \ 697 } else if (env->fp_status.float_exception_flags & \ 698 float_flag_invalid) { \ 699 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1); \ 700 } \ 701 float_check_status(env); \ 702 } \ 703 return farg.ll; \ 704 } 705 706 FPU_FCTI(fctiw, int32, 0x80000000U) 707 FPU_FCTI(fctiwz, int32_round_to_zero, 0x80000000U) 708 FPU_FCTI(fctiwu, uint32, 0x00000000U) 709 FPU_FCTI(fctiwuz, uint32_round_to_zero, 0x00000000U) 710 FPU_FCTI(fctid, int64, 0x8000000000000000ULL) 711 FPU_FCTI(fctidz, int64_round_to_zero, 0x8000000000000000ULL) 712 FPU_FCTI(fctidu, uint64, 0x0000000000000000ULL) 713 FPU_FCTI(fctiduz, uint64_round_to_zero, 0x0000000000000000ULL) 714 715 #define FPU_FCFI(op, cvtr, is_single) \ 716 uint64_t helper_##op(CPUPPCState *env, uint64_t arg) \ 717 { \ 718 CPU_DoubleU farg; \ 719 \ 720 if (is_single) { \ 721 float32 tmp = cvtr(arg, &env->fp_status); \ 722 farg.d = float32_to_float64(tmp, &env->fp_status); \ 723 } else { \ 724 farg.d = cvtr(arg, &env->fp_status); \ 725 } \ 726 float_check_status(env); \ 727 return farg.ll; \ 728 } 729 730 FPU_FCFI(fcfid, int64_to_float64, 0) 731 FPU_FCFI(fcfids, int64_to_float32, 1) 732 FPU_FCFI(fcfidu, uint64_to_float64, 0) 733 FPU_FCFI(fcfidus, uint64_to_float32, 1) 734 735 static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg, 736 int rounding_mode) 737 { 738 CPU_DoubleU farg; 739 740 farg.ll = arg; 741 742 if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { 743 /* sNaN round */ 744 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 745 farg.ll = arg | 0x0008000000000000ULL; 746 } else { 747 int inexact = get_float_exception_flags(&env->fp_status) & 748 float_flag_inexact; 749 set_float_rounding_mode(rounding_mode, &env->fp_status); 750 farg.ll = float64_round_to_int(farg.d, &env->fp_status); 751 /* Restore rounding mode from FPSCR */ 752 fpscr_set_rounding_mode(env); 753 754 /* fri* does not set FPSCR[XX] */ 755 if (!inexact) { 756 env->fp_status.float_exception_flags &= ~float_flag_inexact; 757 } 758 } 759 float_check_status(env); 760 return farg.ll; 761 } 762 763 uint64_t helper_frin(CPUPPCState *env, uint64_t arg) 764 { 765 return do_fri(env, arg, float_round_ties_away); 766 } 767 768 uint64_t helper_friz(CPUPPCState *env, uint64_t arg) 769 { 770 return do_fri(env, arg, float_round_to_zero); 771 } 772 773 uint64_t helper_frip(CPUPPCState *env, uint64_t arg) 774 { 775 return do_fri(env, arg, float_round_up); 776 } 777 778 uint64_t helper_frim(CPUPPCState *env, uint64_t arg) 779 { 780 return do_fri(env, arg, float_round_down); 781 } 782 783 #define FPU_MADDSUB_UPDATE(NAME, TP) \ 784 static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3, \ 785 unsigned int madd_flags) \ 786 { \ 787 if (TP##_is_signaling_nan(arg1, &env->fp_status) || \ 788 TP##_is_signaling_nan(arg2, &env->fp_status) || \ 789 TP##_is_signaling_nan(arg3, &env->fp_status)) { \ 790 /* sNaN operation */ \ 791 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \ 792 } \ 793 if ((TP##_is_infinity(arg1) && TP##_is_zero(arg2)) || \ 794 (TP##_is_zero(arg1) && TP##_is_infinity(arg2))) { \ 795 /* Multiplication of zero by infinity */ \ 796 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); \ 797 } \ 798 if ((TP##_is_infinity(arg1) || TP##_is_infinity(arg2)) && \ 799 TP##_is_infinity(arg3)) { \ 800 uint8_t aSign, bSign, cSign; \ 801 \ 802 aSign = TP##_is_neg(arg1); \ 803 bSign = TP##_is_neg(arg2); \ 804 cSign = TP##_is_neg(arg3); \ 805 if (madd_flags & float_muladd_negate_c) { \ 806 cSign ^= 1; \ 807 } \ 808 if (aSign ^ bSign ^ cSign) { \ 809 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); \ 810 } \ 811 } \ 812 } 813 FPU_MADDSUB_UPDATE(float32_maddsub_update_excp, float32) 814 FPU_MADDSUB_UPDATE(float64_maddsub_update_excp, float64) 815 816 #define FPU_FMADD(op, madd_flags) \ 817 uint64_t helper_##op(CPUPPCState *env, uint64_t arg1, \ 818 uint64_t arg2, uint64_t arg3) \ 819 { \ 820 uint32_t flags; \ 821 float64 ret = float64_muladd(arg1, arg2, arg3, madd_flags, \ 822 &env->fp_status); \ 823 flags = get_float_exception_flags(&env->fp_status); \ 824 if (flags) { \ 825 if (flags & float_flag_invalid) { \ 826 float64_maddsub_update_excp(env, arg1, arg2, arg3, \ 827 madd_flags); \ 828 } \ 829 float_check_status(env); \ 830 } \ 831 return ret; \ 832 } 833 834 #define MADD_FLGS 0 835 #define MSUB_FLGS float_muladd_negate_c 836 #define NMADD_FLGS float_muladd_negate_result 837 #define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result) 838 839 FPU_FMADD(fmadd, MADD_FLGS) 840 FPU_FMADD(fnmadd, NMADD_FLGS) 841 FPU_FMADD(fmsub, MSUB_FLGS) 842 FPU_FMADD(fnmsub, NMSUB_FLGS) 843 844 /* frsp - frsp. */ 845 uint64_t helper_frsp(CPUPPCState *env, uint64_t arg) 846 { 847 CPU_DoubleU farg; 848 float32 f32; 849 850 farg.ll = arg; 851 852 if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { 853 /* sNaN square root */ 854 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 855 } 856 f32 = float64_to_float32(farg.d, &env->fp_status); 857 farg.d = float32_to_float64(f32, &env->fp_status); 858 859 return farg.ll; 860 } 861 862 /* fsqrt - fsqrt. */ 863 uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg) 864 { 865 CPU_DoubleU farg; 866 867 farg.ll = arg; 868 869 if (unlikely(float64_is_any_nan(farg.d))) { 870 if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { 871 /* sNaN reciprocal square root */ 872 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 873 farg.ll = float64_snan_to_qnan(farg.ll); 874 } 875 } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) { 876 /* Square root of a negative nonzero number */ 877 farg.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1); 878 } else { 879 farg.d = float64_sqrt(farg.d, &env->fp_status); 880 } 881 return farg.ll; 882 } 883 884 /* fre - fre. */ 885 uint64_t helper_fre(CPUPPCState *env, uint64_t arg) 886 { 887 CPU_DoubleU farg; 888 889 farg.ll = arg; 890 891 if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { 892 /* sNaN reciprocal */ 893 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 894 } 895 farg.d = float64_div(float64_one, farg.d, &env->fp_status); 896 return farg.d; 897 } 898 899 /* fres - fres. */ 900 uint64_t helper_fres(CPUPPCState *env, uint64_t arg) 901 { 902 CPU_DoubleU farg; 903 float32 f32; 904 905 farg.ll = arg; 906 907 if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { 908 /* sNaN reciprocal */ 909 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 910 } 911 farg.d = float64_div(float64_one, farg.d, &env->fp_status); 912 f32 = float64_to_float32(farg.d, &env->fp_status); 913 farg.d = float32_to_float64(f32, &env->fp_status); 914 915 return farg.ll; 916 } 917 918 /* frsqrte - frsqrte. */ 919 uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg) 920 { 921 CPU_DoubleU farg; 922 923 farg.ll = arg; 924 925 if (unlikely(float64_is_any_nan(farg.d))) { 926 if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { 927 /* sNaN reciprocal square root */ 928 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 929 farg.ll = float64_snan_to_qnan(farg.ll); 930 } 931 } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) { 932 /* Reciprocal square root of a negative nonzero number */ 933 farg.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1); 934 } else { 935 farg.d = float64_sqrt(farg.d, &env->fp_status); 936 farg.d = float64_div(float64_one, farg.d, &env->fp_status); 937 } 938 939 return farg.ll; 940 } 941 942 /* fsel - fsel. */ 943 uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2, 944 uint64_t arg3) 945 { 946 CPU_DoubleU farg1; 947 948 farg1.ll = arg1; 949 950 if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && 951 !float64_is_any_nan(farg1.d)) { 952 return arg2; 953 } else { 954 return arg3; 955 } 956 } 957 958 uint32_t helper_ftdiv(uint64_t fra, uint64_t frb) 959 { 960 int fe_flag = 0; 961 int fg_flag = 0; 962 963 if (unlikely(float64_is_infinity(fra) || 964 float64_is_infinity(frb) || 965 float64_is_zero(frb))) { 966 fe_flag = 1; 967 fg_flag = 1; 968 } else { 969 int e_a = ppc_float64_get_unbiased_exp(fra); 970 int e_b = ppc_float64_get_unbiased_exp(frb); 971 972 if (unlikely(float64_is_any_nan(fra) || 973 float64_is_any_nan(frb))) { 974 fe_flag = 1; 975 } else if ((e_b <= -1022) || (e_b >= 1021)) { 976 fe_flag = 1; 977 } else if (!float64_is_zero(fra) && 978 (((e_a - e_b) >= 1023) || 979 ((e_a - e_b) <= -1021) || 980 (e_a <= -970))) { 981 fe_flag = 1; 982 } 983 984 if (unlikely(float64_is_zero_or_denormal(frb))) { 985 /* XB is not zero because of the above check and */ 986 /* so must be denormalized. */ 987 fg_flag = 1; 988 } 989 } 990 991 return 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); 992 } 993 994 uint32_t helper_ftsqrt(uint64_t frb) 995 { 996 int fe_flag = 0; 997 int fg_flag = 0; 998 999 if (unlikely(float64_is_infinity(frb) || float64_is_zero(frb))) { 1000 fe_flag = 1; 1001 fg_flag = 1; 1002 } else { 1003 int e_b = ppc_float64_get_unbiased_exp(frb); 1004 1005 if (unlikely(float64_is_any_nan(frb))) { 1006 fe_flag = 1; 1007 } else if (unlikely(float64_is_zero(frb))) { 1008 fe_flag = 1; 1009 } else if (unlikely(float64_is_neg(frb))) { 1010 fe_flag = 1; 1011 } else if (!float64_is_zero(frb) && (e_b <= (-1022+52))) { 1012 fe_flag = 1; 1013 } 1014 1015 if (unlikely(float64_is_zero_or_denormal(frb))) { 1016 /* XB is not zero because of the above check and */ 1017 /* therefore must be denormalized. */ 1018 fg_flag = 1; 1019 } 1020 } 1021 1022 return 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); 1023 } 1024 1025 void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2, 1026 uint32_t crfD) 1027 { 1028 CPU_DoubleU farg1, farg2; 1029 uint32_t ret = 0; 1030 1031 farg1.ll = arg1; 1032 farg2.ll = arg2; 1033 1034 if (unlikely(float64_is_any_nan(farg1.d) || 1035 float64_is_any_nan(farg2.d))) { 1036 ret = 0x01UL; 1037 } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { 1038 ret = 0x08UL; 1039 } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { 1040 ret = 0x04UL; 1041 } else { 1042 ret = 0x02UL; 1043 } 1044 1045 env->fpscr &= ~(0x0F << FPSCR_FPRF); 1046 env->fpscr |= ret << FPSCR_FPRF; 1047 env->crf[crfD] = ret; 1048 if (unlikely(ret == 0x01UL 1049 && (float64_is_signaling_nan(farg1.d, &env->fp_status) || 1050 float64_is_signaling_nan(farg2.d, &env->fp_status)))) { 1051 /* sNaN comparison */ 1052 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 1053 } 1054 } 1055 1056 void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2, 1057 uint32_t crfD) 1058 { 1059 CPU_DoubleU farg1, farg2; 1060 uint32_t ret = 0; 1061 1062 farg1.ll = arg1; 1063 farg2.ll = arg2; 1064 1065 if (unlikely(float64_is_any_nan(farg1.d) || 1066 float64_is_any_nan(farg2.d))) { 1067 ret = 0x01UL; 1068 } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { 1069 ret = 0x08UL; 1070 } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { 1071 ret = 0x04UL; 1072 } else { 1073 ret = 0x02UL; 1074 } 1075 1076 env->fpscr &= ~(0x0F << FPSCR_FPRF); 1077 env->fpscr |= ret << FPSCR_FPRF; 1078 env->crf[crfD] = ret; 1079 if (unlikely(ret == 0x01UL)) { 1080 if (float64_is_signaling_nan(farg1.d, &env->fp_status) || 1081 float64_is_signaling_nan(farg2.d, &env->fp_status)) { 1082 /* sNaN comparison */ 1083 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | 1084 POWERPC_EXCP_FP_VXVC, 1); 1085 } else { 1086 /* qNaN comparison */ 1087 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1); 1088 } 1089 } 1090 } 1091 1092 /* Single-precision floating-point conversions */ 1093 static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val) 1094 { 1095 CPU_FloatU u; 1096 1097 u.f = int32_to_float32(val, &env->vec_status); 1098 1099 return u.l; 1100 } 1101 1102 static inline uint32_t efscfui(CPUPPCState *env, uint32_t val) 1103 { 1104 CPU_FloatU u; 1105 1106 u.f = uint32_to_float32(val, &env->vec_status); 1107 1108 return u.l; 1109 } 1110 1111 static inline int32_t efsctsi(CPUPPCState *env, uint32_t val) 1112 { 1113 CPU_FloatU u; 1114 1115 u.l = val; 1116 /* NaN are not treated the same way IEEE 754 does */ 1117 if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) { 1118 return 0; 1119 } 1120 1121 return float32_to_int32(u.f, &env->vec_status); 1122 } 1123 1124 static inline uint32_t efsctui(CPUPPCState *env, uint32_t val) 1125 { 1126 CPU_FloatU u; 1127 1128 u.l = val; 1129 /* NaN are not treated the same way IEEE 754 does */ 1130 if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) { 1131 return 0; 1132 } 1133 1134 return float32_to_uint32(u.f, &env->vec_status); 1135 } 1136 1137 static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val) 1138 { 1139 CPU_FloatU u; 1140 1141 u.l = val; 1142 /* NaN are not treated the same way IEEE 754 does */ 1143 if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) { 1144 return 0; 1145 } 1146 1147 return float32_to_int32_round_to_zero(u.f, &env->vec_status); 1148 } 1149 1150 static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val) 1151 { 1152 CPU_FloatU u; 1153 1154 u.l = val; 1155 /* NaN are not treated the same way IEEE 754 does */ 1156 if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) { 1157 return 0; 1158 } 1159 1160 return float32_to_uint32_round_to_zero(u.f, &env->vec_status); 1161 } 1162 1163 static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val) 1164 { 1165 CPU_FloatU u; 1166 float32 tmp; 1167 1168 u.f = int32_to_float32(val, &env->vec_status); 1169 tmp = int64_to_float32(1ULL << 32, &env->vec_status); 1170 u.f = float32_div(u.f, tmp, &env->vec_status); 1171 1172 return u.l; 1173 } 1174 1175 static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val) 1176 { 1177 CPU_FloatU u; 1178 float32 tmp; 1179 1180 u.f = uint32_to_float32(val, &env->vec_status); 1181 tmp = uint64_to_float32(1ULL << 32, &env->vec_status); 1182 u.f = float32_div(u.f, tmp, &env->vec_status); 1183 1184 return u.l; 1185 } 1186 1187 static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val) 1188 { 1189 CPU_FloatU u; 1190 float32 tmp; 1191 1192 u.l = val; 1193 /* NaN are not treated the same way IEEE 754 does */ 1194 if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) { 1195 return 0; 1196 } 1197 tmp = uint64_to_float32(1ULL << 32, &env->vec_status); 1198 u.f = float32_mul(u.f, tmp, &env->vec_status); 1199 1200 return float32_to_int32(u.f, &env->vec_status); 1201 } 1202 1203 static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val) 1204 { 1205 CPU_FloatU u; 1206 float32 tmp; 1207 1208 u.l = val; 1209 /* NaN are not treated the same way IEEE 754 does */ 1210 if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) { 1211 return 0; 1212 } 1213 tmp = uint64_to_float32(1ULL << 32, &env->vec_status); 1214 u.f = float32_mul(u.f, tmp, &env->vec_status); 1215 1216 return float32_to_uint32(u.f, &env->vec_status); 1217 } 1218 1219 #define HELPER_SPE_SINGLE_CONV(name) \ 1220 uint32_t helper_e##name(CPUPPCState *env, uint32_t val) \ 1221 { \ 1222 return e##name(env, val); \ 1223 } 1224 /* efscfsi */ 1225 HELPER_SPE_SINGLE_CONV(fscfsi); 1226 /* efscfui */ 1227 HELPER_SPE_SINGLE_CONV(fscfui); 1228 /* efscfuf */ 1229 HELPER_SPE_SINGLE_CONV(fscfuf); 1230 /* efscfsf */ 1231 HELPER_SPE_SINGLE_CONV(fscfsf); 1232 /* efsctsi */ 1233 HELPER_SPE_SINGLE_CONV(fsctsi); 1234 /* efsctui */ 1235 HELPER_SPE_SINGLE_CONV(fsctui); 1236 /* efsctsiz */ 1237 HELPER_SPE_SINGLE_CONV(fsctsiz); 1238 /* efsctuiz */ 1239 HELPER_SPE_SINGLE_CONV(fsctuiz); 1240 /* efsctsf */ 1241 HELPER_SPE_SINGLE_CONV(fsctsf); 1242 /* efsctuf */ 1243 HELPER_SPE_SINGLE_CONV(fsctuf); 1244 1245 #define HELPER_SPE_VECTOR_CONV(name) \ 1246 uint64_t helper_ev##name(CPUPPCState *env, uint64_t val) \ 1247 { \ 1248 return ((uint64_t)e##name(env, val >> 32) << 32) | \ 1249 (uint64_t)e##name(env, val); \ 1250 } 1251 /* evfscfsi */ 1252 HELPER_SPE_VECTOR_CONV(fscfsi); 1253 /* evfscfui */ 1254 HELPER_SPE_VECTOR_CONV(fscfui); 1255 /* evfscfuf */ 1256 HELPER_SPE_VECTOR_CONV(fscfuf); 1257 /* evfscfsf */ 1258 HELPER_SPE_VECTOR_CONV(fscfsf); 1259 /* evfsctsi */ 1260 HELPER_SPE_VECTOR_CONV(fsctsi); 1261 /* evfsctui */ 1262 HELPER_SPE_VECTOR_CONV(fsctui); 1263 /* evfsctsiz */ 1264 HELPER_SPE_VECTOR_CONV(fsctsiz); 1265 /* evfsctuiz */ 1266 HELPER_SPE_VECTOR_CONV(fsctuiz); 1267 /* evfsctsf */ 1268 HELPER_SPE_VECTOR_CONV(fsctsf); 1269 /* evfsctuf */ 1270 HELPER_SPE_VECTOR_CONV(fsctuf); 1271 1272 /* Single-precision floating-point arithmetic */ 1273 static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2) 1274 { 1275 CPU_FloatU u1, u2; 1276 1277 u1.l = op1; 1278 u2.l = op2; 1279 u1.f = float32_add(u1.f, u2.f, &env->vec_status); 1280 return u1.l; 1281 } 1282 1283 static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2) 1284 { 1285 CPU_FloatU u1, u2; 1286 1287 u1.l = op1; 1288 u2.l = op2; 1289 u1.f = float32_sub(u1.f, u2.f, &env->vec_status); 1290 return u1.l; 1291 } 1292 1293 static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2) 1294 { 1295 CPU_FloatU u1, u2; 1296 1297 u1.l = op1; 1298 u2.l = op2; 1299 u1.f = float32_mul(u1.f, u2.f, &env->vec_status); 1300 return u1.l; 1301 } 1302 1303 static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2) 1304 { 1305 CPU_FloatU u1, u2; 1306 1307 u1.l = op1; 1308 u2.l = op2; 1309 u1.f = float32_div(u1.f, u2.f, &env->vec_status); 1310 return u1.l; 1311 } 1312 1313 #define HELPER_SPE_SINGLE_ARITH(name) \ 1314 uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ 1315 { \ 1316 return e##name(env, op1, op2); \ 1317 } 1318 /* efsadd */ 1319 HELPER_SPE_SINGLE_ARITH(fsadd); 1320 /* efssub */ 1321 HELPER_SPE_SINGLE_ARITH(fssub); 1322 /* efsmul */ 1323 HELPER_SPE_SINGLE_ARITH(fsmul); 1324 /* efsdiv */ 1325 HELPER_SPE_SINGLE_ARITH(fsdiv); 1326 1327 #define HELPER_SPE_VECTOR_ARITH(name) \ 1328 uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \ 1329 { \ 1330 return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) | \ 1331 (uint64_t)e##name(env, op1, op2); \ 1332 } 1333 /* evfsadd */ 1334 HELPER_SPE_VECTOR_ARITH(fsadd); 1335 /* evfssub */ 1336 HELPER_SPE_VECTOR_ARITH(fssub); 1337 /* evfsmul */ 1338 HELPER_SPE_VECTOR_ARITH(fsmul); 1339 /* evfsdiv */ 1340 HELPER_SPE_VECTOR_ARITH(fsdiv); 1341 1342 /* Single-precision floating-point comparisons */ 1343 static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2) 1344 { 1345 CPU_FloatU u1, u2; 1346 1347 u1.l = op1; 1348 u2.l = op2; 1349 return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0; 1350 } 1351 1352 static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2) 1353 { 1354 CPU_FloatU u1, u2; 1355 1356 u1.l = op1; 1357 u2.l = op2; 1358 return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4; 1359 } 1360 1361 static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2) 1362 { 1363 CPU_FloatU u1, u2; 1364 1365 u1.l = op1; 1366 u2.l = op2; 1367 return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0; 1368 } 1369 1370 static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2) 1371 { 1372 /* XXX: TODO: ignore special values (NaN, infinites, ...) */ 1373 return efscmplt(env, op1, op2); 1374 } 1375 1376 static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2) 1377 { 1378 /* XXX: TODO: ignore special values (NaN, infinites, ...) */ 1379 return efscmpgt(env, op1, op2); 1380 } 1381 1382 static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2) 1383 { 1384 /* XXX: TODO: ignore special values (NaN, infinites, ...) */ 1385 return efscmpeq(env, op1, op2); 1386 } 1387 1388 #define HELPER_SINGLE_SPE_CMP(name) \ 1389 uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \ 1390 { \ 1391 return e##name(env, op1, op2); \ 1392 } 1393 /* efststlt */ 1394 HELPER_SINGLE_SPE_CMP(fststlt); 1395 /* efststgt */ 1396 HELPER_SINGLE_SPE_CMP(fststgt); 1397 /* efststeq */ 1398 HELPER_SINGLE_SPE_CMP(fststeq); 1399 /* efscmplt */ 1400 HELPER_SINGLE_SPE_CMP(fscmplt); 1401 /* efscmpgt */ 1402 HELPER_SINGLE_SPE_CMP(fscmpgt); 1403 /* efscmpeq */ 1404 HELPER_SINGLE_SPE_CMP(fscmpeq); 1405 1406 static inline uint32_t evcmp_merge(int t0, int t1) 1407 { 1408 return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1); 1409 } 1410 1411 #define HELPER_VECTOR_SPE_CMP(name) \ 1412 uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \ 1413 { \ 1414 return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32), \ 1415 e##name(env, op1, op2)); \ 1416 } 1417 /* evfststlt */ 1418 HELPER_VECTOR_SPE_CMP(fststlt); 1419 /* evfststgt */ 1420 HELPER_VECTOR_SPE_CMP(fststgt); 1421 /* evfststeq */ 1422 HELPER_VECTOR_SPE_CMP(fststeq); 1423 /* evfscmplt */ 1424 HELPER_VECTOR_SPE_CMP(fscmplt); 1425 /* evfscmpgt */ 1426 HELPER_VECTOR_SPE_CMP(fscmpgt); 1427 /* evfscmpeq */ 1428 HELPER_VECTOR_SPE_CMP(fscmpeq); 1429 1430 /* Double-precision floating-point conversion */ 1431 uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val) 1432 { 1433 CPU_DoubleU u; 1434 1435 u.d = int32_to_float64(val, &env->vec_status); 1436 1437 return u.ll; 1438 } 1439 1440 uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val) 1441 { 1442 CPU_DoubleU u; 1443 1444 u.d = int64_to_float64(val, &env->vec_status); 1445 1446 return u.ll; 1447 } 1448 1449 uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val) 1450 { 1451 CPU_DoubleU u; 1452 1453 u.d = uint32_to_float64(val, &env->vec_status); 1454 1455 return u.ll; 1456 } 1457 1458 uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val) 1459 { 1460 CPU_DoubleU u; 1461 1462 u.d = uint64_to_float64(val, &env->vec_status); 1463 1464 return u.ll; 1465 } 1466 1467 uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val) 1468 { 1469 CPU_DoubleU u; 1470 1471 u.ll = val; 1472 /* NaN are not treated the same way IEEE 754 does */ 1473 if (unlikely(float64_is_any_nan(u.d))) { 1474 return 0; 1475 } 1476 1477 return float64_to_int32(u.d, &env->vec_status); 1478 } 1479 1480 uint32_t helper_efdctui(CPUPPCState *env, uint64_t val) 1481 { 1482 CPU_DoubleU u; 1483 1484 u.ll = val; 1485 /* NaN are not treated the same way IEEE 754 does */ 1486 if (unlikely(float64_is_any_nan(u.d))) { 1487 return 0; 1488 } 1489 1490 return float64_to_uint32(u.d, &env->vec_status); 1491 } 1492 1493 uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val) 1494 { 1495 CPU_DoubleU u; 1496 1497 u.ll = val; 1498 /* NaN are not treated the same way IEEE 754 does */ 1499 if (unlikely(float64_is_any_nan(u.d))) { 1500 return 0; 1501 } 1502 1503 return float64_to_int32_round_to_zero(u.d, &env->vec_status); 1504 } 1505 1506 uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val) 1507 { 1508 CPU_DoubleU u; 1509 1510 u.ll = val; 1511 /* NaN are not treated the same way IEEE 754 does */ 1512 if (unlikely(float64_is_any_nan(u.d))) { 1513 return 0; 1514 } 1515 1516 return float64_to_int64_round_to_zero(u.d, &env->vec_status); 1517 } 1518 1519 uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val) 1520 { 1521 CPU_DoubleU u; 1522 1523 u.ll = val; 1524 /* NaN are not treated the same way IEEE 754 does */ 1525 if (unlikely(float64_is_any_nan(u.d))) { 1526 return 0; 1527 } 1528 1529 return float64_to_uint32_round_to_zero(u.d, &env->vec_status); 1530 } 1531 1532 uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val) 1533 { 1534 CPU_DoubleU u; 1535 1536 u.ll = val; 1537 /* NaN are not treated the same way IEEE 754 does */ 1538 if (unlikely(float64_is_any_nan(u.d))) { 1539 return 0; 1540 } 1541 1542 return float64_to_uint64_round_to_zero(u.d, &env->vec_status); 1543 } 1544 1545 uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val) 1546 { 1547 CPU_DoubleU u; 1548 float64 tmp; 1549 1550 u.d = int32_to_float64(val, &env->vec_status); 1551 tmp = int64_to_float64(1ULL << 32, &env->vec_status); 1552 u.d = float64_div(u.d, tmp, &env->vec_status); 1553 1554 return u.ll; 1555 } 1556 1557 uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val) 1558 { 1559 CPU_DoubleU u; 1560 float64 tmp; 1561 1562 u.d = uint32_to_float64(val, &env->vec_status); 1563 tmp = int64_to_float64(1ULL << 32, &env->vec_status); 1564 u.d = float64_div(u.d, tmp, &env->vec_status); 1565 1566 return u.ll; 1567 } 1568 1569 uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val) 1570 { 1571 CPU_DoubleU u; 1572 float64 tmp; 1573 1574 u.ll = val; 1575 /* NaN are not treated the same way IEEE 754 does */ 1576 if (unlikely(float64_is_any_nan(u.d))) { 1577 return 0; 1578 } 1579 tmp = uint64_to_float64(1ULL << 32, &env->vec_status); 1580 u.d = float64_mul(u.d, tmp, &env->vec_status); 1581 1582 return float64_to_int32(u.d, &env->vec_status); 1583 } 1584 1585 uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val) 1586 { 1587 CPU_DoubleU u; 1588 float64 tmp; 1589 1590 u.ll = val; 1591 /* NaN are not treated the same way IEEE 754 does */ 1592 if (unlikely(float64_is_any_nan(u.d))) { 1593 return 0; 1594 } 1595 tmp = uint64_to_float64(1ULL << 32, &env->vec_status); 1596 u.d = float64_mul(u.d, tmp, &env->vec_status); 1597 1598 return float64_to_uint32(u.d, &env->vec_status); 1599 } 1600 1601 uint32_t helper_efscfd(CPUPPCState *env, uint64_t val) 1602 { 1603 CPU_DoubleU u1; 1604 CPU_FloatU u2; 1605 1606 u1.ll = val; 1607 u2.f = float64_to_float32(u1.d, &env->vec_status); 1608 1609 return u2.l; 1610 } 1611 1612 uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val) 1613 { 1614 CPU_DoubleU u2; 1615 CPU_FloatU u1; 1616 1617 u1.l = val; 1618 u2.d = float32_to_float64(u1.f, &env->vec_status); 1619 1620 return u2.ll; 1621 } 1622 1623 /* Double precision fixed-point arithmetic */ 1624 uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2) 1625 { 1626 CPU_DoubleU u1, u2; 1627 1628 u1.ll = op1; 1629 u2.ll = op2; 1630 u1.d = float64_add(u1.d, u2.d, &env->vec_status); 1631 return u1.ll; 1632 } 1633 1634 uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2) 1635 { 1636 CPU_DoubleU u1, u2; 1637 1638 u1.ll = op1; 1639 u2.ll = op2; 1640 u1.d = float64_sub(u1.d, u2.d, &env->vec_status); 1641 return u1.ll; 1642 } 1643 1644 uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2) 1645 { 1646 CPU_DoubleU u1, u2; 1647 1648 u1.ll = op1; 1649 u2.ll = op2; 1650 u1.d = float64_mul(u1.d, u2.d, &env->vec_status); 1651 return u1.ll; 1652 } 1653 1654 uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2) 1655 { 1656 CPU_DoubleU u1, u2; 1657 1658 u1.ll = op1; 1659 u2.ll = op2; 1660 u1.d = float64_div(u1.d, u2.d, &env->vec_status); 1661 return u1.ll; 1662 } 1663 1664 /* Double precision floating point helpers */ 1665 uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2) 1666 { 1667 CPU_DoubleU u1, u2; 1668 1669 u1.ll = op1; 1670 u2.ll = op2; 1671 return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0; 1672 } 1673 1674 uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2) 1675 { 1676 CPU_DoubleU u1, u2; 1677 1678 u1.ll = op1; 1679 u2.ll = op2; 1680 return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4; 1681 } 1682 1683 uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2) 1684 { 1685 CPU_DoubleU u1, u2; 1686 1687 u1.ll = op1; 1688 u2.ll = op2; 1689 return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0; 1690 } 1691 1692 uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2) 1693 { 1694 /* XXX: TODO: test special values (NaN, infinites, ...) */ 1695 return helper_efdtstlt(env, op1, op2); 1696 } 1697 1698 uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2) 1699 { 1700 /* XXX: TODO: test special values (NaN, infinites, ...) */ 1701 return helper_efdtstgt(env, op1, op2); 1702 } 1703 1704 uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2) 1705 { 1706 /* XXX: TODO: test special values (NaN, infinites, ...) */ 1707 return helper_efdtsteq(env, op1, op2); 1708 } 1709 1710 #define float64_to_float64(x, env) x 1711 1712 1713 /* VSX_ADD_SUB - VSX floating point add/subract 1714 * name - instruction mnemonic 1715 * op - operation (add or sub) 1716 * nels - number of elements (1, 2 or 4) 1717 * tp - type (float32 or float64) 1718 * fld - vsr_t field (VsrD(*) or VsrW(*)) 1719 * sfprf - set FPRF 1720 */ 1721 #define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp) \ 1722 void helper_##name(CPUPPCState *env, uint32_t opcode) \ 1723 { \ 1724 ppc_vsr_t xt, xa, xb; \ 1725 int i; \ 1726 \ 1727 getVSR(xA(opcode), &xa, env); \ 1728 getVSR(xB(opcode), &xb, env); \ 1729 getVSR(xT(opcode), &xt, env); \ 1730 helper_reset_fpstatus(env); \ 1731 \ 1732 for (i = 0; i < nels; i++) { \ 1733 float_status tstat = env->fp_status; \ 1734 set_float_exception_flags(0, &tstat); \ 1735 xt.fld = tp##_##op(xa.fld, xb.fld, &tstat); \ 1736 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ 1737 \ 1738 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ 1739 if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) { \ 1740 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \ 1741 } else if (tp##_is_signaling_nan(xa.fld, &tstat) || \ 1742 tp##_is_signaling_nan(xb.fld, &tstat)) { \ 1743 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \ 1744 } \ 1745 } \ 1746 \ 1747 if (r2sp) { \ 1748 xt.fld = helper_frsp(env, xt.fld); \ 1749 } \ 1750 \ 1751 if (sfprf) { \ 1752 helper_compute_fprf_float64(env, xt.fld); \ 1753 } \ 1754 } \ 1755 putVSR(xT(opcode), &xt, env); \ 1756 float_check_status(env); \ 1757 } 1758 1759 VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0) 1760 VSX_ADD_SUB(xsaddsp, add, 1, float64, VsrD(0), 1, 1) 1761 VSX_ADD_SUB(xvadddp, add, 2, float64, VsrD(i), 0, 0) 1762 VSX_ADD_SUB(xvaddsp, add, 4, float32, VsrW(i), 0, 0) 1763 VSX_ADD_SUB(xssubdp, sub, 1, float64, VsrD(0), 1, 0) 1764 VSX_ADD_SUB(xssubsp, sub, 1, float64, VsrD(0), 1, 1) 1765 VSX_ADD_SUB(xvsubdp, sub, 2, float64, VsrD(i), 0, 0) 1766 VSX_ADD_SUB(xvsubsp, sub, 4, float32, VsrW(i), 0, 0) 1767 1768 void helper_xsaddqp(CPUPPCState *env, uint32_t opcode) 1769 { 1770 ppc_vsr_t xt, xa, xb; 1771 float_status tstat; 1772 1773 getVSR(rA(opcode) + 32, &xa, env); 1774 getVSR(rB(opcode) + 32, &xb, env); 1775 getVSR(rD(opcode) + 32, &xt, env); 1776 helper_reset_fpstatus(env); 1777 1778 tstat = env->fp_status; 1779 if (unlikely(Rc(opcode) != 0)) { 1780 tstat.float_rounding_mode = float_round_to_odd; 1781 } 1782 1783 set_float_exception_flags(0, &tstat); 1784 xt.f128 = float128_add(xa.f128, xb.f128, &tstat); 1785 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 1786 1787 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 1788 if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) { 1789 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); 1790 } else if (float128_is_signaling_nan(xa.f128, &tstat) || 1791 float128_is_signaling_nan(xb.f128, &tstat)) { 1792 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 1793 } 1794 } 1795 1796 helper_compute_fprf_float128(env, xt.f128); 1797 1798 putVSR(rD(opcode) + 32, &xt, env); 1799 float_check_status(env); 1800 } 1801 1802 /* VSX_MUL - VSX floating point multiply 1803 * op - instruction mnemonic 1804 * nels - number of elements (1, 2 or 4) 1805 * tp - type (float32 or float64) 1806 * fld - vsr_t field (VsrD(*) or VsrW(*)) 1807 * sfprf - set FPRF 1808 */ 1809 #define VSX_MUL(op, nels, tp, fld, sfprf, r2sp) \ 1810 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 1811 { \ 1812 ppc_vsr_t xt, xa, xb; \ 1813 int i; \ 1814 \ 1815 getVSR(xA(opcode), &xa, env); \ 1816 getVSR(xB(opcode), &xb, env); \ 1817 getVSR(xT(opcode), &xt, env); \ 1818 helper_reset_fpstatus(env); \ 1819 \ 1820 for (i = 0; i < nels; i++) { \ 1821 float_status tstat = env->fp_status; \ 1822 set_float_exception_flags(0, &tstat); \ 1823 xt.fld = tp##_mul(xa.fld, xb.fld, &tstat); \ 1824 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ 1825 \ 1826 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ 1827 if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) || \ 1828 (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) { \ 1829 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf); \ 1830 } else if (tp##_is_signaling_nan(xa.fld, &tstat) || \ 1831 tp##_is_signaling_nan(xb.fld, &tstat)) { \ 1832 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \ 1833 } \ 1834 } \ 1835 \ 1836 if (r2sp) { \ 1837 xt.fld = helper_frsp(env, xt.fld); \ 1838 } \ 1839 \ 1840 if (sfprf) { \ 1841 helper_compute_fprf_float64(env, xt.fld); \ 1842 } \ 1843 } \ 1844 \ 1845 putVSR(xT(opcode), &xt, env); \ 1846 float_check_status(env); \ 1847 } 1848 1849 VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0) 1850 VSX_MUL(xsmulsp, 1, float64, VsrD(0), 1, 1) 1851 VSX_MUL(xvmuldp, 2, float64, VsrD(i), 0, 0) 1852 VSX_MUL(xvmulsp, 4, float32, VsrW(i), 0, 0) 1853 1854 void helper_xsmulqp(CPUPPCState *env, uint32_t opcode) 1855 { 1856 ppc_vsr_t xt, xa, xb; 1857 float_status tstat; 1858 1859 getVSR(rA(opcode) + 32, &xa, env); 1860 getVSR(rB(opcode) + 32, &xb, env); 1861 getVSR(rD(opcode) + 32, &xt, env); 1862 1863 helper_reset_fpstatus(env); 1864 tstat = env->fp_status; 1865 if (unlikely(Rc(opcode) != 0)) { 1866 tstat.float_rounding_mode = float_round_to_odd; 1867 } 1868 1869 set_float_exception_flags(0, &tstat); 1870 xt.f128 = float128_mul(xa.f128, xb.f128, &tstat); 1871 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 1872 1873 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 1874 if ((float128_is_infinity(xa.f128) && float128_is_zero(xb.f128)) || 1875 (float128_is_infinity(xb.f128) && float128_is_zero(xa.f128))) { 1876 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); 1877 } else if (float128_is_signaling_nan(xa.f128, &tstat) || 1878 float128_is_signaling_nan(xb.f128, &tstat)) { 1879 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 1880 } 1881 } 1882 helper_compute_fprf_float128(env, xt.f128); 1883 1884 putVSR(rD(opcode) + 32, &xt, env); 1885 float_check_status(env); 1886 } 1887 1888 /* VSX_DIV - VSX floating point divide 1889 * op - instruction mnemonic 1890 * nels - number of elements (1, 2 or 4) 1891 * tp - type (float32 or float64) 1892 * fld - vsr_t field (VsrD(*) or VsrW(*)) 1893 * sfprf - set FPRF 1894 */ 1895 #define VSX_DIV(op, nels, tp, fld, sfprf, r2sp) \ 1896 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 1897 { \ 1898 ppc_vsr_t xt, xa, xb; \ 1899 int i; \ 1900 \ 1901 getVSR(xA(opcode), &xa, env); \ 1902 getVSR(xB(opcode), &xb, env); \ 1903 getVSR(xT(opcode), &xt, env); \ 1904 helper_reset_fpstatus(env); \ 1905 \ 1906 for (i = 0; i < nels; i++) { \ 1907 float_status tstat = env->fp_status; \ 1908 set_float_exception_flags(0, &tstat); \ 1909 xt.fld = tp##_div(xa.fld, xb.fld, &tstat); \ 1910 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ 1911 \ 1912 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ 1913 if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) { \ 1914 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf); \ 1915 } else if (tp##_is_zero(xa.fld) && \ 1916 tp##_is_zero(xb.fld)) { \ 1917 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf); \ 1918 } else if (tp##_is_signaling_nan(xa.fld, &tstat) || \ 1919 tp##_is_signaling_nan(xb.fld, &tstat)) { \ 1920 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \ 1921 } \ 1922 } \ 1923 \ 1924 if (r2sp) { \ 1925 xt.fld = helper_frsp(env, xt.fld); \ 1926 } \ 1927 \ 1928 if (sfprf) { \ 1929 helper_compute_fprf_float64(env, xt.fld); \ 1930 } \ 1931 } \ 1932 \ 1933 putVSR(xT(opcode), &xt, env); \ 1934 float_check_status(env); \ 1935 } 1936 1937 VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0) 1938 VSX_DIV(xsdivsp, 1, float64, VsrD(0), 1, 1) 1939 VSX_DIV(xvdivdp, 2, float64, VsrD(i), 0, 0) 1940 VSX_DIV(xvdivsp, 4, float32, VsrW(i), 0, 0) 1941 1942 void helper_xsdivqp(CPUPPCState *env, uint32_t opcode) 1943 { 1944 ppc_vsr_t xt, xa, xb; 1945 float_status tstat; 1946 1947 getVSR(rA(opcode) + 32, &xa, env); 1948 getVSR(rB(opcode) + 32, &xb, env); 1949 getVSR(rD(opcode) + 32, &xt, env); 1950 1951 helper_reset_fpstatus(env); 1952 tstat = env->fp_status; 1953 if (unlikely(Rc(opcode) != 0)) { 1954 tstat.float_rounding_mode = float_round_to_odd; 1955 } 1956 1957 set_float_exception_flags(0, &tstat); 1958 xt.f128 = float128_div(xa.f128, xb.f128, &tstat); 1959 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 1960 1961 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 1962 if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) { 1963 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1); 1964 } else if (float128_is_zero(xa.f128) && 1965 float128_is_zero(xb.f128)) { 1966 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1); 1967 } else if (float128_is_signaling_nan(xa.f128, &tstat) || 1968 float128_is_signaling_nan(xb.f128, &tstat)) { 1969 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 1970 } 1971 } 1972 1973 helper_compute_fprf_float128(env, xt.f128); 1974 putVSR(rD(opcode) + 32, &xt, env); 1975 float_check_status(env); 1976 } 1977 1978 /* VSX_RE - VSX floating point reciprocal estimate 1979 * op - instruction mnemonic 1980 * nels - number of elements (1, 2 or 4) 1981 * tp - type (float32 or float64) 1982 * fld - vsr_t field (VsrD(*) or VsrW(*)) 1983 * sfprf - set FPRF 1984 */ 1985 #define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \ 1986 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 1987 { \ 1988 ppc_vsr_t xt, xb; \ 1989 int i; \ 1990 \ 1991 getVSR(xB(opcode), &xb, env); \ 1992 getVSR(xT(opcode), &xt, env); \ 1993 helper_reset_fpstatus(env); \ 1994 \ 1995 for (i = 0; i < nels; i++) { \ 1996 if (unlikely(tp##_is_signaling_nan(xb.fld, &env->fp_status))) { \ 1997 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \ 1998 } \ 1999 xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status); \ 2000 \ 2001 if (r2sp) { \ 2002 xt.fld = helper_frsp(env, xt.fld); \ 2003 } \ 2004 \ 2005 if (sfprf) { \ 2006 helper_compute_fprf_float64(env, xt.fld); \ 2007 } \ 2008 } \ 2009 \ 2010 putVSR(xT(opcode), &xt, env); \ 2011 float_check_status(env); \ 2012 } 2013 2014 VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0) 2015 VSX_RE(xsresp, 1, float64, VsrD(0), 1, 1) 2016 VSX_RE(xvredp, 2, float64, VsrD(i), 0, 0) 2017 VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0) 2018 2019 /* VSX_SQRT - VSX floating point square root 2020 * op - instruction mnemonic 2021 * nels - number of elements (1, 2 or 4) 2022 * tp - type (float32 or float64) 2023 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2024 * sfprf - set FPRF 2025 */ 2026 #define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \ 2027 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2028 { \ 2029 ppc_vsr_t xt, xb; \ 2030 int i; \ 2031 \ 2032 getVSR(xB(opcode), &xb, env); \ 2033 getVSR(xT(opcode), &xt, env); \ 2034 helper_reset_fpstatus(env); \ 2035 \ 2036 for (i = 0; i < nels; i++) { \ 2037 float_status tstat = env->fp_status; \ 2038 set_float_exception_flags(0, &tstat); \ 2039 xt.fld = tp##_sqrt(xb.fld, &tstat); \ 2040 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ 2041 \ 2042 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ 2043 if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \ 2044 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \ 2045 } else if (tp##_is_signaling_nan(xb.fld, &tstat)) { \ 2046 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \ 2047 } \ 2048 } \ 2049 \ 2050 if (r2sp) { \ 2051 xt.fld = helper_frsp(env, xt.fld); \ 2052 } \ 2053 \ 2054 if (sfprf) { \ 2055 helper_compute_fprf_float64(env, xt.fld); \ 2056 } \ 2057 } \ 2058 \ 2059 putVSR(xT(opcode), &xt, env); \ 2060 float_check_status(env); \ 2061 } 2062 2063 VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0) 2064 VSX_SQRT(xssqrtsp, 1, float64, VsrD(0), 1, 1) 2065 VSX_SQRT(xvsqrtdp, 2, float64, VsrD(i), 0, 0) 2066 VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0) 2067 2068 /* VSX_RSQRTE - VSX floating point reciprocal square root estimate 2069 * op - instruction mnemonic 2070 * nels - number of elements (1, 2 or 4) 2071 * tp - type (float32 or float64) 2072 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2073 * sfprf - set FPRF 2074 */ 2075 #define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \ 2076 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2077 { \ 2078 ppc_vsr_t xt, xb; \ 2079 int i; \ 2080 \ 2081 getVSR(xB(opcode), &xb, env); \ 2082 getVSR(xT(opcode), &xt, env); \ 2083 helper_reset_fpstatus(env); \ 2084 \ 2085 for (i = 0; i < nels; i++) { \ 2086 float_status tstat = env->fp_status; \ 2087 set_float_exception_flags(0, &tstat); \ 2088 xt.fld = tp##_sqrt(xb.fld, &tstat); \ 2089 xt.fld = tp##_div(tp##_one, xt.fld, &tstat); \ 2090 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ 2091 \ 2092 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ 2093 if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \ 2094 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \ 2095 } else if (tp##_is_signaling_nan(xb.fld, &tstat)) { \ 2096 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \ 2097 } \ 2098 } \ 2099 \ 2100 if (r2sp) { \ 2101 xt.fld = helper_frsp(env, xt.fld); \ 2102 } \ 2103 \ 2104 if (sfprf) { \ 2105 helper_compute_fprf_float64(env, xt.fld); \ 2106 } \ 2107 } \ 2108 \ 2109 putVSR(xT(opcode), &xt, env); \ 2110 float_check_status(env); \ 2111 } 2112 2113 VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0) 2114 VSX_RSQRTE(xsrsqrtesp, 1, float64, VsrD(0), 1, 1) 2115 VSX_RSQRTE(xvrsqrtedp, 2, float64, VsrD(i), 0, 0) 2116 VSX_RSQRTE(xvrsqrtesp, 4, float32, VsrW(i), 0, 0) 2117 2118 /* VSX_TDIV - VSX floating point test for divide 2119 * op - instruction mnemonic 2120 * nels - number of elements (1, 2 or 4) 2121 * tp - type (float32 or float64) 2122 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2123 * emin - minimum unbiased exponent 2124 * emax - maximum unbiased exponent 2125 * nbits - number of fraction bits 2126 */ 2127 #define VSX_TDIV(op, nels, tp, fld, emin, emax, nbits) \ 2128 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2129 { \ 2130 ppc_vsr_t xa, xb; \ 2131 int i; \ 2132 int fe_flag = 0; \ 2133 int fg_flag = 0; \ 2134 \ 2135 getVSR(xA(opcode), &xa, env); \ 2136 getVSR(xB(opcode), &xb, env); \ 2137 \ 2138 for (i = 0; i < nels; i++) { \ 2139 if (unlikely(tp##_is_infinity(xa.fld) || \ 2140 tp##_is_infinity(xb.fld) || \ 2141 tp##_is_zero(xb.fld))) { \ 2142 fe_flag = 1; \ 2143 fg_flag = 1; \ 2144 } else { \ 2145 int e_a = ppc_##tp##_get_unbiased_exp(xa.fld); \ 2146 int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \ 2147 \ 2148 if (unlikely(tp##_is_any_nan(xa.fld) || \ 2149 tp##_is_any_nan(xb.fld))) { \ 2150 fe_flag = 1; \ 2151 } else if ((e_b <= emin) || (e_b >= (emax-2))) { \ 2152 fe_flag = 1; \ 2153 } else if (!tp##_is_zero(xa.fld) && \ 2154 (((e_a - e_b) >= emax) || \ 2155 ((e_a - e_b) <= (emin+1)) || \ 2156 (e_a <= (emin+nbits)))) { \ 2157 fe_flag = 1; \ 2158 } \ 2159 \ 2160 if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \ 2161 /* XB is not zero because of the above check and */ \ 2162 /* so must be denormalized. */ \ 2163 fg_flag = 1; \ 2164 } \ 2165 } \ 2166 } \ 2167 \ 2168 env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \ 2169 } 2170 2171 VSX_TDIV(xstdivdp, 1, float64, VsrD(0), -1022, 1023, 52) 2172 VSX_TDIV(xvtdivdp, 2, float64, VsrD(i), -1022, 1023, 52) 2173 VSX_TDIV(xvtdivsp, 4, float32, VsrW(i), -126, 127, 23) 2174 2175 /* VSX_TSQRT - VSX floating point test for square root 2176 * op - instruction mnemonic 2177 * nels - number of elements (1, 2 or 4) 2178 * tp - type (float32 or float64) 2179 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2180 * emin - minimum unbiased exponent 2181 * emax - maximum unbiased exponent 2182 * nbits - number of fraction bits 2183 */ 2184 #define VSX_TSQRT(op, nels, tp, fld, emin, nbits) \ 2185 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2186 { \ 2187 ppc_vsr_t xa, xb; \ 2188 int i; \ 2189 int fe_flag = 0; \ 2190 int fg_flag = 0; \ 2191 \ 2192 getVSR(xA(opcode), &xa, env); \ 2193 getVSR(xB(opcode), &xb, env); \ 2194 \ 2195 for (i = 0; i < nels; i++) { \ 2196 if (unlikely(tp##_is_infinity(xb.fld) || \ 2197 tp##_is_zero(xb.fld))) { \ 2198 fe_flag = 1; \ 2199 fg_flag = 1; \ 2200 } else { \ 2201 int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \ 2202 \ 2203 if (unlikely(tp##_is_any_nan(xb.fld))) { \ 2204 fe_flag = 1; \ 2205 } else if (unlikely(tp##_is_zero(xb.fld))) { \ 2206 fe_flag = 1; \ 2207 } else if (unlikely(tp##_is_neg(xb.fld))) { \ 2208 fe_flag = 1; \ 2209 } else if (!tp##_is_zero(xb.fld) && \ 2210 (e_b <= (emin+nbits))) { \ 2211 fe_flag = 1; \ 2212 } \ 2213 \ 2214 if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \ 2215 /* XB is not zero because of the above check and */ \ 2216 /* therefore must be denormalized. */ \ 2217 fg_flag = 1; \ 2218 } \ 2219 } \ 2220 } \ 2221 \ 2222 env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \ 2223 } 2224 2225 VSX_TSQRT(xstsqrtdp, 1, float64, VsrD(0), -1022, 52) 2226 VSX_TSQRT(xvtsqrtdp, 2, float64, VsrD(i), -1022, 52) 2227 VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23) 2228 2229 /* VSX_MADD - VSX floating point muliply/add variations 2230 * op - instruction mnemonic 2231 * nels - number of elements (1, 2 or 4) 2232 * tp - type (float32 or float64) 2233 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2234 * maddflgs - flags for the float*muladd routine that control the 2235 * various forms (madd, msub, nmadd, nmsub) 2236 * afrm - A form (1=A, 0=M) 2237 * sfprf - set FPRF 2238 */ 2239 #define VSX_MADD(op, nels, tp, fld, maddflgs, afrm, sfprf, r2sp) \ 2240 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2241 { \ 2242 ppc_vsr_t xt_in, xa, xb, xt_out; \ 2243 ppc_vsr_t *b, *c; \ 2244 int i; \ 2245 \ 2246 if (afrm) { /* AxB + T */ \ 2247 b = &xb; \ 2248 c = &xt_in; \ 2249 } else { /* AxT + B */ \ 2250 b = &xt_in; \ 2251 c = &xb; \ 2252 } \ 2253 \ 2254 getVSR(xA(opcode), &xa, env); \ 2255 getVSR(xB(opcode), &xb, env); \ 2256 getVSR(xT(opcode), &xt_in, env); \ 2257 \ 2258 xt_out = xt_in; \ 2259 \ 2260 helper_reset_fpstatus(env); \ 2261 \ 2262 for (i = 0; i < nels; i++) { \ 2263 float_status tstat = env->fp_status; \ 2264 set_float_exception_flags(0, &tstat); \ 2265 if (r2sp && (tstat.float_rounding_mode == float_round_nearest_even)) {\ 2266 /* Avoid double rounding errors by rounding the intermediate */ \ 2267 /* result to odd. */ \ 2268 set_float_rounding_mode(float_round_to_zero, &tstat); \ 2269 xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \ 2270 maddflgs, &tstat); \ 2271 xt_out.fld |= (get_float_exception_flags(&tstat) & \ 2272 float_flag_inexact) != 0; \ 2273 } else { \ 2274 xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \ 2275 maddflgs, &tstat); \ 2276 } \ 2277 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ 2278 \ 2279 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ 2280 tp##_maddsub_update_excp(env, xa.fld, b->fld, c->fld, maddflgs); \ 2281 } \ 2282 \ 2283 if (r2sp) { \ 2284 xt_out.fld = helper_frsp(env, xt_out.fld); \ 2285 } \ 2286 \ 2287 if (sfprf) { \ 2288 helper_compute_fprf_float64(env, xt_out.fld); \ 2289 } \ 2290 } \ 2291 putVSR(xT(opcode), &xt_out, env); \ 2292 float_check_status(env); \ 2293 } 2294 2295 VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0) 2296 VSX_MADD(xsmaddmdp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 0) 2297 VSX_MADD(xsmsubadp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 0) 2298 VSX_MADD(xsmsubmdp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 0) 2299 VSX_MADD(xsnmaddadp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 0) 2300 VSX_MADD(xsnmaddmdp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 0) 2301 VSX_MADD(xsnmsubadp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 0) 2302 VSX_MADD(xsnmsubmdp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 0) 2303 2304 VSX_MADD(xsmaddasp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 1) 2305 VSX_MADD(xsmaddmsp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 1) 2306 VSX_MADD(xsmsubasp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 1) 2307 VSX_MADD(xsmsubmsp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 1) 2308 VSX_MADD(xsnmaddasp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 1) 2309 VSX_MADD(xsnmaddmsp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 1) 2310 VSX_MADD(xsnmsubasp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 1) 2311 VSX_MADD(xsnmsubmsp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 1) 2312 2313 VSX_MADD(xvmaddadp, 2, float64, VsrD(i), MADD_FLGS, 1, 0, 0) 2314 VSX_MADD(xvmaddmdp, 2, float64, VsrD(i), MADD_FLGS, 0, 0, 0) 2315 VSX_MADD(xvmsubadp, 2, float64, VsrD(i), MSUB_FLGS, 1, 0, 0) 2316 VSX_MADD(xvmsubmdp, 2, float64, VsrD(i), MSUB_FLGS, 0, 0, 0) 2317 VSX_MADD(xvnmaddadp, 2, float64, VsrD(i), NMADD_FLGS, 1, 0, 0) 2318 VSX_MADD(xvnmaddmdp, 2, float64, VsrD(i), NMADD_FLGS, 0, 0, 0) 2319 VSX_MADD(xvnmsubadp, 2, float64, VsrD(i), NMSUB_FLGS, 1, 0, 0) 2320 VSX_MADD(xvnmsubmdp, 2, float64, VsrD(i), NMSUB_FLGS, 0, 0, 0) 2321 2322 VSX_MADD(xvmaddasp, 4, float32, VsrW(i), MADD_FLGS, 1, 0, 0) 2323 VSX_MADD(xvmaddmsp, 4, float32, VsrW(i), MADD_FLGS, 0, 0, 0) 2324 VSX_MADD(xvmsubasp, 4, float32, VsrW(i), MSUB_FLGS, 1, 0, 0) 2325 VSX_MADD(xvmsubmsp, 4, float32, VsrW(i), MSUB_FLGS, 0, 0, 0) 2326 VSX_MADD(xvnmaddasp, 4, float32, VsrW(i), NMADD_FLGS, 1, 0, 0) 2327 VSX_MADD(xvnmaddmsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0, 0) 2328 VSX_MADD(xvnmsubasp, 4, float32, VsrW(i), NMSUB_FLGS, 1, 0, 0) 2329 VSX_MADD(xvnmsubmsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0, 0) 2330 2331 /* VSX_SCALAR_CMP_DP - VSX scalar floating point compare double precision 2332 * op - instruction mnemonic 2333 * cmp - comparison operation 2334 * exp - expected result of comparison 2335 * svxvc - set VXVC bit 2336 */ 2337 #define VSX_SCALAR_CMP_DP(op, cmp, exp, svxvc) \ 2338 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2339 { \ 2340 ppc_vsr_t xt, xa, xb; \ 2341 bool vxsnan_flag = false, vxvc_flag = false, vex_flag = false; \ 2342 \ 2343 getVSR(xA(opcode), &xa, env); \ 2344 getVSR(xB(opcode), &xb, env); \ 2345 getVSR(xT(opcode), &xt, env); \ 2346 \ 2347 if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) || \ 2348 float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ 2349 vxsnan_flag = true; \ 2350 if (fpscr_ve == 0 && svxvc) { \ 2351 vxvc_flag = true; \ 2352 } \ 2353 } else if (svxvc) { \ 2354 vxvc_flag = float64_is_quiet_nan(xa.VsrD(0), &env->fp_status) || \ 2355 float64_is_quiet_nan(xb.VsrD(0), &env->fp_status); \ 2356 } \ 2357 if (vxsnan_flag) { \ 2358 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2359 } \ 2360 if (vxvc_flag) { \ 2361 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \ 2362 } \ 2363 vex_flag = fpscr_ve && (vxvc_flag || vxsnan_flag); \ 2364 \ 2365 if (!vex_flag) { \ 2366 if (float64_##cmp(xb.VsrD(0), xa.VsrD(0), &env->fp_status) == exp) { \ 2367 xt.VsrD(0) = -1; \ 2368 xt.VsrD(1) = 0; \ 2369 } else { \ 2370 xt.VsrD(0) = 0; \ 2371 xt.VsrD(1) = 0; \ 2372 } \ 2373 } \ 2374 putVSR(xT(opcode), &xt, env); \ 2375 helper_float_check_status(env); \ 2376 } 2377 2378 VSX_SCALAR_CMP_DP(xscmpeqdp, eq, 1, 0) 2379 VSX_SCALAR_CMP_DP(xscmpgedp, le, 1, 1) 2380 VSX_SCALAR_CMP_DP(xscmpgtdp, lt, 1, 1) 2381 VSX_SCALAR_CMP_DP(xscmpnedp, eq, 0, 0) 2382 2383 void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode) 2384 { 2385 ppc_vsr_t xa, xb; 2386 int64_t exp_a, exp_b; 2387 uint32_t cc; 2388 2389 getVSR(xA(opcode), &xa, env); 2390 getVSR(xB(opcode), &xb, env); 2391 2392 exp_a = extract64(xa.VsrD(0), 52, 11); 2393 exp_b = extract64(xb.VsrD(0), 52, 11); 2394 2395 if (unlikely(float64_is_any_nan(xa.VsrD(0)) || 2396 float64_is_any_nan(xb.VsrD(0)))) { 2397 cc = CRF_SO; 2398 } else { 2399 if (exp_a < exp_b) { 2400 cc = CRF_LT; 2401 } else if (exp_a > exp_b) { 2402 cc = CRF_GT; 2403 } else { 2404 cc = CRF_EQ; 2405 } 2406 } 2407 2408 env->fpscr &= ~(0x0F << FPSCR_FPRF); 2409 env->fpscr |= cc << FPSCR_FPRF; 2410 env->crf[BF(opcode)] = cc; 2411 2412 helper_float_check_status(env); 2413 } 2414 2415 void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode) 2416 { 2417 ppc_vsr_t xa, xb; 2418 int64_t exp_a, exp_b; 2419 uint32_t cc; 2420 2421 getVSR(rA(opcode) + 32, &xa, env); 2422 getVSR(rB(opcode) + 32, &xb, env); 2423 2424 exp_a = extract64(xa.VsrD(0), 48, 15); 2425 exp_b = extract64(xb.VsrD(0), 48, 15); 2426 2427 if (unlikely(float128_is_any_nan(xa.f128) || 2428 float128_is_any_nan(xb.f128))) { 2429 cc = CRF_SO; 2430 } else { 2431 if (exp_a < exp_b) { 2432 cc = CRF_LT; 2433 } else if (exp_a > exp_b) { 2434 cc = CRF_GT; 2435 } else { 2436 cc = CRF_EQ; 2437 } 2438 } 2439 2440 env->fpscr &= ~(0x0F << FPSCR_FPRF); 2441 env->fpscr |= cc << FPSCR_FPRF; 2442 env->crf[BF(opcode)] = cc; 2443 2444 helper_float_check_status(env); 2445 } 2446 2447 #define VSX_SCALAR_CMP(op, ordered) \ 2448 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2449 { \ 2450 ppc_vsr_t xa, xb; \ 2451 uint32_t cc = 0; \ 2452 bool vxsnan_flag = false, vxvc_flag = false; \ 2453 \ 2454 helper_reset_fpstatus(env); \ 2455 getVSR(xA(opcode), &xa, env); \ 2456 getVSR(xB(opcode), &xb, env); \ 2457 \ 2458 if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) || \ 2459 float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ 2460 vxsnan_flag = true; \ 2461 cc = CRF_SO; \ 2462 if (fpscr_ve == 0 && ordered) { \ 2463 vxvc_flag = true; \ 2464 } \ 2465 } else if (float64_is_quiet_nan(xa.VsrD(0), &env->fp_status) || \ 2466 float64_is_quiet_nan(xb.VsrD(0), &env->fp_status)) { \ 2467 cc = CRF_SO; \ 2468 if (ordered) { \ 2469 vxvc_flag = true; \ 2470 } \ 2471 } \ 2472 if (vxsnan_flag) { \ 2473 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2474 } \ 2475 if (vxvc_flag) { \ 2476 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \ 2477 } \ 2478 \ 2479 if (float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) { \ 2480 cc |= CRF_LT; \ 2481 } else if (!float64_le(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) { \ 2482 cc |= CRF_GT; \ 2483 } else { \ 2484 cc |= CRF_EQ; \ 2485 } \ 2486 \ 2487 env->fpscr &= ~(0x0F << FPSCR_FPRF); \ 2488 env->fpscr |= cc << FPSCR_FPRF; \ 2489 env->crf[BF(opcode)] = cc; \ 2490 \ 2491 float_check_status(env); \ 2492 } 2493 2494 VSX_SCALAR_CMP(xscmpodp, 1) 2495 VSX_SCALAR_CMP(xscmpudp, 0) 2496 2497 #define VSX_SCALAR_CMPQ(op, ordered) \ 2498 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2499 { \ 2500 ppc_vsr_t xa, xb; \ 2501 uint32_t cc = 0; \ 2502 bool vxsnan_flag = false, vxvc_flag = false; \ 2503 \ 2504 helper_reset_fpstatus(env); \ 2505 getVSR(rA(opcode) + 32, &xa, env); \ 2506 getVSR(rB(opcode) + 32, &xb, env); \ 2507 \ 2508 if (float128_is_signaling_nan(xa.f128, &env->fp_status) || \ 2509 float128_is_signaling_nan(xb.f128, &env->fp_status)) { \ 2510 vxsnan_flag = true; \ 2511 cc = CRF_SO; \ 2512 if (fpscr_ve == 0 && ordered) { \ 2513 vxvc_flag = true; \ 2514 } \ 2515 } else if (float128_is_quiet_nan(xa.f128, &env->fp_status) || \ 2516 float128_is_quiet_nan(xb.f128, &env->fp_status)) { \ 2517 cc = CRF_SO; \ 2518 if (ordered) { \ 2519 vxvc_flag = true; \ 2520 } \ 2521 } \ 2522 if (vxsnan_flag) { \ 2523 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2524 } \ 2525 if (vxvc_flag) { \ 2526 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \ 2527 } \ 2528 \ 2529 if (float128_lt(xa.f128, xb.f128, &env->fp_status)) { \ 2530 cc |= CRF_LT; \ 2531 } else if (!float128_le(xa.f128, xb.f128, &env->fp_status)) { \ 2532 cc |= CRF_GT; \ 2533 } else { \ 2534 cc |= CRF_EQ; \ 2535 } \ 2536 \ 2537 env->fpscr &= ~(0x0F << FPSCR_FPRF); \ 2538 env->fpscr |= cc << FPSCR_FPRF; \ 2539 env->crf[BF(opcode)] = cc; \ 2540 \ 2541 float_check_status(env); \ 2542 } 2543 2544 VSX_SCALAR_CMPQ(xscmpoqp, 1) 2545 VSX_SCALAR_CMPQ(xscmpuqp, 0) 2546 2547 /* VSX_MAX_MIN - VSX floating point maximum/minimum 2548 * name - instruction mnemonic 2549 * op - operation (max or min) 2550 * nels - number of elements (1, 2 or 4) 2551 * tp - type (float32 or float64) 2552 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2553 */ 2554 #define VSX_MAX_MIN(name, op, nels, tp, fld) \ 2555 void helper_##name(CPUPPCState *env, uint32_t opcode) \ 2556 { \ 2557 ppc_vsr_t xt, xa, xb; \ 2558 int i; \ 2559 \ 2560 getVSR(xA(opcode), &xa, env); \ 2561 getVSR(xB(opcode), &xb, env); \ 2562 getVSR(xT(opcode), &xt, env); \ 2563 \ 2564 for (i = 0; i < nels; i++) { \ 2565 xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status); \ 2566 if (unlikely(tp##_is_signaling_nan(xa.fld, &env->fp_status) || \ 2567 tp##_is_signaling_nan(xb.fld, &env->fp_status))) { \ 2568 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2569 } \ 2570 } \ 2571 \ 2572 putVSR(xT(opcode), &xt, env); \ 2573 float_check_status(env); \ 2574 } 2575 2576 VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0)) 2577 VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, VsrD(i)) 2578 VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, VsrW(i)) 2579 VSX_MAX_MIN(xsmindp, minnum, 1, float64, VsrD(0)) 2580 VSX_MAX_MIN(xvmindp, minnum, 2, float64, VsrD(i)) 2581 VSX_MAX_MIN(xvminsp, minnum, 4, float32, VsrW(i)) 2582 2583 #define VSX_MAX_MINC(name, max) \ 2584 void helper_##name(CPUPPCState *env, uint32_t opcode) \ 2585 { \ 2586 ppc_vsr_t xt, xa, xb; \ 2587 bool vxsnan_flag = false, vex_flag = false; \ 2588 \ 2589 getVSR(rA(opcode) + 32, &xa, env); \ 2590 getVSR(rB(opcode) + 32, &xb, env); \ 2591 getVSR(rD(opcode) + 32, &xt, env); \ 2592 \ 2593 if (unlikely(float64_is_any_nan(xa.VsrD(0)) || \ 2594 float64_is_any_nan(xb.VsrD(0)))) { \ 2595 if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) || \ 2596 float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ 2597 vxsnan_flag = true; \ 2598 } \ 2599 xt.VsrD(0) = xb.VsrD(0); \ 2600 } else if ((max && \ 2601 !float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) || \ 2602 (!max && \ 2603 float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status))) { \ 2604 xt.VsrD(0) = xa.VsrD(0); \ 2605 } else { \ 2606 xt.VsrD(0) = xb.VsrD(0); \ 2607 } \ 2608 \ 2609 vex_flag = fpscr_ve & vxsnan_flag; \ 2610 if (vxsnan_flag) { \ 2611 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2612 } \ 2613 if (!vex_flag) { \ 2614 putVSR(rD(opcode) + 32, &xt, env); \ 2615 } \ 2616 } \ 2617 2618 VSX_MAX_MINC(xsmaxcdp, 1); 2619 VSX_MAX_MINC(xsmincdp, 0); 2620 2621 #define VSX_MAX_MINJ(name, max) \ 2622 void helper_##name(CPUPPCState *env, uint32_t opcode) \ 2623 { \ 2624 ppc_vsr_t xt, xa, xb; \ 2625 bool vxsnan_flag = false, vex_flag = false; \ 2626 \ 2627 getVSR(rA(opcode) + 32, &xa, env); \ 2628 getVSR(rB(opcode) + 32, &xb, env); \ 2629 getVSR(rD(opcode) + 32, &xt, env); \ 2630 \ 2631 if (unlikely(float64_is_any_nan(xa.VsrD(0)))) { \ 2632 if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status)) { \ 2633 vxsnan_flag = true; \ 2634 } \ 2635 xt.VsrD(0) = xa.VsrD(0); \ 2636 } else if (unlikely(float64_is_any_nan(xb.VsrD(0)))) { \ 2637 if (float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ 2638 vxsnan_flag = true; \ 2639 } \ 2640 xt.VsrD(0) = xb.VsrD(0); \ 2641 } else if (float64_is_zero(xa.VsrD(0)) && float64_is_zero(xb.VsrD(0))) { \ 2642 if (max) { \ 2643 if (!float64_is_neg(xa.VsrD(0)) || !float64_is_neg(xb.VsrD(0))) { \ 2644 xt.VsrD(0) = 0ULL; \ 2645 } else { \ 2646 xt.VsrD(0) = 0x8000000000000000ULL; \ 2647 } \ 2648 } else { \ 2649 if (float64_is_neg(xa.VsrD(0)) || float64_is_neg(xb.VsrD(0))) { \ 2650 xt.VsrD(0) = 0x8000000000000000ULL; \ 2651 } else { \ 2652 xt.VsrD(0) = 0ULL; \ 2653 } \ 2654 } \ 2655 } else if ((max && \ 2656 !float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) || \ 2657 (!max && \ 2658 float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status))) { \ 2659 xt.VsrD(0) = xa.VsrD(0); \ 2660 } else { \ 2661 xt.VsrD(0) = xb.VsrD(0); \ 2662 } \ 2663 \ 2664 vex_flag = fpscr_ve & vxsnan_flag; \ 2665 if (vxsnan_flag) { \ 2666 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2667 } \ 2668 if (!vex_flag) { \ 2669 putVSR(rD(opcode) + 32, &xt, env); \ 2670 } \ 2671 } \ 2672 2673 VSX_MAX_MINJ(xsmaxjdp, 1); 2674 VSX_MAX_MINJ(xsminjdp, 0); 2675 2676 /* VSX_CMP - VSX floating point compare 2677 * op - instruction mnemonic 2678 * nels - number of elements (1, 2 or 4) 2679 * tp - type (float32 or float64) 2680 * fld - vsr_t field (VsrD(*) or VsrW(*)) 2681 * cmp - comparison operation 2682 * svxvc - set VXVC bit 2683 * exp - expected result of comparison 2684 */ 2685 #define VSX_CMP(op, nels, tp, fld, cmp, svxvc, exp) \ 2686 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2687 { \ 2688 ppc_vsr_t xt, xa, xb; \ 2689 int i; \ 2690 int all_true = 1; \ 2691 int all_false = 1; \ 2692 \ 2693 getVSR(xA(opcode), &xa, env); \ 2694 getVSR(xB(opcode), &xb, env); \ 2695 getVSR(xT(opcode), &xt, env); \ 2696 \ 2697 for (i = 0; i < nels; i++) { \ 2698 if (unlikely(tp##_is_any_nan(xa.fld) || \ 2699 tp##_is_any_nan(xb.fld))) { \ 2700 if (tp##_is_signaling_nan(xa.fld, &env->fp_status) || \ 2701 tp##_is_signaling_nan(xb.fld, &env->fp_status)) { \ 2702 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2703 } \ 2704 if (svxvc) { \ 2705 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \ 2706 } \ 2707 xt.fld = 0; \ 2708 all_true = 0; \ 2709 } else { \ 2710 if (tp##_##cmp(xb.fld, xa.fld, &env->fp_status) == exp) { \ 2711 xt.fld = -1; \ 2712 all_false = 0; \ 2713 } else { \ 2714 xt.fld = 0; \ 2715 all_true = 0; \ 2716 } \ 2717 } \ 2718 } \ 2719 \ 2720 putVSR(xT(opcode), &xt, env); \ 2721 if ((opcode >> (31-21)) & 1) { \ 2722 env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0); \ 2723 } \ 2724 float_check_status(env); \ 2725 } 2726 2727 VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0, 1) 2728 VSX_CMP(xvcmpgedp, 2, float64, VsrD(i), le, 1, 1) 2729 VSX_CMP(xvcmpgtdp, 2, float64, VsrD(i), lt, 1, 1) 2730 VSX_CMP(xvcmpnedp, 2, float64, VsrD(i), eq, 0, 0) 2731 VSX_CMP(xvcmpeqsp, 4, float32, VsrW(i), eq, 0, 1) 2732 VSX_CMP(xvcmpgesp, 4, float32, VsrW(i), le, 1, 1) 2733 VSX_CMP(xvcmpgtsp, 4, float32, VsrW(i), lt, 1, 1) 2734 VSX_CMP(xvcmpnesp, 4, float32, VsrW(i), eq, 0, 0) 2735 2736 /* VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion 2737 * op - instruction mnemonic 2738 * nels - number of elements (1, 2 or 4) 2739 * stp - source type (float32 or float64) 2740 * ttp - target type (float32 or float64) 2741 * sfld - source vsr_t field 2742 * tfld - target vsr_t field (f32 or f64) 2743 * sfprf - set FPRF 2744 */ 2745 #define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf) \ 2746 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2747 { \ 2748 ppc_vsr_t xt, xb; \ 2749 int i; \ 2750 \ 2751 getVSR(xB(opcode), &xb, env); \ 2752 getVSR(xT(opcode), &xt, env); \ 2753 \ 2754 for (i = 0; i < nels; i++) { \ 2755 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ 2756 if (unlikely(stp##_is_signaling_nan(xb.sfld, \ 2757 &env->fp_status))) { \ 2758 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2759 xt.tfld = ttp##_snan_to_qnan(xt.tfld); \ 2760 } \ 2761 if (sfprf) { \ 2762 helper_compute_fprf_##ttp(env, xt.tfld); \ 2763 } \ 2764 } \ 2765 \ 2766 putVSR(xT(opcode), &xt, env); \ 2767 float_check_status(env); \ 2768 } 2769 2770 VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1) 2771 VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, VsrW(0), VsrD(0), 1) 2772 VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, VsrD(i), VsrW(2*i), 0) 2773 VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2*i), VsrD(i), 0) 2774 2775 /* VSX_CVT_FP_TO_FP_VECTOR - VSX floating point/floating point conversion 2776 * op - instruction mnemonic 2777 * nels - number of elements (1, 2 or 4) 2778 * stp - source type (float32 or float64) 2779 * ttp - target type (float32 or float64) 2780 * sfld - source vsr_t field 2781 * tfld - target vsr_t field (f32 or f64) 2782 * sfprf - set FPRF 2783 */ 2784 #define VSX_CVT_FP_TO_FP_VECTOR(op, nels, stp, ttp, sfld, tfld, sfprf) \ 2785 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2786 { \ 2787 ppc_vsr_t xt, xb; \ 2788 int i; \ 2789 \ 2790 getVSR(rB(opcode) + 32, &xb, env); \ 2791 getVSR(rD(opcode) + 32, &xt, env); \ 2792 \ 2793 for (i = 0; i < nels; i++) { \ 2794 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ 2795 if (unlikely(stp##_is_signaling_nan(xb.sfld, \ 2796 &env->fp_status))) { \ 2797 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2798 xt.tfld = ttp##_snan_to_qnan(xt.tfld); \ 2799 } \ 2800 if (sfprf) { \ 2801 helper_compute_fprf_##ttp(env, xt.tfld); \ 2802 } \ 2803 } \ 2804 \ 2805 putVSR(rD(opcode) + 32, &xt, env); \ 2806 float_check_status(env); \ 2807 } 2808 2809 VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1) 2810 2811 /* VSX_CVT_FP_TO_FP_HP - VSX floating point/floating point conversion 2812 * involving one half precision value 2813 * op - instruction mnemonic 2814 * nels - number of elements (1, 2 or 4) 2815 * stp - source type 2816 * ttp - target type 2817 * sfld - source vsr_t field 2818 * tfld - target vsr_t field 2819 * sfprf - set FPRF 2820 */ 2821 #define VSX_CVT_FP_TO_FP_HP(op, nels, stp, ttp, sfld, tfld, sfprf) \ 2822 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2823 { \ 2824 ppc_vsr_t xt, xb; \ 2825 int i; \ 2826 \ 2827 getVSR(xB(opcode), &xb, env); \ 2828 memset(&xt, 0, sizeof(xt)); \ 2829 \ 2830 for (i = 0; i < nels; i++) { \ 2831 xt.tfld = stp##_to_##ttp(xb.sfld, 1, &env->fp_status); \ 2832 if (unlikely(stp##_is_signaling_nan(xb.sfld, \ 2833 &env->fp_status))) { \ 2834 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2835 xt.tfld = ttp##_snan_to_qnan(xt.tfld); \ 2836 } \ 2837 if (sfprf) { \ 2838 helper_compute_fprf_##ttp(env, xt.tfld); \ 2839 } \ 2840 } \ 2841 \ 2842 putVSR(xT(opcode), &xt, env); \ 2843 float_check_status(env); \ 2844 } 2845 2846 VSX_CVT_FP_TO_FP_HP(xscvdphp, 1, float64, float16, VsrD(0), VsrH(3), 1) 2847 VSX_CVT_FP_TO_FP_HP(xscvhpdp, 1, float16, float64, VsrH(3), VsrD(0), 1) 2848 VSX_CVT_FP_TO_FP_HP(xvcvsphp, 4, float32, float16, VsrW(i), VsrH(2 * i + 1), 0) 2849 VSX_CVT_FP_TO_FP_HP(xvcvhpsp, 4, float16, float32, VsrH(2 * i + 1), VsrW(i), 0) 2850 2851 /* 2852 * xscvqpdp isn't using VSX_CVT_FP_TO_FP() because xscvqpdpo will be 2853 * added to this later. 2854 */ 2855 void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode) 2856 { 2857 ppc_vsr_t xt, xb; 2858 float_status tstat; 2859 2860 getVSR(rB(opcode) + 32, &xb, env); 2861 memset(&xt, 0, sizeof(xt)); 2862 2863 tstat = env->fp_status; 2864 if (unlikely(Rc(opcode) != 0)) { 2865 tstat.float_rounding_mode = float_round_to_odd; 2866 } 2867 2868 xt.VsrD(0) = float128_to_float64(xb.f128, &tstat); 2869 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 2870 if (unlikely(float128_is_signaling_nan(xb.f128, 2871 &tstat))) { 2872 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); 2873 xt.VsrD(0) = float64_snan_to_qnan(xt.VsrD(0)); 2874 } 2875 helper_compute_fprf_float64(env, xt.VsrD(0)); 2876 2877 putVSR(rD(opcode) + 32, &xt, env); 2878 float_check_status(env); 2879 } 2880 2881 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb) 2882 { 2883 float_status tstat = env->fp_status; 2884 set_float_exception_flags(0, &tstat); 2885 2886 return (uint64_t)float64_to_float32(xb, &tstat) << 32; 2887 } 2888 2889 uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb) 2890 { 2891 float_status tstat = env->fp_status; 2892 set_float_exception_flags(0, &tstat); 2893 2894 return float32_to_float64(xb >> 32, &tstat); 2895 } 2896 2897 /* VSX_CVT_FP_TO_INT - VSX floating point to integer conversion 2898 * op - instruction mnemonic 2899 * nels - number of elements (1, 2 or 4) 2900 * stp - source type (float32 or float64) 2901 * ttp - target type (int32, uint32, int64 or uint64) 2902 * sfld - source vsr_t field 2903 * tfld - target vsr_t field 2904 * rnan - resulting NaN 2905 */ 2906 #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan) \ 2907 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2908 { \ 2909 ppc_vsr_t xt, xb; \ 2910 int i; \ 2911 \ 2912 getVSR(xB(opcode), &xb, env); \ 2913 getVSR(xT(opcode), &xt, env); \ 2914 \ 2915 for (i = 0; i < nels; i++) { \ 2916 if (unlikely(stp##_is_any_nan(xb.sfld))) { \ 2917 if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) { \ 2918 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2919 } \ 2920 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \ 2921 xt.tfld = rnan; \ 2922 } else { \ 2923 xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, \ 2924 &env->fp_status); \ 2925 if (env->fp_status.float_exception_flags & float_flag_invalid) { \ 2926 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \ 2927 } \ 2928 } \ 2929 } \ 2930 \ 2931 putVSR(xT(opcode), &xt, env); \ 2932 float_check_status(env); \ 2933 } 2934 2935 VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \ 2936 0x8000000000000000ULL) 2937 VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, VsrD(0), VsrW(1), \ 2938 0x80000000U) 2939 VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), 0ULL) 2940 VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, VsrD(0), VsrW(1), 0U) 2941 VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), \ 2942 0x8000000000000000ULL) 2943 VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, VsrD(i), VsrW(2*i), \ 2944 0x80000000U) 2945 VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), 0ULL) 2946 VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, VsrD(i), VsrW(2*i), 0U) 2947 VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2*i), VsrD(i), \ 2948 0x8000000000000000ULL) 2949 VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U) 2950 VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2*i), VsrD(i), 0ULL) 2951 VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U) 2952 2953 /* VSX_CVT_FP_TO_INT_VECTOR - VSX floating point to integer conversion 2954 * op - instruction mnemonic 2955 * stp - source type (float32 or float64) 2956 * ttp - target type (int32, uint32, int64 or uint64) 2957 * sfld - source vsr_t field 2958 * tfld - target vsr_t field 2959 * rnan - resulting NaN 2960 */ 2961 #define VSX_CVT_FP_TO_INT_VECTOR(op, stp, ttp, sfld, tfld, rnan) \ 2962 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 2963 { \ 2964 ppc_vsr_t xt, xb; \ 2965 \ 2966 getVSR(rB(opcode) + 32, &xb, env); \ 2967 memset(&xt, 0, sizeof(xt)); \ 2968 \ 2969 if (unlikely(stp##_is_any_nan(xb.sfld))) { \ 2970 if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) { \ 2971 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 2972 } \ 2973 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \ 2974 xt.tfld = rnan; \ 2975 } else { \ 2976 xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, \ 2977 &env->fp_status); \ 2978 if (env->fp_status.float_exception_flags & float_flag_invalid) { \ 2979 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \ 2980 } \ 2981 } \ 2982 \ 2983 putVSR(rD(opcode) + 32, &xt, env); \ 2984 float_check_status(env); \ 2985 } 2986 2987 VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0), \ 2988 0x8000000000000000ULL) 2989 2990 VSX_CVT_FP_TO_INT_VECTOR(xscvqpswz, float128, int32, f128, VsrD(0), \ 2991 0xffffffff80000000ULL) 2992 VSX_CVT_FP_TO_INT_VECTOR(xscvqpudz, float128, uint64, f128, VsrD(0), 0x0ULL) 2993 VSX_CVT_FP_TO_INT_VECTOR(xscvqpuwz, float128, uint32, f128, VsrD(0), 0x0ULL) 2994 2995 /* VSX_CVT_INT_TO_FP - VSX integer to floating point conversion 2996 * op - instruction mnemonic 2997 * nels - number of elements (1, 2 or 4) 2998 * stp - source type (int32, uint32, int64 or uint64) 2999 * ttp - target type (float32 or float64) 3000 * sfld - source vsr_t field 3001 * tfld - target vsr_t field 3002 * jdef - definition of the j index (i or 2*i) 3003 * sfprf - set FPRF 3004 */ 3005 #define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf, r2sp) \ 3006 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 3007 { \ 3008 ppc_vsr_t xt, xb; \ 3009 int i; \ 3010 \ 3011 getVSR(xB(opcode), &xb, env); \ 3012 getVSR(xT(opcode), &xt, env); \ 3013 \ 3014 for (i = 0; i < nels; i++) { \ 3015 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ 3016 if (r2sp) { \ 3017 xt.tfld = helper_frsp(env, xt.tfld); \ 3018 } \ 3019 if (sfprf) { \ 3020 helper_compute_fprf_float64(env, xt.tfld); \ 3021 } \ 3022 } \ 3023 \ 3024 putVSR(xT(opcode), &xt, env); \ 3025 float_check_status(env); \ 3026 } 3027 3028 VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0) 3029 VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 0) 3030 VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, VsrD(0), VsrD(0), 1, 1) 3031 VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 1) 3032 VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, VsrD(i), VsrD(i), 0, 0) 3033 VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, VsrD(i), VsrD(i), 0, 0) 3034 VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, VsrW(2*i), VsrD(i), 0, 0) 3035 VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, VsrW(2*i), VsrD(i), 0, 0) 3036 VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, VsrD(i), VsrW(2*i), 0, 0) 3037 VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, VsrD(i), VsrW(2*i), 0, 0) 3038 VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, VsrW(i), VsrW(i), 0, 0) 3039 VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, VsrW(i), VsrW(i), 0, 0) 3040 3041 /* VSX_CVT_INT_TO_FP_VECTOR - VSX integer to floating point conversion 3042 * op - instruction mnemonic 3043 * stp - source type (int32, uint32, int64 or uint64) 3044 * ttp - target type (float32 or float64) 3045 * sfld - source vsr_t field 3046 * tfld - target vsr_t field 3047 */ 3048 #define VSX_CVT_INT_TO_FP_VECTOR(op, stp, ttp, sfld, tfld) \ 3049 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 3050 { \ 3051 ppc_vsr_t xt, xb; \ 3052 \ 3053 getVSR(rB(opcode) + 32, &xb, env); \ 3054 getVSR(rD(opcode) + 32, &xt, env); \ 3055 \ 3056 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ 3057 helper_compute_fprf_##ttp(env, xt.tfld); \ 3058 \ 3059 putVSR(xT(opcode) + 32, &xt, env); \ 3060 float_check_status(env); \ 3061 } 3062 3063 VSX_CVT_INT_TO_FP_VECTOR(xscvsdqp, int64, float128, VsrD(0), f128) 3064 VSX_CVT_INT_TO_FP_VECTOR(xscvudqp, uint64, float128, VsrD(0), f128) 3065 3066 /* For "use current rounding mode", define a value that will not be one of 3067 * the existing rounding model enums. 3068 */ 3069 #define FLOAT_ROUND_CURRENT (float_round_nearest_even + float_round_down + \ 3070 float_round_up + float_round_to_zero) 3071 3072 /* VSX_ROUND - VSX floating point round 3073 * op - instruction mnemonic 3074 * nels - number of elements (1, 2 or 4) 3075 * tp - type (float32 or float64) 3076 * fld - vsr_t field (VsrD(*) or VsrW(*)) 3077 * rmode - rounding mode 3078 * sfprf - set FPRF 3079 */ 3080 #define VSX_ROUND(op, nels, tp, fld, rmode, sfprf) \ 3081 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 3082 { \ 3083 ppc_vsr_t xt, xb; \ 3084 int i; \ 3085 getVSR(xB(opcode), &xb, env); \ 3086 getVSR(xT(opcode), &xt, env); \ 3087 \ 3088 if (rmode != FLOAT_ROUND_CURRENT) { \ 3089 set_float_rounding_mode(rmode, &env->fp_status); \ 3090 } \ 3091 \ 3092 for (i = 0; i < nels; i++) { \ 3093 if (unlikely(tp##_is_signaling_nan(xb.fld, \ 3094 &env->fp_status))) { \ 3095 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ 3096 xt.fld = tp##_snan_to_qnan(xb.fld); \ 3097 } else { \ 3098 xt.fld = tp##_round_to_int(xb.fld, &env->fp_status); \ 3099 } \ 3100 if (sfprf) { \ 3101 helper_compute_fprf_float64(env, xt.fld); \ 3102 } \ 3103 } \ 3104 \ 3105 /* If this is not a "use current rounding mode" instruction, \ 3106 * then inhibit setting of the XX bit and restore rounding \ 3107 * mode from FPSCR */ \ 3108 if (rmode != FLOAT_ROUND_CURRENT) { \ 3109 fpscr_set_rounding_mode(env); \ 3110 env->fp_status.float_exception_flags &= ~float_flag_inexact; \ 3111 } \ 3112 \ 3113 putVSR(xT(opcode), &xt, env); \ 3114 float_check_status(env); \ 3115 } 3116 3117 VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_ties_away, 1) 3118 VSX_ROUND(xsrdpic, 1, float64, VsrD(0), FLOAT_ROUND_CURRENT, 1) 3119 VSX_ROUND(xsrdpim, 1, float64, VsrD(0), float_round_down, 1) 3120 VSX_ROUND(xsrdpip, 1, float64, VsrD(0), float_round_up, 1) 3121 VSX_ROUND(xsrdpiz, 1, float64, VsrD(0), float_round_to_zero, 1) 3122 3123 VSX_ROUND(xvrdpi, 2, float64, VsrD(i), float_round_ties_away, 0) 3124 VSX_ROUND(xvrdpic, 2, float64, VsrD(i), FLOAT_ROUND_CURRENT, 0) 3125 VSX_ROUND(xvrdpim, 2, float64, VsrD(i), float_round_down, 0) 3126 VSX_ROUND(xvrdpip, 2, float64, VsrD(i), float_round_up, 0) 3127 VSX_ROUND(xvrdpiz, 2, float64, VsrD(i), float_round_to_zero, 0) 3128 3129 VSX_ROUND(xvrspi, 4, float32, VsrW(i), float_round_ties_away, 0) 3130 VSX_ROUND(xvrspic, 4, float32, VsrW(i), FLOAT_ROUND_CURRENT, 0) 3131 VSX_ROUND(xvrspim, 4, float32, VsrW(i), float_round_down, 0) 3132 VSX_ROUND(xvrspip, 4, float32, VsrW(i), float_round_up, 0) 3133 VSX_ROUND(xvrspiz, 4, float32, VsrW(i), float_round_to_zero, 0) 3134 3135 uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb) 3136 { 3137 helper_reset_fpstatus(env); 3138 3139 uint64_t xt = helper_frsp(env, xb); 3140 3141 helper_compute_fprf_float64(env, xt); 3142 float_check_status(env); 3143 return xt; 3144 } 3145 3146 #define VSX_XXPERM(op, indexed) \ 3147 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 3148 { \ 3149 ppc_vsr_t xt, xa, pcv, xto; \ 3150 int i, idx; \ 3151 \ 3152 getVSR(xA(opcode), &xa, env); \ 3153 getVSR(xT(opcode), &xt, env); \ 3154 getVSR(xB(opcode), &pcv, env); \ 3155 \ 3156 for (i = 0; i < 16; i++) { \ 3157 idx = pcv.VsrB(i) & 0x1F; \ 3158 if (indexed) { \ 3159 idx = 31 - idx; \ 3160 } \ 3161 xto.VsrB(i) = (idx <= 15) ? xa.VsrB(idx) : xt.VsrB(idx - 16); \ 3162 } \ 3163 putVSR(xT(opcode), &xto, env); \ 3164 } 3165 3166 VSX_XXPERM(xxperm, 0) 3167 VSX_XXPERM(xxpermr, 1) 3168 3169 void helper_xvxsigsp(CPUPPCState *env, uint32_t opcode) 3170 { 3171 ppc_vsr_t xt, xb; 3172 uint32_t exp, i, fraction; 3173 3174 getVSR(xB(opcode), &xb, env); 3175 memset(&xt, 0, sizeof(xt)); 3176 3177 for (i = 0; i < 4; i++) { 3178 exp = (xb.VsrW(i) >> 23) & 0xFF; 3179 fraction = xb.VsrW(i) & 0x7FFFFF; 3180 if (exp != 0 && exp != 255) { 3181 xt.VsrW(i) = fraction | 0x00800000; 3182 } else { 3183 xt.VsrW(i) = fraction; 3184 } 3185 } 3186 putVSR(xT(opcode), &xt, env); 3187 } 3188 3189 /* VSX_TEST_DC - VSX floating point test data class 3190 * op - instruction mnemonic 3191 * nels - number of elements (1, 2 or 4) 3192 * xbn - VSR register number 3193 * tp - type (float32 or float64) 3194 * fld - vsr_t field (VsrD(*) or VsrW(*)) 3195 * tfld - target vsr_t field (VsrD(*) or VsrW(*)) 3196 * fld_max - target field max 3197 * scrf - set result in CR and FPCC 3198 */ 3199 #define VSX_TEST_DC(op, nels, xbn, tp, fld, tfld, fld_max, scrf) \ 3200 void helper_##op(CPUPPCState *env, uint32_t opcode) \ 3201 { \ 3202 ppc_vsr_t xt, xb; \ 3203 uint32_t i, sign, dcmx; \ 3204 uint32_t cc, match = 0; \ 3205 \ 3206 getVSR(xbn, &xb, env); \ 3207 if (!scrf) { \ 3208 memset(&xt, 0, sizeof(xt)); \ 3209 dcmx = DCMX_XV(opcode); \ 3210 } else { \ 3211 dcmx = DCMX(opcode); \ 3212 } \ 3213 \ 3214 for (i = 0; i < nels; i++) { \ 3215 sign = tp##_is_neg(xb.fld); \ 3216 if (tp##_is_any_nan(xb.fld)) { \ 3217 match = extract32(dcmx, 6, 1); \ 3218 } else if (tp##_is_infinity(xb.fld)) { \ 3219 match = extract32(dcmx, 4 + !sign, 1); \ 3220 } else if (tp##_is_zero(xb.fld)) { \ 3221 match = extract32(dcmx, 2 + !sign, 1); \ 3222 } else if (tp##_is_zero_or_denormal(xb.fld)) { \ 3223 match = extract32(dcmx, 0 + !sign, 1); \ 3224 } \ 3225 \ 3226 if (scrf) { \ 3227 cc = sign << CRF_LT_BIT | match << CRF_EQ_BIT; \ 3228 env->fpscr &= ~(0x0F << FPSCR_FPRF); \ 3229 env->fpscr |= cc << FPSCR_FPRF; \ 3230 env->crf[BF(opcode)] = cc; \ 3231 } else { \ 3232 xt.tfld = match ? fld_max : 0; \ 3233 } \ 3234 match = 0; \ 3235 } \ 3236 if (!scrf) { \ 3237 putVSR(xT(opcode), &xt, env); \ 3238 } \ 3239 } 3240 3241 VSX_TEST_DC(xvtstdcdp, 2, xB(opcode), float64, VsrD(i), VsrD(i), UINT64_MAX, 0) 3242 VSX_TEST_DC(xvtstdcsp, 4, xB(opcode), float32, VsrW(i), VsrW(i), UINT32_MAX, 0) 3243 VSX_TEST_DC(xststdcdp, 1, xB(opcode), float64, VsrD(0), VsrD(0), 0, 1) 3244 VSX_TEST_DC(xststdcqp, 1, (rB(opcode) + 32), float128, f128, VsrD(0), 0, 1) 3245 3246 void helper_xststdcsp(CPUPPCState *env, uint32_t opcode) 3247 { 3248 ppc_vsr_t xb; 3249 uint32_t dcmx, sign, exp; 3250 uint32_t cc, match = 0, not_sp = 0; 3251 3252 getVSR(xB(opcode), &xb, env); 3253 dcmx = DCMX(opcode); 3254 exp = (xb.VsrD(0) >> 52) & 0x7FF; 3255 3256 sign = float64_is_neg(xb.VsrD(0)); 3257 if (float64_is_any_nan(xb.VsrD(0))) { 3258 match = extract32(dcmx, 6, 1); 3259 } else if (float64_is_infinity(xb.VsrD(0))) { 3260 match = extract32(dcmx, 4 + !sign, 1); 3261 } else if (float64_is_zero(xb.VsrD(0))) { 3262 match = extract32(dcmx, 2 + !sign, 1); 3263 } else if (float64_is_zero_or_denormal(xb.VsrD(0)) || 3264 (exp > 0 && exp < 0x381)) { 3265 match = extract32(dcmx, 0 + !sign, 1); 3266 } 3267 3268 not_sp = !float64_eq(xb.VsrD(0), 3269 float32_to_float64( 3270 float64_to_float32(xb.VsrD(0), &env->fp_status), 3271 &env->fp_status), &env->fp_status); 3272 3273 cc = sign << CRF_LT_BIT | match << CRF_EQ_BIT | not_sp << CRF_SO_BIT; 3274 env->fpscr &= ~(0x0F << FPSCR_FPRF); 3275 env->fpscr |= cc << FPSCR_FPRF; 3276 env->crf[BF(opcode)] = cc; 3277 } 3278 3279 void helper_xsrqpi(CPUPPCState *env, uint32_t opcode) 3280 { 3281 ppc_vsr_t xb; 3282 ppc_vsr_t xt; 3283 uint8_t r = Rrm(opcode); 3284 uint8_t ex = Rc(opcode); 3285 uint8_t rmc = RMC(opcode); 3286 uint8_t rmode = 0; 3287 float_status tstat; 3288 3289 getVSR(rB(opcode) + 32, &xb, env); 3290 memset(&xt, 0, sizeof(xt)); 3291 helper_reset_fpstatus(env); 3292 3293 if (r == 0 && rmc == 0) { 3294 rmode = float_round_ties_away; 3295 } else if (r == 0 && rmc == 0x3) { 3296 rmode = fpscr_rn; 3297 } else if (r == 1) { 3298 switch (rmc) { 3299 case 0: 3300 rmode = float_round_nearest_even; 3301 break; 3302 case 1: 3303 rmode = float_round_to_zero; 3304 break; 3305 case 2: 3306 rmode = float_round_up; 3307 break; 3308 case 3: 3309 rmode = float_round_down; 3310 break; 3311 default: 3312 abort(); 3313 } 3314 } 3315 3316 tstat = env->fp_status; 3317 set_float_exception_flags(0, &tstat); 3318 set_float_rounding_mode(rmode, &tstat); 3319 xt.f128 = float128_round_to_int(xb.f128, &tstat); 3320 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 3321 3322 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 3323 if (float128_is_signaling_nan(xb.f128, &tstat)) { 3324 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); 3325 xt.f128 = float128_snan_to_qnan(xt.f128); 3326 } 3327 } 3328 3329 if (ex == 0 && (tstat.float_exception_flags & float_flag_inexact)) { 3330 env->fp_status.float_exception_flags &= ~float_flag_inexact; 3331 } 3332 3333 helper_compute_fprf_float128(env, xt.f128); 3334 float_check_status(env); 3335 putVSR(rD(opcode) + 32, &xt, env); 3336 } 3337 3338 void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode) 3339 { 3340 ppc_vsr_t xb; 3341 ppc_vsr_t xt; 3342 uint8_t r = Rrm(opcode); 3343 uint8_t rmc = RMC(opcode); 3344 uint8_t rmode = 0; 3345 floatx80 round_res; 3346 float_status tstat; 3347 3348 getVSR(rB(opcode) + 32, &xb, env); 3349 memset(&xt, 0, sizeof(xt)); 3350 helper_reset_fpstatus(env); 3351 3352 if (r == 0 && rmc == 0) { 3353 rmode = float_round_ties_away; 3354 } else if (r == 0 && rmc == 0x3) { 3355 rmode = fpscr_rn; 3356 } else if (r == 1) { 3357 switch (rmc) { 3358 case 0: 3359 rmode = float_round_nearest_even; 3360 break; 3361 case 1: 3362 rmode = float_round_to_zero; 3363 break; 3364 case 2: 3365 rmode = float_round_up; 3366 break; 3367 case 3: 3368 rmode = float_round_down; 3369 break; 3370 default: 3371 abort(); 3372 } 3373 } 3374 3375 tstat = env->fp_status; 3376 set_float_exception_flags(0, &tstat); 3377 set_float_rounding_mode(rmode, &tstat); 3378 round_res = float128_to_floatx80(xb.f128, &tstat); 3379 xt.f128 = floatx80_to_float128(round_res, &tstat); 3380 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 3381 3382 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 3383 if (float128_is_signaling_nan(xb.f128, &tstat)) { 3384 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); 3385 xt.f128 = float128_snan_to_qnan(xt.f128); 3386 } 3387 } 3388 3389 helper_compute_fprf_float128(env, xt.f128); 3390 putVSR(rD(opcode) + 32, &xt, env); 3391 float_check_status(env); 3392 } 3393 3394 void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode) 3395 { 3396 ppc_vsr_t xb; 3397 ppc_vsr_t xt; 3398 float_status tstat; 3399 3400 getVSR(rB(opcode) + 32, &xb, env); 3401 memset(&xt, 0, sizeof(xt)); 3402 helper_reset_fpstatus(env); 3403 3404 tstat = env->fp_status; 3405 if (unlikely(Rc(opcode) != 0)) { 3406 tstat.float_rounding_mode = float_round_to_odd; 3407 } 3408 3409 set_float_exception_flags(0, &tstat); 3410 xt.f128 = float128_sqrt(xb.f128, &tstat); 3411 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 3412 3413 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 3414 if (float128_is_signaling_nan(xb.f128, &tstat)) { 3415 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 3416 xt.f128 = float128_snan_to_qnan(xb.f128); 3417 } else if (float128_is_quiet_nan(xb.f128, &tstat)) { 3418 xt.f128 = xb.f128; 3419 } else if (float128_is_neg(xb.f128) && !float128_is_zero(xb.f128)) { 3420 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1); 3421 xt.f128 = float128_default_nan(&env->fp_status); 3422 } 3423 } 3424 3425 helper_compute_fprf_float128(env, xt.f128); 3426 putVSR(rD(opcode) + 32, &xt, env); 3427 float_check_status(env); 3428 } 3429 3430 void helper_xssubqp(CPUPPCState *env, uint32_t opcode) 3431 { 3432 ppc_vsr_t xt, xa, xb; 3433 float_status tstat; 3434 3435 getVSR(rA(opcode) + 32, &xa, env); 3436 getVSR(rB(opcode) + 32, &xb, env); 3437 getVSR(rD(opcode) + 32, &xt, env); 3438 helper_reset_fpstatus(env); 3439 3440 tstat = env->fp_status; 3441 if (unlikely(Rc(opcode) != 0)) { 3442 tstat.float_rounding_mode = float_round_to_odd; 3443 } 3444 3445 set_float_exception_flags(0, &tstat); 3446 xt.f128 = float128_sub(xa.f128, xb.f128, &tstat); 3447 env->fp_status.float_exception_flags |= tstat.float_exception_flags; 3448 3449 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { 3450 if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) { 3451 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); 3452 } else if (float128_is_signaling_nan(xa.f128, &tstat) || 3453 float128_is_signaling_nan(xb.f128, &tstat)) { 3454 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); 3455 } 3456 } 3457 3458 helper_compute_fprf_float128(env, xt.f128); 3459 putVSR(rD(opcode) + 32, &xt, env); 3460 float_check_status(env); 3461 } 3462