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