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