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