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