qemu/target-ppc/fpu_helper.c
<<
>>
Prefs
   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 "cpu.h"
  20#include "helper.h"
  21
  22/*****************************************************************************/
  23/* Floating point operations helpers */
  24uint64_t helper_float32_to_float64(CPUPPCState *env, uint32_t arg)
  25{
  26    CPU_FloatU f;
  27    CPU_DoubleU d;
  28
  29    f.l = arg;
  30    d.d = float32_to_float64(f.f, &env->fp_status);
  31    return d.ll;
  32}
  33
  34uint32_t helper_float64_to_float32(CPUPPCState *env, uint64_t arg)
  35{
  36    CPU_FloatU f;
  37    CPU_DoubleU d;
  38
  39    d.ll = arg;
  40    f.f = float64_to_float32(d.d, &env->fp_status);
  41    return f.l;
  42}
  43
  44static inline int isden(float64 d)
  45{
  46    CPU_DoubleU u;
  47
  48    u.d = d;
  49
  50    return ((u.ll >> 52) & 0x7FF) == 0;
  51}
  52
  53uint32_t helper_compute_fprf(CPUPPCState *env, uint64_t arg, uint32_t set_fprf)
  54{
  55    CPU_DoubleU farg;
  56    int isneg;
  57    int ret;
  58
  59    farg.ll = arg;
  60    isneg = float64_is_neg(farg.d);
  61    if (unlikely(float64_is_any_nan(farg.d))) {
  62        if (float64_is_signaling_nan(farg.d)) {
  63            /* Signaling NaN: flags are undefined */
  64            ret = 0x00;
  65        } else {
  66            /* Quiet NaN */
  67            ret = 0x11;
  68        }
  69    } else if (unlikely(float64_is_infinity(farg.d))) {
  70        /* +/- infinity */
  71        if (isneg) {
  72            ret = 0x09;
  73        } else {
  74            ret = 0x05;
  75        }
  76    } else {
  77        if (float64_is_zero(farg.d)) {
  78            /* +/- zero */
  79            if (isneg) {
  80                ret = 0x12;
  81            } else {
  82                ret = 0x02;
  83            }
  84        } else {
  85            if (isden(farg.d)) {
  86                /* Denormalized numbers */
  87                ret = 0x10;
  88            } else {
  89                /* Normalized numbers */
  90                ret = 0x00;
  91            }
  92            if (isneg) {
  93                ret |= 0x08;
  94            } else {
  95                ret |= 0x04;
  96            }
  97        }
  98    }
  99    if (set_fprf) {
 100        /* We update FPSCR_FPRF */
 101        env->fpscr &= ~(0x1F << FPSCR_FPRF);
 102        env->fpscr |= ret << FPSCR_FPRF;
 103    }
 104    /* We just need fpcc to update Rc1 */
 105    return ret & 0xF;
 106}
 107
 108/* Floating-point invalid operations exception */
 109static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op)
 110{
 111    uint64_t ret = 0;
 112    int ve;
 113
 114    ve = fpscr_ve;
 115    switch (op) {
 116    case POWERPC_EXCP_FP_VXSNAN:
 117        env->fpscr |= 1 << FPSCR_VXSNAN;
 118        break;
 119    case POWERPC_EXCP_FP_VXSOFT:
 120        env->fpscr |= 1 << FPSCR_VXSOFT;
 121        break;
 122    case POWERPC_EXCP_FP_VXISI:
 123        /* Magnitude subtraction of infinities */
 124        env->fpscr |= 1 << FPSCR_VXISI;
 125        goto update_arith;
 126    case POWERPC_EXCP_FP_VXIDI:
 127        /* Division of infinity by infinity */
 128        env->fpscr |= 1 << FPSCR_VXIDI;
 129        goto update_arith;
 130    case POWERPC_EXCP_FP_VXZDZ:
 131        /* Division of zero by zero */
 132        env->fpscr |= 1 << FPSCR_VXZDZ;
 133        goto update_arith;
 134    case POWERPC_EXCP_FP_VXIMZ:
 135        /* Multiplication of zero by infinity */
 136        env->fpscr |= 1 << FPSCR_VXIMZ;
 137        goto update_arith;
 138    case POWERPC_EXCP_FP_VXVC:
 139        /* Ordered comparison of NaN */
 140        env->fpscr |= 1 << FPSCR_VXVC;
 141        env->fpscr &= ~(0xF << FPSCR_FPCC);
 142        env->fpscr |= 0x11 << FPSCR_FPCC;
 143        /* We must update the target FPR before raising the exception */
 144        if (ve != 0) {
 145            env->exception_index = POWERPC_EXCP_PROGRAM;
 146            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
 147            /* Update the floating-point enabled exception summary */
 148            env->fpscr |= 1 << FPSCR_FEX;
 149            /* Exception is differed */
 150            ve = 0;
 151        }
 152        break;
 153    case POWERPC_EXCP_FP_VXSQRT:
 154        /* Square root of a negative number */
 155        env->fpscr |= 1 << FPSCR_VXSQRT;
 156    update_arith:
 157        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
 158        if (ve == 0) {
 159            /* Set the result to quiet NaN */
 160            ret = 0x7FF8000000000000ULL;
 161            env->fpscr &= ~(0xF << FPSCR_FPCC);
 162            env->fpscr |= 0x11 << FPSCR_FPCC;
 163        }
 164        break;
 165    case POWERPC_EXCP_FP_VXCVI:
 166        /* Invalid conversion */
 167        env->fpscr |= 1 << FPSCR_VXCVI;
 168        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
 169        if (ve == 0) {
 170            /* Set the result to quiet NaN */
 171            ret = 0x7FF8000000000000ULL;
 172            env->fpscr &= ~(0xF << FPSCR_FPCC);
 173            env->fpscr |= 0x11 << FPSCR_FPCC;
 174        }
 175        break;
 176    }
 177    /* Update the floating-point invalid operation summary */
 178    env->fpscr |= 1 << FPSCR_VX;
 179    /* Update the floating-point exception summary */
 180    env->fpscr |= 1 << FPSCR_FX;
 181    if (ve != 0) {
 182        /* Update the floating-point enabled exception summary */
 183        env->fpscr |= 1 << FPSCR_FEX;
 184        if (msr_fe0 != 0 || msr_fe1 != 0) {
 185            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
 186                                       POWERPC_EXCP_FP | op);
 187        }
 188    }
 189    return ret;
 190}
 191
 192static inline void float_zero_divide_excp(CPUPPCState *env)
 193{
 194    env->fpscr |= 1 << FPSCR_ZX;
 195    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
 196    /* Update the floating-point exception summary */
 197    env->fpscr |= 1 << FPSCR_FX;
 198    if (fpscr_ze != 0) {
 199        /* Update the floating-point enabled exception summary */
 200        env->fpscr |= 1 << FPSCR_FEX;
 201        if (msr_fe0 != 0 || msr_fe1 != 0) {
 202            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
 203                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
 204        }
 205    }
 206}
 207
 208static inline void float_overflow_excp(CPUPPCState *env)
 209{
 210    env->fpscr |= 1 << FPSCR_OX;
 211    /* Update the floating-point exception summary */
 212    env->fpscr |= 1 << FPSCR_FX;
 213    if (fpscr_oe != 0) {
 214        /* XXX: should adjust the result */
 215        /* Update the floating-point enabled exception summary */
 216        env->fpscr |= 1 << FPSCR_FEX;
 217        /* We must update the target FPR before raising the exception */
 218        env->exception_index = POWERPC_EXCP_PROGRAM;
 219        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
 220    } else {
 221        env->fpscr |= 1 << FPSCR_XX;
 222        env->fpscr |= 1 << FPSCR_FI;
 223    }
 224}
 225
 226static inline void float_underflow_excp(CPUPPCState *env)
 227{
 228    env->fpscr |= 1 << FPSCR_UX;
 229    /* Update the floating-point exception summary */
 230    env->fpscr |= 1 << FPSCR_FX;
 231    if (fpscr_ue != 0) {
 232        /* XXX: should adjust the result */
 233        /* Update the floating-point enabled exception summary */
 234        env->fpscr |= 1 << FPSCR_FEX;
 235        /* We must update the target FPR before raising the exception */
 236        env->exception_index = POWERPC_EXCP_PROGRAM;
 237        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
 238    }
 239}
 240
 241static inline void float_inexact_excp(CPUPPCState *env)
 242{
 243    env->fpscr |= 1 << FPSCR_XX;
 244    /* Update the floating-point exception summary */
 245    env->fpscr |= 1 << FPSCR_FX;
 246    if (fpscr_xe != 0) {
 247        /* Update the floating-point enabled exception summary */
 248        env->fpscr |= 1 << FPSCR_FEX;
 249        /* We must update the target FPR before raising the exception */
 250        env->exception_index = POWERPC_EXCP_PROGRAM;
 251        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
 252    }
 253}
 254
 255static inline void fpscr_set_rounding_mode(CPUPPCState *env)
 256{
 257    int rnd_type;
 258
 259    /* Set rounding mode */
 260    switch (fpscr_rn) {
 261    case 0:
 262        /* Best approximation (round to nearest) */
 263        rnd_type = float_round_nearest_even;
 264        break;
 265    case 1:
 266        /* Smaller magnitude (round toward zero) */
 267        rnd_type = float_round_to_zero;
 268        break;
 269    case 2:
 270        /* Round toward +infinite */
 271        rnd_type = float_round_up;
 272        break;
 273    default:
 274    case 3:
 275        /* Round toward -infinite */
 276        rnd_type = float_round_down;
 277        break;
 278    }
 279    set_float_rounding_mode(rnd_type, &env->fp_status);
 280}
 281
 282void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit)
 283{
 284    int prev;
 285
 286    prev = (env->fpscr >> bit) & 1;
 287    env->fpscr &= ~(1 << bit);
 288    if (prev == 1) {
 289        switch (bit) {
 290        case FPSCR_RN1:
 291        case FPSCR_RN:
 292            fpscr_set_rounding_mode(env);
 293            break;
 294        default:
 295            break;
 296        }
 297    }
 298}
 299
 300void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
 301{
 302    int prev;
 303
 304    prev = (env->fpscr >> bit) & 1;
 305    env->fpscr |= 1 << bit;
 306    if (prev == 0) {
 307        switch (bit) {
 308        case FPSCR_VX:
 309            env->fpscr |= 1 << FPSCR_FX;
 310            if (fpscr_ve) {
 311                goto raise_ve;
 312            }
 313            break;
 314        case FPSCR_OX:
 315            env->fpscr |= 1 << FPSCR_FX;
 316            if (fpscr_oe) {
 317                goto raise_oe;
 318            }
 319            break;
 320        case FPSCR_UX:
 321            env->fpscr |= 1 << FPSCR_FX;
 322            if (fpscr_ue) {
 323                goto raise_ue;
 324            }
 325            break;
 326        case FPSCR_ZX:
 327            env->fpscr |= 1 << FPSCR_FX;
 328            if (fpscr_ze) {
 329                goto raise_ze;
 330            }
 331            break;
 332        case FPSCR_XX:
 333            env->fpscr |= 1 << FPSCR_FX;
 334            if (fpscr_xe) {
 335                goto raise_xe;
 336            }
 337            break;
 338        case FPSCR_VXSNAN:
 339        case FPSCR_VXISI:
 340        case FPSCR_VXIDI:
 341        case FPSCR_VXZDZ:
 342        case FPSCR_VXIMZ:
 343        case FPSCR_VXVC:
 344        case FPSCR_VXSOFT:
 345        case FPSCR_VXSQRT:
 346        case FPSCR_VXCVI:
 347            env->fpscr |= 1 << FPSCR_VX;
 348            env->fpscr |= 1 << FPSCR_FX;
 349            if (fpscr_ve != 0) {
 350                goto raise_ve;
 351            }
 352            break;
 353        case FPSCR_VE:
 354            if (fpscr_vx != 0) {
 355            raise_ve:
 356                env->error_code = POWERPC_EXCP_FP;
 357                if (fpscr_vxsnan) {
 358                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
 359                }
 360                if (fpscr_vxisi) {
 361                    env->error_code |= POWERPC_EXCP_FP_VXISI;
 362                }
 363                if (fpscr_vxidi) {
 364                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
 365                }
 366                if (fpscr_vxzdz) {
 367                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
 368                }
 369                if (fpscr_vximz) {
 370                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
 371                }
 372                if (fpscr_vxvc) {
 373                    env->error_code |= POWERPC_EXCP_FP_VXVC;
 374                }
 375                if (fpscr_vxsoft) {
 376                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
 377                }
 378                if (fpscr_vxsqrt) {
 379                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
 380                }
 381                if (fpscr_vxcvi) {
 382                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
 383                }
 384                goto raise_excp;
 385            }
 386            break;
 387        case FPSCR_OE:
 388            if (fpscr_ox != 0) {
 389            raise_oe:
 390                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
 391                goto raise_excp;
 392            }
 393            break;
 394        case FPSCR_UE:
 395            if (fpscr_ux != 0) {
 396            raise_ue:
 397                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
 398                goto raise_excp;
 399            }
 400            break;
 401        case FPSCR_ZE:
 402            if (fpscr_zx != 0) {
 403            raise_ze:
 404                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
 405                goto raise_excp;
 406            }
 407            break;
 408        case FPSCR_XE:
 409            if (fpscr_xx != 0) {
 410            raise_xe:
 411                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
 412                goto raise_excp;
 413            }
 414            break;
 415        case FPSCR_RN1:
 416        case FPSCR_RN:
 417            fpscr_set_rounding_mode(env);
 418            break;
 419        default:
 420            break;
 421        raise_excp:
 422            /* Update the floating-point enabled exception summary */
 423            env->fpscr |= 1 << FPSCR_FEX;
 424            /* We have to update Rc1 before raising the exception */
 425            env->exception_index = POWERPC_EXCP_PROGRAM;
 426            break;
 427        }
 428    }
 429}
 430
 431void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
 432{
 433    /*
 434     * We use only the 32 LSB of the incoming fpr
 435     */
 436    uint32_t prev, new;
 437    int i;
 438
 439    prev = env->fpscr;
 440    new = (uint32_t)arg;
 441    new &= ~0x60000000;
 442    new |= prev & 0x60000000;
 443    for (i = 0; i < 8; i++) {
 444        if (mask & (1 << i)) {
 445            env->fpscr &= ~(0xF << (4 * i));
 446            env->fpscr |= new & (0xF << (4 * i));
 447        }
 448    }
 449    /* Update VX and FEX */
 450    if (fpscr_ix != 0) {
 451        env->fpscr |= 1 << FPSCR_VX;
 452    } else {
 453        env->fpscr &= ~(1 << FPSCR_VX);
 454    }
 455    if ((fpscr_ex & fpscr_eex) != 0) {
 456        env->fpscr |= 1 << FPSCR_FEX;
 457        env->exception_index = POWERPC_EXCP_PROGRAM;
 458        /* XXX: we should compute it properly */
 459        env->error_code = POWERPC_EXCP_FP;
 460    } else {
 461        env->fpscr &= ~(1 << FPSCR_FEX);
 462    }
 463    fpscr_set_rounding_mode(env);
 464}
 465
 466void helper_float_check_status(CPUPPCState *env)
 467{
 468    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
 469        (env->error_code & POWERPC_EXCP_FP)) {
 470        /* Differred floating-point exception after target FPR update */
 471        if (msr_fe0 != 0 || msr_fe1 != 0) {
 472            helper_raise_exception_err(env, env->exception_index,
 473                                       env->error_code);
 474        }
 475    } else {
 476        int status = get_float_exception_flags(&env->fp_status);
 477        if (status & float_flag_divbyzero) {
 478            float_zero_divide_excp(env);
 479        } else if (status & float_flag_overflow) {
 480            float_overflow_excp(env);
 481        } else if (status & float_flag_underflow) {
 482            float_underflow_excp(env);
 483        } else if (status & float_flag_inexact) {
 484            float_inexact_excp(env);
 485        }
 486    }
 487}
 488
 489void helper_reset_fpstatus(CPUPPCState *env)
 490{
 491    set_float_exception_flags(0, &env->fp_status);
 492}
 493
 494/* fadd - fadd. */
 495uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
 496{
 497    CPU_DoubleU farg1, farg2;
 498
 499    farg1.ll = arg1;
 500    farg2.ll = arg2;
 501
 502    if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
 503                 float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
 504        /* Magnitude subtraction of infinities */
 505        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
 506    } else {
 507        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 508                     float64_is_signaling_nan(farg2.d))) {
 509            /* sNaN addition */
 510            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 511        }
 512        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
 513    }
 514
 515    return farg1.ll;
 516}
 517
 518/* fsub - fsub. */
 519uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
 520{
 521    CPU_DoubleU farg1, farg2;
 522
 523    farg1.ll = arg1;
 524    farg2.ll = arg2;
 525
 526    if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
 527                 float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
 528        /* Magnitude subtraction of infinities */
 529        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
 530    } else {
 531        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 532                     float64_is_signaling_nan(farg2.d))) {
 533            /* sNaN subtraction */
 534            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 535        }
 536        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
 537    }
 538
 539    return farg1.ll;
 540}
 541
 542/* fmul - fmul. */
 543uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
 544{
 545    CPU_DoubleU farg1, farg2;
 546
 547    farg1.ll = arg1;
 548    farg2.ll = arg2;
 549
 550    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 551                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 552        /* Multiplication of zero by infinity */
 553        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
 554    } else {
 555        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 556                     float64_is_signaling_nan(farg2.d))) {
 557            /* sNaN multiplication */
 558            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 559        }
 560        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
 561    }
 562
 563    return farg1.ll;
 564}
 565
 566/* fdiv - fdiv. */
 567uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
 568{
 569    CPU_DoubleU farg1, farg2;
 570
 571    farg1.ll = arg1;
 572    farg2.ll = arg2;
 573
 574    if (unlikely(float64_is_infinity(farg1.d) &&
 575                 float64_is_infinity(farg2.d))) {
 576        /* Division of infinity by infinity */
 577        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI);
 578    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
 579        /* Division of zero by zero */
 580        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ);
 581    } else {
 582        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 583                     float64_is_signaling_nan(farg2.d))) {
 584            /* sNaN division */
 585            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 586        }
 587        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
 588    }
 589
 590    return farg1.ll;
 591}
 592
 593/* fabs */
 594uint64_t helper_fabs(CPUPPCState *env, uint64_t arg)
 595{
 596    CPU_DoubleU farg;
 597
 598    farg.ll = arg;
 599    farg.d = float64_abs(farg.d);
 600    return farg.ll;
 601}
 602
 603/* fnabs */
 604uint64_t helper_fnabs(CPUPPCState *env, uint64_t arg)
 605{
 606    CPU_DoubleU farg;
 607
 608    farg.ll = arg;
 609    farg.d = float64_abs(farg.d);
 610    farg.d = float64_chs(farg.d);
 611    return farg.ll;
 612}
 613
 614/* fneg */
 615uint64_t helper_fneg(CPUPPCState *env, uint64_t arg)
 616{
 617    CPU_DoubleU farg;
 618
 619    farg.ll = arg;
 620    farg.d = float64_chs(farg.d);
 621    return farg.ll;
 622}
 623
 624/* fctiw - fctiw. */
 625uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg)
 626{
 627    CPU_DoubleU farg;
 628
 629    farg.ll = arg;
 630
 631    if (unlikely(float64_is_signaling_nan(farg.d))) {
 632        /* sNaN conversion */
 633        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
 634                                        POWERPC_EXCP_FP_VXCVI);
 635    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
 636                        float64_is_infinity(farg.d))) {
 637        /* qNan / infinity conversion */
 638        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
 639    } else {
 640        farg.ll = float64_to_int32(farg.d, &env->fp_status);
 641        /* XXX: higher bits are not supposed to be significant.
 642         *     to make tests easier, return the same as a real PowerPC 750
 643         */
 644        farg.ll |= 0xFFF80000ULL << 32;
 645    }
 646    return farg.ll;
 647}
 648
 649/* fctiwz - fctiwz. */
 650uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg)
 651{
 652    CPU_DoubleU farg;
 653
 654    farg.ll = arg;
 655
 656    if (unlikely(float64_is_signaling_nan(farg.d))) {
 657        /* sNaN conversion */
 658        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
 659                                        POWERPC_EXCP_FP_VXCVI);
 660    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
 661                        float64_is_infinity(farg.d))) {
 662        /* qNan / infinity conversion */
 663        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
 664    } else {
 665        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
 666        /* XXX: higher bits are not supposed to be significant.
 667         *     to make tests easier, return the same as a real PowerPC 750
 668         */
 669        farg.ll |= 0xFFF80000ULL << 32;
 670    }
 671    return farg.ll;
 672}
 673
 674#if defined(TARGET_PPC64)
 675/* fcfid - fcfid. */
 676uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg)
 677{
 678    CPU_DoubleU farg;
 679
 680    farg.d = int64_to_float64(arg, &env->fp_status);
 681    return farg.ll;
 682}
 683
 684/* fctid - fctid. */
 685uint64_t helper_fctid(CPUPPCState *env, uint64_t arg)
 686{
 687    CPU_DoubleU farg;
 688
 689    farg.ll = arg;
 690
 691    if (unlikely(float64_is_signaling_nan(farg.d))) {
 692        /* sNaN conversion */
 693        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
 694                                        POWERPC_EXCP_FP_VXCVI);
 695    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
 696                        float64_is_infinity(farg.d))) {
 697        /* qNan / infinity conversion */
 698        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
 699    } else {
 700        farg.ll = float64_to_int64(farg.d, &env->fp_status);
 701    }
 702    return farg.ll;
 703}
 704
 705/* fctidz - fctidz. */
 706uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg)
 707{
 708    CPU_DoubleU farg;
 709
 710    farg.ll = arg;
 711
 712    if (unlikely(float64_is_signaling_nan(farg.d))) {
 713        /* sNaN conversion */
 714        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
 715                                        POWERPC_EXCP_FP_VXCVI);
 716    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
 717                        float64_is_infinity(farg.d))) {
 718        /* qNan / infinity conversion */
 719        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
 720    } else {
 721        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
 722    }
 723    return farg.ll;
 724}
 725
 726#endif
 727
 728static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
 729                              int rounding_mode)
 730{
 731    CPU_DoubleU farg;
 732
 733    farg.ll = arg;
 734
 735    if (unlikely(float64_is_signaling_nan(farg.d))) {
 736        /* sNaN round */
 737        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
 738                                        POWERPC_EXCP_FP_VXCVI);
 739    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
 740                        float64_is_infinity(farg.d))) {
 741        /* qNan / infinity round */
 742        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
 743    } else {
 744        set_float_rounding_mode(rounding_mode, &env->fp_status);
 745        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
 746        /* Restore rounding mode from FPSCR */
 747        fpscr_set_rounding_mode(env);
 748    }
 749    return farg.ll;
 750}
 751
 752uint64_t helper_frin(CPUPPCState *env, uint64_t arg)
 753{
 754    return do_fri(env, arg, float_round_nearest_even);
 755}
 756
 757uint64_t helper_friz(CPUPPCState *env, uint64_t arg)
 758{
 759    return do_fri(env, arg, float_round_to_zero);
 760}
 761
 762uint64_t helper_frip(CPUPPCState *env, uint64_t arg)
 763{
 764    return do_fri(env, arg, float_round_up);
 765}
 766
 767uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
 768{
 769    return do_fri(env, arg, float_round_down);
 770}
 771
 772/* fmadd - fmadd. */
 773uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
 774                      uint64_t arg3)
 775{
 776    CPU_DoubleU farg1, farg2, farg3;
 777
 778    farg1.ll = arg1;
 779    farg2.ll = arg2;
 780    farg3.ll = arg3;
 781
 782    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 783                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 784        /* Multiplication of zero by infinity */
 785        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
 786    } else {
 787        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 788                     float64_is_signaling_nan(farg2.d) ||
 789                     float64_is_signaling_nan(farg3.d))) {
 790            /* sNaN operation */
 791            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 792        }
 793        /* This is the way the PowerPC specification defines it */
 794        float128 ft0_128, ft1_128;
 795
 796        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 797        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 798        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 799        if (unlikely(float128_is_infinity(ft0_128) &&
 800                     float64_is_infinity(farg3.d) &&
 801                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
 802            /* Magnitude subtraction of infinities */
 803            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
 804        } else {
 805            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 806            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
 807            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 808        }
 809    }
 810
 811    return farg1.ll;
 812}
 813
 814/* fmsub - fmsub. */
 815uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
 816                      uint64_t arg3)
 817{
 818    CPU_DoubleU farg1, farg2, farg3;
 819
 820    farg1.ll = arg1;
 821    farg2.ll = arg2;
 822    farg3.ll = arg3;
 823
 824    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 825                 (float64_is_zero(farg1.d) &&
 826                  float64_is_infinity(farg2.d)))) {
 827        /* Multiplication of zero by infinity */
 828        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
 829    } else {
 830        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 831                     float64_is_signaling_nan(farg2.d) ||
 832                     float64_is_signaling_nan(farg3.d))) {
 833            /* sNaN operation */
 834            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 835        }
 836        /* This is the way the PowerPC specification defines it */
 837        float128 ft0_128, ft1_128;
 838
 839        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 840        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 841        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 842        if (unlikely(float128_is_infinity(ft0_128) &&
 843                     float64_is_infinity(farg3.d) &&
 844                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
 845            /* Magnitude subtraction of infinities */
 846            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
 847        } else {
 848            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 849            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
 850            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 851        }
 852    }
 853    return farg1.ll;
 854}
 855
 856/* fnmadd - fnmadd. */
 857uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
 858                       uint64_t arg3)
 859{
 860    CPU_DoubleU farg1, farg2, farg3;
 861
 862    farg1.ll = arg1;
 863    farg2.ll = arg2;
 864    farg3.ll = arg3;
 865
 866    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 867                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 868        /* Multiplication of zero by infinity */
 869        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
 870    } else {
 871        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 872                     float64_is_signaling_nan(farg2.d) ||
 873                     float64_is_signaling_nan(farg3.d))) {
 874            /* sNaN operation */
 875            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 876        }
 877        /* This is the way the PowerPC specification defines it */
 878        float128 ft0_128, ft1_128;
 879
 880        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 881        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 882        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 883        if (unlikely(float128_is_infinity(ft0_128) &&
 884                     float64_is_infinity(farg3.d) &&
 885                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
 886            /* Magnitude subtraction of infinities */
 887            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
 888        } else {
 889            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 890            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
 891            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 892        }
 893        if (likely(!float64_is_any_nan(farg1.d))) {
 894            farg1.d = float64_chs(farg1.d);
 895        }
 896    }
 897    return farg1.ll;
 898}
 899
 900/* fnmsub - fnmsub. */
 901uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
 902                       uint64_t arg3)
 903{
 904    CPU_DoubleU farg1, farg2, farg3;
 905
 906    farg1.ll = arg1;
 907    farg2.ll = arg2;
 908    farg3.ll = arg3;
 909
 910    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 911                 (float64_is_zero(farg1.d) &&
 912                  float64_is_infinity(farg2.d)))) {
 913        /* Multiplication of zero by infinity */
 914        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
 915    } else {
 916        if (unlikely(float64_is_signaling_nan(farg1.d) ||
 917                     float64_is_signaling_nan(farg2.d) ||
 918                     float64_is_signaling_nan(farg3.d))) {
 919            /* sNaN operation */
 920            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 921        }
 922        /* This is the way the PowerPC specification defines it */
 923        float128 ft0_128, ft1_128;
 924
 925        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 926        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 927        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 928        if (unlikely(float128_is_infinity(ft0_128) &&
 929                     float64_is_infinity(farg3.d) &&
 930                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
 931            /* Magnitude subtraction of infinities */
 932            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
 933        } else {
 934            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 935            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
 936            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 937        }
 938        if (likely(!float64_is_any_nan(farg1.d))) {
 939            farg1.d = float64_chs(farg1.d);
 940        }
 941    }
 942    return farg1.ll;
 943}
 944
 945/* frsp - frsp. */
 946uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
 947{
 948    CPU_DoubleU farg;
 949    float32 f32;
 950
 951    farg.ll = arg;
 952
 953    if (unlikely(float64_is_signaling_nan(farg.d))) {
 954        /* sNaN square root */
 955        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 956    }
 957    f32 = float64_to_float32(farg.d, &env->fp_status);
 958    farg.d = float32_to_float64(f32, &env->fp_status);
 959
 960    return farg.ll;
 961}
 962
 963/* fsqrt - fsqrt. */
 964uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
 965{
 966    CPU_DoubleU farg;
 967
 968    farg.ll = arg;
 969
 970    if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
 971        /* Square root of a negative nonzero number */
 972        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT);
 973    } else {
 974        if (unlikely(float64_is_signaling_nan(farg.d))) {
 975            /* sNaN square root */
 976            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 977        }
 978        farg.d = float64_sqrt(farg.d, &env->fp_status);
 979    }
 980    return farg.ll;
 981}
 982
 983/* fre - fre. */
 984uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
 985{
 986    CPU_DoubleU farg;
 987
 988    farg.ll = arg;
 989
 990    if (unlikely(float64_is_signaling_nan(farg.d))) {
 991        /* sNaN reciprocal */
 992        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
 993    }
 994    farg.d = float64_div(float64_one, farg.d, &env->fp_status);
 995    return farg.d;
 996}
 997
 998/* fres - fres. */
 999uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
1000{
1001    CPU_DoubleU farg;
1002    float32 f32;
1003
1004    farg.ll = arg;
1005
1006    if (unlikely(float64_is_signaling_nan(farg.d))) {
1007        /* sNaN reciprocal */
1008        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
1009    }
1010    farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1011    f32 = float64_to_float32(farg.d, &env->fp_status);
1012    farg.d = float32_to_float64(f32, &env->fp_status);
1013
1014    return farg.ll;
1015}
1016
1017/* frsqrte  - frsqrte. */
1018uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
1019{
1020    CPU_DoubleU farg;
1021    float32 f32;
1022
1023    farg.ll = arg;
1024
1025    if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1026        /* Reciprocal square root of a negative nonzero number */
1027        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT);
1028    } else {
1029        if (unlikely(float64_is_signaling_nan(farg.d))) {
1030            /* sNaN reciprocal square root */
1031            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
1032        }
1033        farg.d = float64_sqrt(farg.d, &env->fp_status);
1034        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1035        f32 = float64_to_float32(farg.d, &env->fp_status);
1036        farg.d = float32_to_float64(f32, &env->fp_status);
1037    }
1038    return farg.ll;
1039}
1040
1041/* fsel - fsel. */
1042uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1043                     uint64_t arg3)
1044{
1045    CPU_DoubleU farg1;
1046
1047    farg1.ll = arg1;
1048
1049    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
1050        !float64_is_any_nan(farg1.d)) {
1051        return arg2;
1052    } else {
1053        return arg3;
1054    }
1055}
1056
1057void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1058                  uint32_t crfD)
1059{
1060    CPU_DoubleU farg1, farg2;
1061    uint32_t ret = 0;
1062
1063    farg1.ll = arg1;
1064    farg2.ll = arg2;
1065
1066    if (unlikely(float64_is_any_nan(farg1.d) ||
1067                 float64_is_any_nan(farg2.d))) {
1068        ret = 0x01UL;
1069    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1070        ret = 0x08UL;
1071    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1072        ret = 0x04UL;
1073    } else {
1074        ret = 0x02UL;
1075    }
1076
1077    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1078    env->fpscr |= ret << FPSCR_FPRF;
1079    env->crf[crfD] = ret;
1080    if (unlikely(ret == 0x01UL
1081                 && (float64_is_signaling_nan(farg1.d) ||
1082                     float64_is_signaling_nan(farg2.d)))) {
1083        /* sNaN comparison */
1084        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
1085    }
1086}
1087
1088void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1089                  uint32_t crfD)
1090{
1091    CPU_DoubleU farg1, farg2;
1092    uint32_t ret = 0;
1093
1094    farg1.ll = arg1;
1095    farg2.ll = arg2;
1096
1097    if (unlikely(float64_is_any_nan(farg1.d) ||
1098                 float64_is_any_nan(farg2.d))) {
1099        ret = 0x01UL;
1100    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1101        ret = 0x08UL;
1102    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1103        ret = 0x04UL;
1104    } else {
1105        ret = 0x02UL;
1106    }
1107
1108    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1109    env->fpscr |= ret << FPSCR_FPRF;
1110    env->crf[crfD] = ret;
1111    if (unlikely(ret == 0x01UL)) {
1112        if (float64_is_signaling_nan(farg1.d) ||
1113            float64_is_signaling_nan(farg2.d)) {
1114            /* sNaN comparison */
1115            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
1116                                  POWERPC_EXCP_FP_VXVC);
1117        } else {
1118            /* qNaN comparison */
1119            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC);
1120        }
1121    }
1122}
1123
1124/* Single-precision floating-point conversions */
1125static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val)
1126{
1127    CPU_FloatU u;
1128
1129    u.f = int32_to_float32(val, &env->vec_status);
1130
1131    return u.l;
1132}
1133
1134static inline uint32_t efscfui(CPUPPCState *env, uint32_t val)
1135{
1136    CPU_FloatU u;
1137
1138    u.f = uint32_to_float32(val, &env->vec_status);
1139
1140    return u.l;
1141}
1142
1143static inline int32_t efsctsi(CPUPPCState *env, uint32_t val)
1144{
1145    CPU_FloatU u;
1146
1147    u.l = val;
1148    /* NaN are not treated the same way IEEE 754 does */
1149    if (unlikely(float32_is_quiet_nan(u.f))) {
1150        return 0;
1151    }
1152
1153    return float32_to_int32(u.f, &env->vec_status);
1154}
1155
1156static inline uint32_t efsctui(CPUPPCState *env, uint32_t val)
1157{
1158    CPU_FloatU u;
1159
1160    u.l = val;
1161    /* NaN are not treated the same way IEEE 754 does */
1162    if (unlikely(float32_is_quiet_nan(u.f))) {
1163        return 0;
1164    }
1165
1166    return float32_to_uint32(u.f, &env->vec_status);
1167}
1168
1169static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val)
1170{
1171    CPU_FloatU u;
1172
1173    u.l = val;
1174    /* NaN are not treated the same way IEEE 754 does */
1175    if (unlikely(float32_is_quiet_nan(u.f))) {
1176        return 0;
1177    }
1178
1179    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
1180}
1181
1182static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val)
1183{
1184    CPU_FloatU u;
1185
1186    u.l = val;
1187    /* NaN are not treated the same way IEEE 754 does */
1188    if (unlikely(float32_is_quiet_nan(u.f))) {
1189        return 0;
1190    }
1191
1192    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
1193}
1194
1195static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val)
1196{
1197    CPU_FloatU u;
1198    float32 tmp;
1199
1200    u.f = int32_to_float32(val, &env->vec_status);
1201    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
1202    u.f = float32_div(u.f, tmp, &env->vec_status);
1203
1204    return u.l;
1205}
1206
1207static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val)
1208{
1209    CPU_FloatU u;
1210    float32 tmp;
1211
1212    u.f = uint32_to_float32(val, &env->vec_status);
1213    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1214    u.f = float32_div(u.f, tmp, &env->vec_status);
1215
1216    return u.l;
1217}
1218
1219static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val)
1220{
1221    CPU_FloatU u;
1222    float32 tmp;
1223
1224    u.l = val;
1225    /* NaN are not treated the same way IEEE 754 does */
1226    if (unlikely(float32_is_quiet_nan(u.f))) {
1227        return 0;
1228    }
1229    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1230    u.f = float32_mul(u.f, tmp, &env->vec_status);
1231
1232    return float32_to_int32(u.f, &env->vec_status);
1233}
1234
1235static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val)
1236{
1237    CPU_FloatU u;
1238    float32 tmp;
1239
1240    u.l = val;
1241    /* NaN are not treated the same way IEEE 754 does */
1242    if (unlikely(float32_is_quiet_nan(u.f))) {
1243        return 0;
1244    }
1245    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1246    u.f = float32_mul(u.f, tmp, &env->vec_status);
1247
1248    return float32_to_uint32(u.f, &env->vec_status);
1249}
1250
1251#define HELPER_SPE_SINGLE_CONV(name)                              \
1252    uint32_t helper_e##name(CPUPPCState *env, uint32_t val)       \
1253    {                                                             \
1254        return e##name(env, val);                                 \
1255    }
1256/* efscfsi */
1257HELPER_SPE_SINGLE_CONV(fscfsi);
1258/* efscfui */
1259HELPER_SPE_SINGLE_CONV(fscfui);
1260/* efscfuf */
1261HELPER_SPE_SINGLE_CONV(fscfuf);
1262/* efscfsf */
1263HELPER_SPE_SINGLE_CONV(fscfsf);
1264/* efsctsi */
1265HELPER_SPE_SINGLE_CONV(fsctsi);
1266/* efsctui */
1267HELPER_SPE_SINGLE_CONV(fsctui);
1268/* efsctsiz */
1269HELPER_SPE_SINGLE_CONV(fsctsiz);
1270/* efsctuiz */
1271HELPER_SPE_SINGLE_CONV(fsctuiz);
1272/* efsctsf */
1273HELPER_SPE_SINGLE_CONV(fsctsf);
1274/* efsctuf */
1275HELPER_SPE_SINGLE_CONV(fsctuf);
1276
1277#define HELPER_SPE_VECTOR_CONV(name)                            \
1278    uint64_t helper_ev##name(CPUPPCState *env, uint64_t val)    \
1279    {                                                           \
1280        return ((uint64_t)e##name(env, val >> 32) << 32) |      \
1281            (uint64_t)e##name(env, val);                        \
1282    }
1283/* evfscfsi */
1284HELPER_SPE_VECTOR_CONV(fscfsi);
1285/* evfscfui */
1286HELPER_SPE_VECTOR_CONV(fscfui);
1287/* evfscfuf */
1288HELPER_SPE_VECTOR_CONV(fscfuf);
1289/* evfscfsf */
1290HELPER_SPE_VECTOR_CONV(fscfsf);
1291/* evfsctsi */
1292HELPER_SPE_VECTOR_CONV(fsctsi);
1293/* evfsctui */
1294HELPER_SPE_VECTOR_CONV(fsctui);
1295/* evfsctsiz */
1296HELPER_SPE_VECTOR_CONV(fsctsiz);
1297/* evfsctuiz */
1298HELPER_SPE_VECTOR_CONV(fsctuiz);
1299/* evfsctsf */
1300HELPER_SPE_VECTOR_CONV(fsctsf);
1301/* evfsctuf */
1302HELPER_SPE_VECTOR_CONV(fsctuf);
1303
1304/* Single-precision floating-point arithmetic */
1305static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2)
1306{
1307    CPU_FloatU u1, u2;
1308
1309    u1.l = op1;
1310    u2.l = op2;
1311    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
1312    return u1.l;
1313}
1314
1315static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2)
1316{
1317    CPU_FloatU u1, u2;
1318
1319    u1.l = op1;
1320    u2.l = op2;
1321    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
1322    return u1.l;
1323}
1324
1325static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2)
1326{
1327    CPU_FloatU u1, u2;
1328
1329    u1.l = op1;
1330    u2.l = op2;
1331    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
1332    return u1.l;
1333}
1334
1335static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2)
1336{
1337    CPU_FloatU u1, u2;
1338
1339    u1.l = op1;
1340    u2.l = op2;
1341    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
1342    return u1.l;
1343}
1344
1345#define HELPER_SPE_SINGLE_ARITH(name)                                   \
1346    uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1347    {                                                                   \
1348        return e##name(env, op1, op2);                                  \
1349    }
1350/* efsadd */
1351HELPER_SPE_SINGLE_ARITH(fsadd);
1352/* efssub */
1353HELPER_SPE_SINGLE_ARITH(fssub);
1354/* efsmul */
1355HELPER_SPE_SINGLE_ARITH(fsmul);
1356/* efsdiv */
1357HELPER_SPE_SINGLE_ARITH(fsdiv);
1358
1359#define HELPER_SPE_VECTOR_ARITH(name)                                   \
1360    uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1361    {                                                                   \
1362        return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) |   \
1363            (uint64_t)e##name(env, op1, op2);                           \
1364    }
1365/* evfsadd */
1366HELPER_SPE_VECTOR_ARITH(fsadd);
1367/* evfssub */
1368HELPER_SPE_VECTOR_ARITH(fssub);
1369/* evfsmul */
1370HELPER_SPE_VECTOR_ARITH(fsmul);
1371/* evfsdiv */
1372HELPER_SPE_VECTOR_ARITH(fsdiv);
1373
1374/* Single-precision floating-point comparisons */
1375static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1376{
1377    CPU_FloatU u1, u2;
1378
1379    u1.l = op1;
1380    u2.l = op2;
1381    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1382}
1383
1384static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1385{
1386    CPU_FloatU u1, u2;
1387
1388    u1.l = op1;
1389    u2.l = op2;
1390    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
1391}
1392
1393static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1394{
1395    CPU_FloatU u1, u2;
1396
1397    u1.l = op1;
1398    u2.l = op2;
1399    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1400}
1401
1402static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1403{
1404    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1405    return efscmplt(env, op1, op2);
1406}
1407
1408static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1409{
1410    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1411    return efscmpgt(env, op1, op2);
1412}
1413
1414static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1415{
1416    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1417    return efscmpeq(env, op1, op2);
1418}
1419
1420#define HELPER_SINGLE_SPE_CMP(name)                                     \
1421    uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1422    {                                                                   \
1423        return e##name(env, op1, op2) << 2;                             \
1424    }
1425/* efststlt */
1426HELPER_SINGLE_SPE_CMP(fststlt);
1427/* efststgt */
1428HELPER_SINGLE_SPE_CMP(fststgt);
1429/* efststeq */
1430HELPER_SINGLE_SPE_CMP(fststeq);
1431/* efscmplt */
1432HELPER_SINGLE_SPE_CMP(fscmplt);
1433/* efscmpgt */
1434HELPER_SINGLE_SPE_CMP(fscmpgt);
1435/* efscmpeq */
1436HELPER_SINGLE_SPE_CMP(fscmpeq);
1437
1438static inline uint32_t evcmp_merge(int t0, int t1)
1439{
1440    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1441}
1442
1443#define HELPER_VECTOR_SPE_CMP(name)                                     \
1444    uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1445    {                                                                   \
1446        return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32),          \
1447                           e##name(env, op1, op2));                     \
1448    }
1449/* evfststlt */
1450HELPER_VECTOR_SPE_CMP(fststlt);
1451/* evfststgt */
1452HELPER_VECTOR_SPE_CMP(fststgt);
1453/* evfststeq */
1454HELPER_VECTOR_SPE_CMP(fststeq);
1455/* evfscmplt */
1456HELPER_VECTOR_SPE_CMP(fscmplt);
1457/* evfscmpgt */
1458HELPER_VECTOR_SPE_CMP(fscmpgt);
1459/* evfscmpeq */
1460HELPER_VECTOR_SPE_CMP(fscmpeq);
1461
1462/* Double-precision floating-point conversion */
1463uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val)
1464{
1465    CPU_DoubleU u;
1466
1467    u.d = int32_to_float64(val, &env->vec_status);
1468
1469    return u.ll;
1470}
1471
1472uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val)
1473{
1474    CPU_DoubleU u;
1475
1476    u.d = int64_to_float64(val, &env->vec_status);
1477
1478    return u.ll;
1479}
1480
1481uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val)
1482{
1483    CPU_DoubleU u;
1484
1485    u.d = uint32_to_float64(val, &env->vec_status);
1486
1487    return u.ll;
1488}
1489
1490uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val)
1491{
1492    CPU_DoubleU u;
1493
1494    u.d = uint64_to_float64(val, &env->vec_status);
1495
1496    return u.ll;
1497}
1498
1499uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val)
1500{
1501    CPU_DoubleU u;
1502
1503    u.ll = val;
1504    /* NaN are not treated the same way IEEE 754 does */
1505    if (unlikely(float64_is_any_nan(u.d))) {
1506        return 0;
1507    }
1508
1509    return float64_to_int32(u.d, &env->vec_status);
1510}
1511
1512uint32_t helper_efdctui(CPUPPCState *env, uint64_t val)
1513{
1514    CPU_DoubleU u;
1515
1516    u.ll = val;
1517    /* NaN are not treated the same way IEEE 754 does */
1518    if (unlikely(float64_is_any_nan(u.d))) {
1519        return 0;
1520    }
1521
1522    return float64_to_uint32(u.d, &env->vec_status);
1523}
1524
1525uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val)
1526{
1527    CPU_DoubleU u;
1528
1529    u.ll = val;
1530    /* NaN are not treated the same way IEEE 754 does */
1531    if (unlikely(float64_is_any_nan(u.d))) {
1532        return 0;
1533    }
1534
1535    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
1536}
1537
1538uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val)
1539{
1540    CPU_DoubleU u;
1541
1542    u.ll = val;
1543    /* NaN are not treated the same way IEEE 754 does */
1544    if (unlikely(float64_is_any_nan(u.d))) {
1545        return 0;
1546    }
1547
1548    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
1549}
1550
1551uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val)
1552{
1553    CPU_DoubleU u;
1554
1555    u.ll = val;
1556    /* NaN are not treated the same way IEEE 754 does */
1557    if (unlikely(float64_is_any_nan(u.d))) {
1558        return 0;
1559    }
1560
1561    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
1562}
1563
1564uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val)
1565{
1566    CPU_DoubleU u;
1567
1568    u.ll = val;
1569    /* NaN are not treated the same way IEEE 754 does */
1570    if (unlikely(float64_is_any_nan(u.d))) {
1571        return 0;
1572    }
1573
1574    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
1575}
1576
1577uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val)
1578{
1579    CPU_DoubleU u;
1580    float64 tmp;
1581
1582    u.d = int32_to_float64(val, &env->vec_status);
1583    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1584    u.d = float64_div(u.d, tmp, &env->vec_status);
1585
1586    return u.ll;
1587}
1588
1589uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val)
1590{
1591    CPU_DoubleU u;
1592    float64 tmp;
1593
1594    u.d = uint32_to_float64(val, &env->vec_status);
1595    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1596    u.d = float64_div(u.d, tmp, &env->vec_status);
1597
1598    return u.ll;
1599}
1600
1601uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val)
1602{
1603    CPU_DoubleU u;
1604    float64 tmp;
1605
1606    u.ll = val;
1607    /* NaN are not treated the same way IEEE 754 does */
1608    if (unlikely(float64_is_any_nan(u.d))) {
1609        return 0;
1610    }
1611    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1612    u.d = float64_mul(u.d, tmp, &env->vec_status);
1613
1614    return float64_to_int32(u.d, &env->vec_status);
1615}
1616
1617uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val)
1618{
1619    CPU_DoubleU u;
1620    float64 tmp;
1621
1622    u.ll = val;
1623    /* NaN are not treated the same way IEEE 754 does */
1624    if (unlikely(float64_is_any_nan(u.d))) {
1625        return 0;
1626    }
1627    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1628    u.d = float64_mul(u.d, tmp, &env->vec_status);
1629
1630    return float64_to_uint32(u.d, &env->vec_status);
1631}
1632
1633uint32_t helper_efscfd(CPUPPCState *env, uint64_t val)
1634{
1635    CPU_DoubleU u1;
1636    CPU_FloatU u2;
1637
1638    u1.ll = val;
1639    u2.f = float64_to_float32(u1.d, &env->vec_status);
1640
1641    return u2.l;
1642}
1643
1644uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val)
1645{
1646    CPU_DoubleU u2;
1647    CPU_FloatU u1;
1648
1649    u1.l = val;
1650    u2.d = float32_to_float64(u1.f, &env->vec_status);
1651
1652    return u2.ll;
1653}
1654
1655/* Double precision fixed-point arithmetic */
1656uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2)
1657{
1658    CPU_DoubleU u1, u2;
1659
1660    u1.ll = op1;
1661    u2.ll = op2;
1662    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
1663    return u1.ll;
1664}
1665
1666uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2)
1667{
1668    CPU_DoubleU u1, u2;
1669
1670    u1.ll = op1;
1671    u2.ll = op2;
1672    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
1673    return u1.ll;
1674}
1675
1676uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2)
1677{
1678    CPU_DoubleU u1, u2;
1679
1680    u1.ll = op1;
1681    u2.ll = op2;
1682    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
1683    return u1.ll;
1684}
1685
1686uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2)
1687{
1688    CPU_DoubleU u1, u2;
1689
1690    u1.ll = op1;
1691    u2.ll = op2;
1692    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
1693    return u1.ll;
1694}
1695
1696/* Double precision floating point helpers */
1697uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1698{
1699    CPU_DoubleU u1, u2;
1700
1701    u1.ll = op1;
1702    u2.ll = op2;
1703    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1704}
1705
1706uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1707{
1708    CPU_DoubleU u1, u2;
1709
1710    u1.ll = op1;
1711    u2.ll = op2;
1712    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
1713}
1714
1715uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1716{
1717    CPU_DoubleU u1, u2;
1718
1719    u1.ll = op1;
1720    u2.ll = op2;
1721    return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1722}
1723
1724uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1725{
1726    /* XXX: TODO: test special values (NaN, infinites, ...) */
1727    return helper_efdtstlt(env, op1, op2);
1728}
1729
1730uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1731{
1732    /* XXX: TODO: test special values (NaN, infinites, ...) */
1733    return helper_efdtstgt(env, op1, op2);
1734}
1735
1736uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1737{
1738    /* XXX: TODO: test special values (NaN, infinites, ...) */
1739    return helper_efdtsteq(env, op1, op2);
1740}
1741