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