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