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