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