qemu/target/ppc/int_helper.c
<<
>>
Prefs
   1/*
   2 *  PowerPC integer and vector 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.1 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
  20#include "qemu/osdep.h"
  21#include "cpu.h"
  22#include "internal.h"
  23#include "qemu/host-utils.h"
  24#include "qemu/main-loop.h"
  25#include "exec/helper-proto.h"
  26#include "crypto/aes.h"
  27#include "fpu/softfloat.h"
  28#include "qapi/error.h"
  29#include "qemu/guest-random.h"
  30
  31#include "helper_regs.h"
  32/*****************************************************************************/
  33/* Fixed point operations helpers */
  34
  35static inline void helper_update_ov_legacy(CPUPPCState *env, int ov)
  36{
  37    if (unlikely(ov)) {
  38        env->so = env->ov = 1;
  39    } else {
  40        env->ov = 0;
  41    }
  42}
  43
  44target_ulong helper_divweu(CPUPPCState *env, target_ulong ra, target_ulong rb,
  45                           uint32_t oe)
  46{
  47    uint64_t rt = 0;
  48    int overflow = 0;
  49
  50    uint64_t dividend = (uint64_t)ra << 32;
  51    uint64_t divisor = (uint32_t)rb;
  52
  53    if (unlikely(divisor == 0)) {
  54        overflow = 1;
  55    } else {
  56        rt = dividend / divisor;
  57        overflow = rt > UINT32_MAX;
  58    }
  59
  60    if (unlikely(overflow)) {
  61        rt = 0; /* Undefined */
  62    }
  63
  64    if (oe) {
  65        helper_update_ov_legacy(env, overflow);
  66    }
  67
  68    return (target_ulong)rt;
  69}
  70
  71target_ulong helper_divwe(CPUPPCState *env, target_ulong ra, target_ulong rb,
  72                          uint32_t oe)
  73{
  74    int64_t rt = 0;
  75    int overflow = 0;
  76
  77    int64_t dividend = (int64_t)ra << 32;
  78    int64_t divisor = (int64_t)((int32_t)rb);
  79
  80    if (unlikely((divisor == 0) ||
  81                 ((divisor == -1ull) && (dividend == INT64_MIN)))) {
  82        overflow = 1;
  83    } else {
  84        rt = dividend / divisor;
  85        overflow = rt != (int32_t)rt;
  86    }
  87
  88    if (unlikely(overflow)) {
  89        rt = 0; /* Undefined */
  90    }
  91
  92    if (oe) {
  93        helper_update_ov_legacy(env, overflow);
  94    }
  95
  96    return (target_ulong)rt;
  97}
  98
  99#if defined(TARGET_PPC64)
 100
 101uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
 102{
 103    uint64_t rt = 0;
 104    int overflow = 0;
 105
 106    overflow = divu128(&rt, &ra, rb);
 107
 108    if (unlikely(overflow)) {
 109        rt = 0; /* Undefined */
 110    }
 111
 112    if (oe) {
 113        helper_update_ov_legacy(env, overflow);
 114    }
 115
 116    return rt;
 117}
 118
 119uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
 120{
 121    int64_t rt = 0;
 122    int64_t ra = (int64_t)rau;
 123    int64_t rb = (int64_t)rbu;
 124    int overflow = divs128(&rt, &ra, rb);
 125
 126    if (unlikely(overflow)) {
 127        rt = 0; /* Undefined */
 128    }
 129
 130    if (oe) {
 131        helper_update_ov_legacy(env, overflow);
 132    }
 133
 134    return rt;
 135}
 136
 137#endif
 138
 139
 140#if defined(TARGET_PPC64)
 141/* if x = 0xab, returns 0xababababababababa */
 142#define pattern(x) (((x) & 0xff) * (~(target_ulong)0 / 0xff))
 143
 144/*
 145 * subtract 1 from each byte, and with inverse, check if MSB is set at each
 146 * byte.
 147 * i.e. ((0x00 - 0x01) & ~(0x00)) & 0x80
 148 *      (0xFF & 0xFF) & 0x80 = 0x80 (zero found)
 149 */
 150#define haszero(v) (((v) - pattern(0x01)) & ~(v) & pattern(0x80))
 151
 152/* When you XOR the pattern and there is a match, that byte will be zero */
 153#define hasvalue(x, n)  (haszero((x) ^ pattern(n)))
 154
 155uint32_t helper_cmpeqb(target_ulong ra, target_ulong rb)
 156{
 157    return hasvalue(rb, ra) ? CRF_GT : 0;
 158}
 159
 160#undef pattern
 161#undef haszero
 162#undef hasvalue
 163
 164/*
 165 * Return a random number.
 166 */
 167uint64_t helper_darn32(void)
 168{
 169    Error *err = NULL;
 170    uint32_t ret;
 171
 172    if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
 173        qemu_log_mask(LOG_UNIMP, "darn: Crypto failure: %s",
 174                      error_get_pretty(err));
 175        error_free(err);
 176        return -1;
 177    }
 178
 179    return ret;
 180}
 181
 182uint64_t helper_darn64(void)
 183{
 184    Error *err = NULL;
 185    uint64_t ret;
 186
 187    if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
 188        qemu_log_mask(LOG_UNIMP, "darn: Crypto failure: %s",
 189                      error_get_pretty(err));
 190        error_free(err);
 191        return -1;
 192    }
 193
 194    return ret;
 195}
 196
 197uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
 198{
 199    int i;
 200    uint64_t ra = 0;
 201
 202    for (i = 0; i < 8; i++) {
 203        int index = (rs >> (i * 8)) & 0xFF;
 204        if (index < 64) {
 205            if (rb & PPC_BIT(index)) {
 206                ra |= 1 << i;
 207            }
 208        }
 209    }
 210    return ra;
 211}
 212
 213#endif
 214
 215target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
 216{
 217    target_ulong mask = 0xff;
 218    target_ulong ra = 0;
 219    int i;
 220
 221    for (i = 0; i < sizeof(target_ulong); i++) {
 222        if ((rs & mask) == (rb & mask)) {
 223            ra |= mask;
 224        }
 225        mask <<= 8;
 226    }
 227    return ra;
 228}
 229
 230/* shift right arithmetic helper */
 231target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
 232                         target_ulong shift)
 233{
 234    int32_t ret;
 235
 236    if (likely(!(shift & 0x20))) {
 237        if (likely((uint32_t)shift != 0)) {
 238            shift &= 0x1f;
 239            ret = (int32_t)value >> shift;
 240            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
 241                env->ca32 = env->ca = 0;
 242            } else {
 243                env->ca32 = env->ca = 1;
 244            }
 245        } else {
 246            ret = (int32_t)value;
 247            env->ca32 = env->ca = 0;
 248        }
 249    } else {
 250        ret = (int32_t)value >> 31;
 251        env->ca32 = env->ca = (ret != 0);
 252    }
 253    return (target_long)ret;
 254}
 255
 256#if defined(TARGET_PPC64)
 257target_ulong helper_srad(CPUPPCState *env, target_ulong value,
 258                         target_ulong shift)
 259{
 260    int64_t ret;
 261
 262    if (likely(!(shift & 0x40))) {
 263        if (likely((uint64_t)shift != 0)) {
 264            shift &= 0x3f;
 265            ret = (int64_t)value >> shift;
 266            if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) {
 267                env->ca32 = env->ca = 0;
 268            } else {
 269                env->ca32 = env->ca = 1;
 270            }
 271        } else {
 272            ret = (int64_t)value;
 273            env->ca32 = env->ca = 0;
 274        }
 275    } else {
 276        ret = (int64_t)value >> 63;
 277        env->ca32 = env->ca = (ret != 0);
 278    }
 279    return ret;
 280}
 281#endif
 282
 283#if defined(TARGET_PPC64)
 284target_ulong helper_popcntb(target_ulong val)
 285{
 286    /* Note that we don't fold past bytes */
 287    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
 288                                           0x5555555555555555ULL);
 289    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
 290                                           0x3333333333333333ULL);
 291    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
 292                                           0x0f0f0f0f0f0f0f0fULL);
 293    return val;
 294}
 295
 296target_ulong helper_popcntw(target_ulong val)
 297{
 298    /* Note that we don't fold past words.  */
 299    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
 300                                           0x5555555555555555ULL);
 301    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
 302                                           0x3333333333333333ULL);
 303    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
 304                                           0x0f0f0f0f0f0f0f0fULL);
 305    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
 306                                           0x00ff00ff00ff00ffULL);
 307    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
 308                                           0x0000ffff0000ffffULL);
 309    return val;
 310}
 311#else
 312target_ulong helper_popcntb(target_ulong val)
 313{
 314    /* Note that we don't fold past bytes */
 315    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
 316    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
 317    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
 318    return val;
 319}
 320#endif
 321
 322/*****************************************************************************/
 323/* PowerPC 601 specific instructions (POWER bridge) */
 324target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
 325{
 326    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
 327
 328    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 329        (int32_t)arg2 == 0) {
 330        env->spr[SPR_MQ] = 0;
 331        return INT32_MIN;
 332    } else {
 333        env->spr[SPR_MQ] = tmp % arg2;
 334        return  tmp / (int32_t)arg2;
 335    }
 336}
 337
 338target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
 339                         target_ulong arg2)
 340{
 341    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
 342
 343    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 344        (int32_t)arg2 == 0) {
 345        env->so = env->ov = 1;
 346        env->spr[SPR_MQ] = 0;
 347        return INT32_MIN;
 348    } else {
 349        env->spr[SPR_MQ] = tmp % arg2;
 350        tmp /= (int32_t)arg2;
 351        if ((int32_t)tmp != tmp) {
 352            env->so = env->ov = 1;
 353        } else {
 354            env->ov = 0;
 355        }
 356        return tmp;
 357    }
 358}
 359
 360target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
 361                         target_ulong arg2)
 362{
 363    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 364        (int32_t)arg2 == 0) {
 365        env->spr[SPR_MQ] = 0;
 366        return INT32_MIN;
 367    } else {
 368        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
 369        return (int32_t)arg1 / (int32_t)arg2;
 370    }
 371}
 372
 373target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
 374                          target_ulong arg2)
 375{
 376    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 377        (int32_t)arg2 == 0) {
 378        env->so = env->ov = 1;
 379        env->spr[SPR_MQ] = 0;
 380        return INT32_MIN;
 381    } else {
 382        env->ov = 0;
 383        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
 384        return (int32_t)arg1 / (int32_t)arg2;
 385    }
 386}
 387
 388/*****************************************************************************/
 389/* 602 specific instructions */
 390/* mfrom is the most crazy instruction ever seen, imho ! */
 391/* Real implementation uses a ROM table. Do the same */
 392/*
 393 * Extremely decomposed:
 394 *                      -arg / 256
 395 * return 256 * log10(10           + 1.0) + 0.5
 396 */
 397#if !defined(CONFIG_USER_ONLY)
 398target_ulong helper_602_mfrom(target_ulong arg)
 399{
 400    if (likely(arg < 602)) {
 401#include "mfrom_table.c.inc"
 402        return mfrom_ROM_table[arg];
 403    } else {
 404        return 0;
 405    }
 406}
 407#endif
 408
 409/*****************************************************************************/
 410/* Altivec extension helpers */
 411#if defined(HOST_WORDS_BIGENDIAN)
 412#define VECTOR_FOR_INORDER_I(index, element)                    \
 413    for (index = 0; index < ARRAY_SIZE(r->element); index++)
 414#else
 415#define VECTOR_FOR_INORDER_I(index, element)                    \
 416    for (index = ARRAY_SIZE(r->element) - 1; index >= 0; index--)
 417#endif
 418
 419/* Saturating arithmetic helpers.  */
 420#define SATCVT(from, to, from_type, to_type, min, max)          \
 421    static inline to_type cvt##from##to(from_type x, int *sat)  \
 422    {                                                           \
 423        to_type r;                                              \
 424                                                                \
 425        if (x < (from_type)min) {                               \
 426            r = min;                                            \
 427            *sat = 1;                                           \
 428        } else if (x > (from_type)max) {                        \
 429            r = max;                                            \
 430            *sat = 1;                                           \
 431        } else {                                                \
 432            r = x;                                              \
 433        }                                                       \
 434        return r;                                               \
 435    }
 436#define SATCVTU(from, to, from_type, to_type, min, max)         \
 437    static inline to_type cvt##from##to(from_type x, int *sat)  \
 438    {                                                           \
 439        to_type r;                                              \
 440                                                                \
 441        if (x > (from_type)max) {                               \
 442            r = max;                                            \
 443            *sat = 1;                                           \
 444        } else {                                                \
 445            r = x;                                              \
 446        }                                                       \
 447        return r;                                               \
 448    }
 449SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
 450SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
 451SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
 452
 453SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
 454SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
 455SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
 456SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
 457SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
 458SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
 459#undef SATCVT
 460#undef SATCVTU
 461
 462void helper_mtvscr(CPUPPCState *env, uint32_t vscr)
 463{
 464    env->vscr = vscr & ~(1u << VSCR_SAT);
 465    /* Which bit we set is completely arbitrary, but clear the rest.  */
 466    env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
 467    env->vscr_sat.u64[1] = 0;
 468    set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
 469}
 470
 471uint32_t helper_mfvscr(CPUPPCState *env)
 472{
 473    uint32_t sat = (env->vscr_sat.u64[0] | env->vscr_sat.u64[1]) != 0;
 474    return env->vscr | (sat << VSCR_SAT);
 475}
 476
 477static inline void set_vscr_sat(CPUPPCState *env)
 478{
 479    /* The choice of non-zero value is arbitrary.  */
 480    env->vscr_sat.u32[0] = 1;
 481}
 482
 483void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 484{
 485    int i;
 486
 487    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
 488        r->u32[i] = ~a->u32[i] < b->u32[i];
 489    }
 490}
 491
 492/* vprtybw */
 493void helper_vprtybw(ppc_avr_t *r, ppc_avr_t *b)
 494{
 495    int i;
 496    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
 497        uint64_t res = b->u32[i] ^ (b->u32[i] >> 16);
 498        res ^= res >> 8;
 499        r->u32[i] = res & 1;
 500    }
 501}
 502
 503/* vprtybd */
 504void helper_vprtybd(ppc_avr_t *r, ppc_avr_t *b)
 505{
 506    int i;
 507    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
 508        uint64_t res = b->u64[i] ^ (b->u64[i] >> 32);
 509        res ^= res >> 16;
 510        res ^= res >> 8;
 511        r->u64[i] = res & 1;
 512    }
 513}
 514
 515/* vprtybq */
 516void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b)
 517{
 518    uint64_t res = b->u64[0] ^ b->u64[1];
 519    res ^= res >> 32;
 520    res ^= res >> 16;
 521    res ^= res >> 8;
 522    r->VsrD(1) = res & 1;
 523    r->VsrD(0) = 0;
 524}
 525
 526#define VARITHFP(suffix, func)                                          \
 527    void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
 528                          ppc_avr_t *b)                                 \
 529    {                                                                   \
 530        int i;                                                          \
 531                                                                        \
 532        for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
 533            r->f32[i] = func(a->f32[i], b->f32[i], &env->vec_status);   \
 534        }                                                               \
 535    }
 536VARITHFP(addfp, float32_add)
 537VARITHFP(subfp, float32_sub)
 538VARITHFP(minfp, float32_min)
 539VARITHFP(maxfp, float32_max)
 540#undef VARITHFP
 541
 542#define VARITHFPFMA(suffix, type)                                       \
 543    void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
 544                           ppc_avr_t *b, ppc_avr_t *c)                  \
 545    {                                                                   \
 546        int i;                                                          \
 547        for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
 548            r->f32[i] = float32_muladd(a->f32[i], c->f32[i], b->f32[i], \
 549                                       type, &env->vec_status);         \
 550        }                                                               \
 551    }
 552VARITHFPFMA(maddfp, 0);
 553VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
 554#undef VARITHFPFMA
 555
 556#define VARITHSAT_CASE(type, op, cvt, element)                          \
 557    {                                                                   \
 558        type result = (type)a->element[i] op (type)b->element[i];       \
 559        r->element[i] = cvt(result, &sat);                              \
 560    }
 561
 562#define VARITHSAT_DO(name, op, optype, cvt, element)                    \
 563    void helper_v##name(ppc_avr_t *r, ppc_avr_t *vscr_sat,              \
 564                        ppc_avr_t *a, ppc_avr_t *b, uint32_t desc)      \
 565    {                                                                   \
 566        int sat = 0;                                                    \
 567        int i;                                                          \
 568                                                                        \
 569        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 570            VARITHSAT_CASE(optype, op, cvt, element);                   \
 571        }                                                               \
 572        if (sat) {                                                      \
 573            vscr_sat->u32[0] = 1;                                       \
 574        }                                                               \
 575    }
 576#define VARITHSAT_SIGNED(suffix, element, optype, cvt)          \
 577    VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)      \
 578    VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
 579#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)        \
 580    VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)      \
 581    VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
 582VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
 583VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
 584VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
 585VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
 586VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
 587VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
 588#undef VARITHSAT_CASE
 589#undef VARITHSAT_DO
 590#undef VARITHSAT_SIGNED
 591#undef VARITHSAT_UNSIGNED
 592
 593#define VAVG_DO(name, element, etype)                                   \
 594    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
 595    {                                                                   \
 596        int i;                                                          \
 597                                                                        \
 598        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 599            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
 600            r->element[i] = x >> 1;                                     \
 601        }                                                               \
 602    }
 603
 604#define VAVG(type, signed_element, signed_type, unsigned_element,       \
 605             unsigned_type)                                             \
 606    VAVG_DO(avgs##type, signed_element, signed_type)                    \
 607    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
 608VAVG(b, s8, int16_t, u8, uint16_t)
 609VAVG(h, s16, int32_t, u16, uint32_t)
 610VAVG(w, s32, int64_t, u32, uint64_t)
 611#undef VAVG_DO
 612#undef VAVG
 613
 614#define VABSDU_DO(name, element)                                        \
 615void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)           \
 616{                                                                       \
 617    int i;                                                              \
 618                                                                        \
 619    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
 620        r->element[i] = (a->element[i] > b->element[i]) ?               \
 621            (a->element[i] - b->element[i]) :                           \
 622            (b->element[i] - a->element[i]);                            \
 623    }                                                                   \
 624}
 625
 626/*
 627 * VABSDU - Vector absolute difference unsigned
 628 *   name    - instruction mnemonic suffix (b: byte, h: halfword, w: word)
 629 *   element - element type to access from vector
 630 */
 631#define VABSDU(type, element)                   \
 632    VABSDU_DO(absdu##type, element)
 633VABSDU(b, u8)
 634VABSDU(h, u16)
 635VABSDU(w, u32)
 636#undef VABSDU_DO
 637#undef VABSDU
 638
 639#define VCF(suffix, cvt, element)                                       \
 640    void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r,             \
 641                            ppc_avr_t *b, uint32_t uim)                 \
 642    {                                                                   \
 643        int i;                                                          \
 644                                                                        \
 645        for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
 646            float32 t = cvt(b->element[i], &env->vec_status);           \
 647            r->f32[i] = float32_scalbn(t, -uim, &env->vec_status);      \
 648        }                                                               \
 649    }
 650VCF(ux, uint32_to_float32, u32)
 651VCF(sx, int32_to_float32, s32)
 652#undef VCF
 653
 654#define VCMP_DO(suffix, compare, element, record)                       \
 655    void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
 656                             ppc_avr_t *a, ppc_avr_t *b)                \
 657    {                                                                   \
 658        uint64_t ones = (uint64_t)-1;                                   \
 659        uint64_t all = ones;                                            \
 660        uint64_t none = 0;                                              \
 661        int i;                                                          \
 662                                                                        \
 663        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 664            uint64_t result = (a->element[i] compare b->element[i] ?    \
 665                               ones : 0x0);                             \
 666            switch (sizeof(a->element[0])) {                            \
 667            case 8:                                                     \
 668                r->u64[i] = result;                                     \
 669                break;                                                  \
 670            case 4:                                                     \
 671                r->u32[i] = result;                                     \
 672                break;                                                  \
 673            case 2:                                                     \
 674                r->u16[i] = result;                                     \
 675                break;                                                  \
 676            case 1:                                                     \
 677                r->u8[i] = result;                                      \
 678                break;                                                  \
 679            }                                                           \
 680            all &= result;                                              \
 681            none |= result;                                             \
 682        }                                                               \
 683        if (record) {                                                   \
 684            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
 685        }                                                               \
 686    }
 687#define VCMP(suffix, compare, element)          \
 688    VCMP_DO(suffix, compare, element, 0)        \
 689    VCMP_DO(suffix##_dot, compare, element, 1)
 690VCMP(equb, ==, u8)
 691VCMP(equh, ==, u16)
 692VCMP(equw, ==, u32)
 693VCMP(equd, ==, u64)
 694VCMP(gtub, >, u8)
 695VCMP(gtuh, >, u16)
 696VCMP(gtuw, >, u32)
 697VCMP(gtud, >, u64)
 698VCMP(gtsb, >, s8)
 699VCMP(gtsh, >, s16)
 700VCMP(gtsw, >, s32)
 701VCMP(gtsd, >, s64)
 702#undef VCMP_DO
 703#undef VCMP
 704
 705#define VCMPNE_DO(suffix, element, etype, cmpzero, record)              \
 706void helper_vcmpne##suffix(CPUPPCState *env, ppc_avr_t *r,              \
 707                            ppc_avr_t *a, ppc_avr_t *b)                 \
 708{                                                                       \
 709    etype ones = (etype)-1;                                             \
 710    etype all = ones;                                                   \
 711    etype result, none = 0;                                             \
 712    int i;                                                              \
 713                                                                        \
 714    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
 715        if (cmpzero) {                                                  \
 716            result = ((a->element[i] == 0)                              \
 717                           || (b->element[i] == 0)                      \
 718                           || (a->element[i] != b->element[i]) ?        \
 719                           ones : 0x0);                                 \
 720        } else {                                                        \
 721            result = (a->element[i] != b->element[i]) ? ones : 0x0;     \
 722        }                                                               \
 723        r->element[i] = result;                                         \
 724        all &= result;                                                  \
 725        none |= result;                                                 \
 726    }                                                                   \
 727    if (record) {                                                       \
 728        env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);           \
 729    }                                                                   \
 730}
 731
 732/*
 733 * VCMPNEZ - Vector compare not equal to zero
 734 *   suffix  - instruction mnemonic suffix (b: byte, h: halfword, w: word)
 735 *   element - element type to access from vector
 736 */
 737#define VCMPNE(suffix, element, etype, cmpzero)         \
 738    VCMPNE_DO(suffix, element, etype, cmpzero, 0)       \
 739    VCMPNE_DO(suffix##_dot, element, etype, cmpzero, 1)
 740VCMPNE(zb, u8, uint8_t, 1)
 741VCMPNE(zh, u16, uint16_t, 1)
 742VCMPNE(zw, u32, uint32_t, 1)
 743VCMPNE(b, u8, uint8_t, 0)
 744VCMPNE(h, u16, uint16_t, 0)
 745VCMPNE(w, u32, uint32_t, 0)
 746#undef VCMPNE_DO
 747#undef VCMPNE
 748
 749#define VCMPFP_DO(suffix, compare, order, record)                       \
 750    void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
 751                             ppc_avr_t *a, ppc_avr_t *b)                \
 752    {                                                                   \
 753        uint32_t ones = (uint32_t)-1;                                   \
 754        uint32_t all = ones;                                            \
 755        uint32_t none = 0;                                              \
 756        int i;                                                          \
 757                                                                        \
 758        for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
 759            uint32_t result;                                            \
 760            FloatRelation rel =                                         \
 761                float32_compare_quiet(a->f32[i], b->f32[i],             \
 762                                      &env->vec_status);                \
 763            if (rel == float_relation_unordered) {                      \
 764                result = 0;                                             \
 765            } else if (rel compare order) {                             \
 766                result = ones;                                          \
 767            } else {                                                    \
 768                result = 0;                                             \
 769            }                                                           \
 770            r->u32[i] = result;                                         \
 771            all &= result;                                              \
 772            none |= result;                                             \
 773        }                                                               \
 774        if (record) {                                                   \
 775            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
 776        }                                                               \
 777    }
 778#define VCMPFP(suffix, compare, order)          \
 779    VCMPFP_DO(suffix, compare, order, 0)        \
 780    VCMPFP_DO(suffix##_dot, compare, order, 1)
 781VCMPFP(eqfp, ==, float_relation_equal)
 782VCMPFP(gefp, !=, float_relation_less)
 783VCMPFP(gtfp, ==, float_relation_greater)
 784#undef VCMPFP_DO
 785#undef VCMPFP
 786
 787static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
 788                                    ppc_avr_t *a, ppc_avr_t *b, int record)
 789{
 790    int i;
 791    int all_in = 0;
 792
 793    for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
 794        FloatRelation le_rel = float32_compare_quiet(a->f32[i], b->f32[i],
 795                                                     &env->vec_status);
 796        if (le_rel == float_relation_unordered) {
 797            r->u32[i] = 0xc0000000;
 798            all_in = 1;
 799        } else {
 800            float32 bneg = float32_chs(b->f32[i]);
 801            FloatRelation ge_rel = float32_compare_quiet(a->f32[i], bneg,
 802                                                         &env->vec_status);
 803            int le = le_rel != float_relation_greater;
 804            int ge = ge_rel != float_relation_less;
 805
 806            r->u32[i] = ((!le) << 31) | ((!ge) << 30);
 807            all_in |= (!le | !ge);
 808        }
 809    }
 810    if (record) {
 811        env->crf[6] = (all_in == 0) << 1;
 812    }
 813}
 814
 815void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 816{
 817    vcmpbfp_internal(env, r, a, b, 0);
 818}
 819
 820void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
 821                        ppc_avr_t *b)
 822{
 823    vcmpbfp_internal(env, r, a, b, 1);
 824}
 825
 826#define VCT(suffix, satcvt, element)                                    \
 827    void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r,             \
 828                            ppc_avr_t *b, uint32_t uim)                 \
 829    {                                                                   \
 830        int i;                                                          \
 831        int sat = 0;                                                    \
 832        float_status s = env->vec_status;                               \
 833                                                                        \
 834        set_float_rounding_mode(float_round_to_zero, &s);               \
 835        for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
 836            if (float32_is_any_nan(b->f32[i])) {                        \
 837                r->element[i] = 0;                                      \
 838            } else {                                                    \
 839                float64 t = float32_to_float64(b->f32[i], &s);          \
 840                int64_t j;                                              \
 841                                                                        \
 842                t = float64_scalbn(t, uim, &s);                         \
 843                j = float64_to_int64(t, &s);                            \
 844                r->element[i] = satcvt(j, &sat);                        \
 845            }                                                           \
 846        }                                                               \
 847        if (sat) {                                                      \
 848            set_vscr_sat(env);                                          \
 849        }                                                               \
 850    }
 851VCT(uxs, cvtsduw, u32)
 852VCT(sxs, cvtsdsw, s32)
 853#undef VCT
 854
 855target_ulong helper_vclzlsbb(ppc_avr_t *r)
 856{
 857    target_ulong count = 0;
 858    int i;
 859    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
 860        if (r->VsrB(i) & 0x01) {
 861            break;
 862        }
 863        count++;
 864    }
 865    return count;
 866}
 867
 868target_ulong helper_vctzlsbb(ppc_avr_t *r)
 869{
 870    target_ulong count = 0;
 871    int i;
 872    for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
 873        if (r->VsrB(i) & 0x01) {
 874            break;
 875        }
 876        count++;
 877    }
 878    return count;
 879}
 880
 881void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
 882                      ppc_avr_t *b, ppc_avr_t *c)
 883{
 884    int sat = 0;
 885    int i;
 886
 887    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 888        int32_t prod = a->s16[i] * b->s16[i];
 889        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
 890
 891        r->s16[i] = cvtswsh(t, &sat);
 892    }
 893
 894    if (sat) {
 895        set_vscr_sat(env);
 896    }
 897}
 898
 899void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
 900                       ppc_avr_t *b, ppc_avr_t *c)
 901{
 902    int sat = 0;
 903    int i;
 904
 905    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 906        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
 907        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
 908        r->s16[i] = cvtswsh(t, &sat);
 909    }
 910
 911    if (sat) {
 912        set_vscr_sat(env);
 913    }
 914}
 915
 916void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 917{
 918    int i;
 919
 920    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 921        int32_t prod = a->s16[i] * b->s16[i];
 922        r->s16[i] = (int16_t) (prod + c->s16[i]);
 923    }
 924}
 925
 926#define VMRG_DO(name, element, access, ofs)                                  \
 927    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)            \
 928    {                                                                        \
 929        ppc_avr_t result;                                                    \
 930        int i, half = ARRAY_SIZE(r->element) / 2;                            \
 931                                                                             \
 932        for (i = 0; i < half; i++) {                                         \
 933            result.access(i * 2 + 0) = a->access(i + ofs);                   \
 934            result.access(i * 2 + 1) = b->access(i + ofs);                   \
 935        }                                                                    \
 936        *r = result;                                                         \
 937    }
 938
 939#define VMRG(suffix, element, access)          \
 940    VMRG_DO(mrgl##suffix, element, access, half)   \
 941    VMRG_DO(mrgh##suffix, element, access, 0)
 942VMRG(b, u8, VsrB)
 943VMRG(h, u16, VsrH)
 944VMRG(w, u32, VsrW)
 945#undef VMRG_DO
 946#undef VMRG
 947
 948void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
 949                     ppc_avr_t *b, ppc_avr_t *c)
 950{
 951    int32_t prod[16];
 952    int i;
 953
 954    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
 955        prod[i] = (int32_t)a->s8[i] * b->u8[i];
 956    }
 957
 958    VECTOR_FOR_INORDER_I(i, s32) {
 959        r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
 960            prod[4 * i + 2] + prod[4 * i + 3];
 961    }
 962}
 963
 964void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
 965                     ppc_avr_t *b, ppc_avr_t *c)
 966{
 967    int32_t prod[8];
 968    int i;
 969
 970    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 971        prod[i] = a->s16[i] * b->s16[i];
 972    }
 973
 974    VECTOR_FOR_INORDER_I(i, s32) {
 975        r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
 976    }
 977}
 978
 979void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
 980                     ppc_avr_t *b, ppc_avr_t *c)
 981{
 982    int32_t prod[8];
 983    int i;
 984    int sat = 0;
 985
 986    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 987        prod[i] = (int32_t)a->s16[i] * b->s16[i];
 988    }
 989
 990    VECTOR_FOR_INORDER_I(i, s32) {
 991        int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
 992
 993        r->u32[i] = cvtsdsw(t, &sat);
 994    }
 995
 996    if (sat) {
 997        set_vscr_sat(env);
 998    }
 999}
1000
1001void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
1002                     ppc_avr_t *b, ppc_avr_t *c)
1003{
1004    uint16_t prod[16];
1005    int i;
1006
1007    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1008        prod[i] = a->u8[i] * b->u8[i];
1009    }
1010
1011    VECTOR_FOR_INORDER_I(i, u32) {
1012        r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
1013            prod[4 * i + 2] + prod[4 * i + 3];
1014    }
1015}
1016
1017void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
1018                     ppc_avr_t *b, ppc_avr_t *c)
1019{
1020    uint32_t prod[8];
1021    int i;
1022
1023    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
1024        prod[i] = a->u16[i] * b->u16[i];
1025    }
1026
1027    VECTOR_FOR_INORDER_I(i, u32) {
1028        r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
1029    }
1030}
1031
1032void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
1033                     ppc_avr_t *b, ppc_avr_t *c)
1034{
1035    uint32_t prod[8];
1036    int i;
1037    int sat = 0;
1038
1039    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
1040        prod[i] = a->u16[i] * b->u16[i];
1041    }
1042
1043    VECTOR_FOR_INORDER_I(i, s32) {
1044        uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
1045
1046        r->u32[i] = cvtuduw(t, &sat);
1047    }
1048
1049    if (sat) {
1050        set_vscr_sat(env);
1051    }
1052}
1053
1054#define VMUL_DO_EVN(name, mul_element, mul_access, prod_access, cast)   \
1055    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
1056    {                                                                   \
1057        int i;                                                          \
1058                                                                        \
1059        for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) {           \
1060            r->prod_access(i >> 1) = (cast)a->mul_access(i) *           \
1061                                     (cast)b->mul_access(i);            \
1062        }                                                               \
1063    }
1064
1065#define VMUL_DO_ODD(name, mul_element, mul_access, prod_access, cast)   \
1066    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
1067    {                                                                   \
1068        int i;                                                          \
1069                                                                        \
1070        for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) {           \
1071            r->prod_access(i >> 1) = (cast)a->mul_access(i + 1) *       \
1072                                     (cast)b->mul_access(i + 1);        \
1073        }                                                               \
1074    }
1075
1076#define VMUL(suffix, mul_element, mul_access, prod_access, cast)       \
1077    VMUL_DO_EVN(mule##suffix, mul_element, mul_access, prod_access, cast)  \
1078    VMUL_DO_ODD(mulo##suffix, mul_element, mul_access, prod_access, cast)
1079VMUL(sb, s8, VsrSB, VsrSH, int16_t)
1080VMUL(sh, s16, VsrSH, VsrSW, int32_t)
1081VMUL(sw, s32, VsrSW, VsrSD, int64_t)
1082VMUL(ub, u8, VsrB, VsrH, uint16_t)
1083VMUL(uh, u16, VsrH, VsrW, uint32_t)
1084VMUL(uw, u32, VsrW, VsrD, uint64_t)
1085#undef VMUL_DO_EVN
1086#undef VMUL_DO_ODD
1087#undef VMUL
1088
1089void helper_vmulhsw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1090{
1091    int i;
1092
1093    for (i = 0; i < 4; i++) {
1094        r->s32[i] = (int32_t)(((int64_t)a->s32[i] * (int64_t)b->s32[i]) >> 32);
1095    }
1096}
1097
1098void helper_vmulhuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1099{
1100    int i;
1101
1102    for (i = 0; i < 4; i++) {
1103        r->u32[i] = (uint32_t)(((uint64_t)a->u32[i] *
1104                               (uint64_t)b->u32[i]) >> 32);
1105    }
1106}
1107
1108void helper_vmulhsd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1109{
1110    uint64_t discard;
1111
1112    muls64(&discard, &r->u64[0], a->s64[0], b->s64[0]);
1113    muls64(&discard, &r->u64[1], a->s64[1], b->s64[1]);
1114}
1115
1116void helper_vmulhud(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1117{
1118    uint64_t discard;
1119
1120    mulu64(&discard, &r->u64[0], a->u64[0], b->u64[0]);
1121    mulu64(&discard, &r->u64[1], a->u64[1], b->u64[1]);
1122}
1123
1124void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1125                  ppc_avr_t *c)
1126{
1127    ppc_avr_t result;
1128    int i;
1129
1130    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1131        int s = c->VsrB(i) & 0x1f;
1132        int index = s & 0xf;
1133
1134        if (s & 0x10) {
1135            result.VsrB(i) = b->VsrB(index);
1136        } else {
1137            result.VsrB(i) = a->VsrB(index);
1138        }
1139    }
1140    *r = result;
1141}
1142
1143void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1144                  ppc_avr_t *c)
1145{
1146    ppc_avr_t result;
1147    int i;
1148
1149    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1150        int s = c->VsrB(i) & 0x1f;
1151        int index = 15 - (s & 0xf);
1152
1153        if (s & 0x10) {
1154            result.VsrB(i) = a->VsrB(index);
1155        } else {
1156            result.VsrB(i) = b->VsrB(index);
1157        }
1158    }
1159    *r = result;
1160}
1161
1162#if defined(HOST_WORDS_BIGENDIAN)
1163#define VBPERMQ_INDEX(avr, i) ((avr)->u8[(i)])
1164#define VBPERMD_INDEX(i) (i)
1165#define VBPERMQ_DW(index) (((index) & 0x40) != 0)
1166#define EXTRACT_BIT(avr, i, index) (extract64((avr)->u64[i], index, 1))
1167#else
1168#define VBPERMQ_INDEX(avr, i) ((avr)->u8[15 - (i)])
1169#define VBPERMD_INDEX(i) (1 - i)
1170#define VBPERMQ_DW(index) (((index) & 0x40) == 0)
1171#define EXTRACT_BIT(avr, i, index) \
1172        (extract64((avr)->u64[1 - i], 63 - index, 1))
1173#endif
1174
1175void helper_vbpermd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1176{
1177    int i, j;
1178    ppc_avr_t result = { .u64 = { 0, 0 } };
1179    VECTOR_FOR_INORDER_I(i, u64) {
1180        for (j = 0; j < 8; j++) {
1181            int index = VBPERMQ_INDEX(b, (i * 8) + j);
1182            if (index < 64 && EXTRACT_BIT(a, i, index)) {
1183                result.u64[VBPERMD_INDEX(i)] |= (0x80 >> j);
1184            }
1185        }
1186    }
1187    *r = result;
1188}
1189
1190void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1191{
1192    int i;
1193    uint64_t perm = 0;
1194
1195    VECTOR_FOR_INORDER_I(i, u8) {
1196        int index = VBPERMQ_INDEX(b, i);
1197
1198        if (index < 128) {
1199            uint64_t mask = (1ull << (63 - (index & 0x3F)));
1200            if (a->u64[VBPERMQ_DW(index)] & mask) {
1201                perm |= (0x8000 >> i);
1202            }
1203        }
1204    }
1205
1206    r->VsrD(0) = perm;
1207    r->VsrD(1) = 0;
1208}
1209
1210#undef VBPERMQ_INDEX
1211#undef VBPERMQ_DW
1212
1213#define PMSUM(name, srcfld, trgfld, trgtyp)                   \
1214void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
1215{                                                             \
1216    int i, j;                                                 \
1217    trgtyp prod[sizeof(ppc_avr_t) / sizeof(a->srcfld[0])];    \
1218                                                              \
1219    VECTOR_FOR_INORDER_I(i, srcfld) {                         \
1220        prod[i] = 0;                                          \
1221        for (j = 0; j < sizeof(a->srcfld[0]) * 8; j++) {      \
1222            if (a->srcfld[i] & (1ull << j)) {                 \
1223                prod[i] ^= ((trgtyp)b->srcfld[i] << j);       \
1224            }                                                 \
1225        }                                                     \
1226    }                                                         \
1227                                                              \
1228    VECTOR_FOR_INORDER_I(i, trgfld) {                         \
1229        r->trgfld[i] = prod[2 * i] ^ prod[2 * i + 1];         \
1230    }                                                         \
1231}
1232
1233PMSUM(vpmsumb, u8, u16, uint16_t)
1234PMSUM(vpmsumh, u16, u32, uint32_t)
1235PMSUM(vpmsumw, u32, u64, uint64_t)
1236
1237void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1238{
1239
1240#ifdef CONFIG_INT128
1241    int i, j;
1242    __uint128_t prod[2];
1243
1244    VECTOR_FOR_INORDER_I(i, u64) {
1245        prod[i] = 0;
1246        for (j = 0; j < 64; j++) {
1247            if (a->u64[i] & (1ull << j)) {
1248                prod[i] ^= (((__uint128_t)b->u64[i]) << j);
1249            }
1250        }
1251    }
1252
1253    r->u128 = prod[0] ^ prod[1];
1254
1255#else
1256    int i, j;
1257    ppc_avr_t prod[2];
1258
1259    VECTOR_FOR_INORDER_I(i, u64) {
1260        prod[i].VsrD(1) = prod[i].VsrD(0) = 0;
1261        for (j = 0; j < 64; j++) {
1262            if (a->u64[i] & (1ull << j)) {
1263                ppc_avr_t bshift;
1264                if (j == 0) {
1265                    bshift.VsrD(0) = 0;
1266                    bshift.VsrD(1) = b->u64[i];
1267                } else {
1268                    bshift.VsrD(0) = b->u64[i] >> (64 - j);
1269                    bshift.VsrD(1) = b->u64[i] << j;
1270                }
1271                prod[i].VsrD(1) ^= bshift.VsrD(1);
1272                prod[i].VsrD(0) ^= bshift.VsrD(0);
1273            }
1274        }
1275    }
1276
1277    r->VsrD(1) = prod[0].VsrD(1) ^ prod[1].VsrD(1);
1278    r->VsrD(0) = prod[0].VsrD(0) ^ prod[1].VsrD(0);
1279#endif
1280}
1281
1282
1283#if defined(HOST_WORDS_BIGENDIAN)
1284#define PKBIG 1
1285#else
1286#define PKBIG 0
1287#endif
1288void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1289{
1290    int i, j;
1291    ppc_avr_t result;
1292#if defined(HOST_WORDS_BIGENDIAN)
1293    const ppc_avr_t *x[2] = { a, b };
1294#else
1295    const ppc_avr_t *x[2] = { b, a };
1296#endif
1297
1298    VECTOR_FOR_INORDER_I(i, u64) {
1299        VECTOR_FOR_INORDER_I(j, u32) {
1300            uint32_t e = x[i]->u32[j];
1301
1302            result.u16[4 * i + j] = (((e >> 9) & 0xfc00) |
1303                                     ((e >> 6) & 0x3e0) |
1304                                     ((e >> 3) & 0x1f));
1305        }
1306    }
1307    *r = result;
1308}
1309
1310#define VPK(suffix, from, to, cvt, dosat)                               \
1311    void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r,             \
1312                            ppc_avr_t *a, ppc_avr_t *b)                 \
1313    {                                                                   \
1314        int i;                                                          \
1315        int sat = 0;                                                    \
1316        ppc_avr_t result;                                               \
1317        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
1318        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
1319                                                                        \
1320        VECTOR_FOR_INORDER_I(i, from) {                                 \
1321            result.to[i] = cvt(a0->from[i], &sat);                      \
1322            result.to[i + ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);\
1323        }                                                               \
1324        *r = result;                                                    \
1325        if (dosat && sat) {                                             \
1326            set_vscr_sat(env);                                          \
1327        }                                                               \
1328    }
1329#define I(x, y) (x)
1330VPK(shss, s16, s8, cvtshsb, 1)
1331VPK(shus, s16, u8, cvtshub, 1)
1332VPK(swss, s32, s16, cvtswsh, 1)
1333VPK(swus, s32, u16, cvtswuh, 1)
1334VPK(sdss, s64, s32, cvtsdsw, 1)
1335VPK(sdus, s64, u32, cvtsduw, 1)
1336VPK(uhus, u16, u8, cvtuhub, 1)
1337VPK(uwus, u32, u16, cvtuwuh, 1)
1338VPK(udus, u64, u32, cvtuduw, 1)
1339VPK(uhum, u16, u8, I, 0)
1340VPK(uwum, u32, u16, I, 0)
1341VPK(udum, u64, u32, I, 0)
1342#undef I
1343#undef VPK
1344#undef PKBIG
1345
1346void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1347{
1348    int i;
1349
1350    for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1351        r->f32[i] = float32_div(float32_one, b->f32[i], &env->vec_status);
1352    }
1353}
1354
1355#define VRFI(suffix, rounding)                                  \
1356    void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r,    \
1357                             ppc_avr_t *b)                      \
1358    {                                                           \
1359        int i;                                                  \
1360        float_status s = env->vec_status;                       \
1361                                                                \
1362        set_float_rounding_mode(rounding, &s);                  \
1363        for (i = 0; i < ARRAY_SIZE(r->f32); i++) {              \
1364            r->f32[i] = float32_round_to_int (b->f32[i], &s);   \
1365        }                                                       \
1366    }
1367VRFI(n, float_round_nearest_even)
1368VRFI(m, float_round_down)
1369VRFI(p, float_round_up)
1370VRFI(z, float_round_to_zero)
1371#undef VRFI
1372
1373void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1374{
1375    int i;
1376
1377    for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1378        float32 t = float32_sqrt(b->f32[i], &env->vec_status);
1379
1380        r->f32[i] = float32_div(float32_one, t, &env->vec_status);
1381    }
1382}
1383
1384#define VRLMI(name, size, element, insert)                            \
1385void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)          \
1386{                                                                     \
1387    int i;                                                            \
1388    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                    \
1389        uint##size##_t src1 = a->element[i];                          \
1390        uint##size##_t src2 = b->element[i];                          \
1391        uint##size##_t src3 = r->element[i];                          \
1392        uint##size##_t begin, end, shift, mask, rot_val;              \
1393                                                                      \
1394        shift = extract##size(src2, 0, 6);                            \
1395        end   = extract##size(src2, 8, 6);                            \
1396        begin = extract##size(src2, 16, 6);                           \
1397        rot_val = rol##size(src1, shift);                             \
1398        mask = mask_u##size(begin, end);                              \
1399        if (insert) {                                                 \
1400            r->element[i] = (rot_val & mask) | (src3 & ~mask);        \
1401        } else {                                                      \
1402            r->element[i] = (rot_val & mask);                         \
1403        }                                                             \
1404    }                                                                 \
1405}
1406
1407VRLMI(vrldmi, 64, u64, 1);
1408VRLMI(vrlwmi, 32, u32, 1);
1409VRLMI(vrldnm, 64, u64, 0);
1410VRLMI(vrlwnm, 32, u32, 0);
1411
1412void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1413                 ppc_avr_t *c)
1414{
1415    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1416    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1417}
1418
1419void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1420{
1421    int i;
1422
1423    for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1424        r->f32[i] = float32_exp2(b->f32[i], &env->vec_status);
1425    }
1426}
1427
1428void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1429{
1430    int i;
1431
1432    for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1433        r->f32[i] = float32_log2(b->f32[i], &env->vec_status);
1434    }
1435}
1436
1437#if defined(HOST_WORDS_BIGENDIAN)
1438#define VEXTU_X_DO(name, size, left)                                \
1439    target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b)  \
1440    {                                                               \
1441        int index;                                                  \
1442        if (left) {                                                 \
1443            index = (a & 0xf) * 8;                                  \
1444        } else {                                                    \
1445            index = ((15 - (a & 0xf) + 1) * 8) - size;              \
1446        }                                                           \
1447        return int128_getlo(int128_rshift(b->s128, index)) &        \
1448            MAKE_64BIT_MASK(0, size);                               \
1449    }
1450#else
1451#define VEXTU_X_DO(name, size, left)                                \
1452    target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b)  \
1453    {                                                               \
1454        int index;                                                  \
1455        if (left) {                                                 \
1456            index = ((15 - (a & 0xf) + 1) * 8) - size;              \
1457        } else {                                                    \
1458            index = (a & 0xf) * 8;                                  \
1459        }                                                           \
1460        return int128_getlo(int128_rshift(b->s128, index)) &        \
1461            MAKE_64BIT_MASK(0, size);                               \
1462    }
1463#endif
1464
1465VEXTU_X_DO(vextublx,  8, 1)
1466VEXTU_X_DO(vextuhlx, 16, 1)
1467VEXTU_X_DO(vextuwlx, 32, 1)
1468VEXTU_X_DO(vextubrx,  8, 0)
1469VEXTU_X_DO(vextuhrx, 16, 0)
1470VEXTU_X_DO(vextuwrx, 32, 0)
1471#undef VEXTU_X_DO
1472
1473void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1474{
1475    int i;
1476    unsigned int shift, bytes, size;
1477
1478    size = ARRAY_SIZE(r->u8);
1479    for (i = 0; i < size; i++) {
1480        shift = b->VsrB(i) & 0x7;             /* extract shift value */
1481        bytes = (a->VsrB(i) << 8) +           /* extract adjacent bytes */
1482            (((i + 1) < size) ? a->VsrB(i + 1) : 0);
1483        r->VsrB(i) = (bytes << shift) >> 8;   /* shift and store result */
1484    }
1485}
1486
1487void helper_vsrv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1488{
1489    int i;
1490    unsigned int shift, bytes;
1491
1492    /*
1493     * Use reverse order, as destination and source register can be
1494     * same. Its being modified in place saving temporary, reverse
1495     * order will guarantee that computed result is not fed back.
1496     */
1497    for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
1498        shift = b->VsrB(i) & 0x7;               /* extract shift value */
1499        bytes = ((i ? a->VsrB(i - 1) : 0) << 8) + a->VsrB(i);
1500                                                /* extract adjacent bytes */
1501        r->VsrB(i) = (bytes >> shift) & 0xFF;   /* shift and store result */
1502    }
1503}
1504
1505void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1506{
1507    int sh = shift & 0xf;
1508    int i;
1509    ppc_avr_t result;
1510
1511    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1512        int index = sh + i;
1513        if (index > 0xf) {
1514            result.VsrB(i) = b->VsrB(index - 0x10);
1515        } else {
1516            result.VsrB(i) = a->VsrB(index);
1517        }
1518    }
1519    *r = result;
1520}
1521
1522void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1523{
1524    int sh = (b->VsrB(0xf) >> 3) & 0xf;
1525
1526#if defined(HOST_WORDS_BIGENDIAN)
1527    memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1528    memset(&r->u8[16 - sh], 0, sh);
1529#else
1530    memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1531    memset(&r->u8[0], 0, sh);
1532#endif
1533}
1534
1535#if defined(HOST_WORDS_BIGENDIAN)
1536#define VINSERT(suffix, element)                                            \
1537    void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
1538    {                                                                       \
1539        memmove(&r->u8[index], &b->u8[8 - sizeof(r->element[0])],           \
1540               sizeof(r->element[0]));                                      \
1541    }
1542#else
1543#define VINSERT(suffix, element)                                            \
1544    void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
1545    {                                                                       \
1546        uint32_t d = (16 - index) - sizeof(r->element[0]);                  \
1547        memmove(&r->u8[d], &b->u8[8], sizeof(r->element[0]));               \
1548    }
1549#endif
1550VINSERT(b, u8)
1551VINSERT(h, u16)
1552VINSERT(w, u32)
1553VINSERT(d, u64)
1554#undef VINSERT
1555#if defined(HOST_WORDS_BIGENDIAN)
1556#define VEXTRACT(suffix, element)                                            \
1557    void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
1558    {                                                                        \
1559        uint32_t es = sizeof(r->element[0]);                                 \
1560        memmove(&r->u8[8 - es], &b->u8[index], es);                          \
1561        memset(&r->u8[8], 0, 8);                                             \
1562        memset(&r->u8[0], 0, 8 - es);                                        \
1563    }
1564#else
1565#define VEXTRACT(suffix, element)                                            \
1566    void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
1567    {                                                                        \
1568        uint32_t es = sizeof(r->element[0]);                                 \
1569        uint32_t s = (16 - index) - es;                                      \
1570        memmove(&r->u8[8], &b->u8[s], es);                                   \
1571        memset(&r->u8[0], 0, 8);                                             \
1572        memset(&r->u8[8 + es], 0, 8 - es);                                   \
1573    }
1574#endif
1575VEXTRACT(ub, u8)
1576VEXTRACT(uh, u16)
1577VEXTRACT(uw, u32)
1578VEXTRACT(d, u64)
1579#undef VEXTRACT
1580
1581void helper_xxextractuw(CPUPPCState *env, ppc_vsr_t *xt,
1582                        ppc_vsr_t *xb, uint32_t index)
1583{
1584    ppc_vsr_t t = { };
1585    size_t es = sizeof(uint32_t);
1586    uint32_t ext_index;
1587    int i;
1588
1589    ext_index = index;
1590    for (i = 0; i < es; i++, ext_index++) {
1591        t.VsrB(8 - es + i) = xb->VsrB(ext_index % 16);
1592    }
1593
1594    *xt = t;
1595}
1596
1597void helper_xxinsertw(CPUPPCState *env, ppc_vsr_t *xt,
1598                      ppc_vsr_t *xb, uint32_t index)
1599{
1600    ppc_vsr_t t = *xt;
1601    size_t es = sizeof(uint32_t);
1602    int ins_index, i = 0;
1603
1604    ins_index = index;
1605    for (i = 0; i < es && ins_index < 16; i++, ins_index++) {
1606        t.VsrB(ins_index) = xb->VsrB(8 - es + i);
1607    }
1608
1609    *xt = t;
1610}
1611
1612#define VEXT_SIGNED(name, element, cast)                            \
1613void helper_##name(ppc_avr_t *r, ppc_avr_t *b)                      \
1614{                                                                   \
1615    int i;                                                          \
1616    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1617        r->element[i] = (cast)b->element[i];                        \
1618    }                                                               \
1619}
1620VEXT_SIGNED(vextsb2w, s32, int8_t)
1621VEXT_SIGNED(vextsb2d, s64, int8_t)
1622VEXT_SIGNED(vextsh2w, s32, int16_t)
1623VEXT_SIGNED(vextsh2d, s64, int16_t)
1624VEXT_SIGNED(vextsw2d, s64, int32_t)
1625#undef VEXT_SIGNED
1626
1627#define VNEG(name, element)                                         \
1628void helper_##name(ppc_avr_t *r, ppc_avr_t *b)                      \
1629{                                                                   \
1630    int i;                                                          \
1631    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1632        r->element[i] = -b->element[i];                             \
1633    }                                                               \
1634}
1635VNEG(vnegw, s32)
1636VNEG(vnegd, s64)
1637#undef VNEG
1638
1639void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1640{
1641    int sh = (b->VsrB(0xf) >> 3) & 0xf;
1642
1643#if defined(HOST_WORDS_BIGENDIAN)
1644    memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1645    memset(&r->u8[0], 0, sh);
1646#else
1647    memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1648    memset(&r->u8[16 - sh], 0, sh);
1649#endif
1650}
1651
1652void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1653{
1654    int i;
1655
1656    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1657        r->u32[i] = a->u32[i] >= b->u32[i];
1658    }
1659}
1660
1661void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1662{
1663    int64_t t;
1664    int i, upper;
1665    ppc_avr_t result;
1666    int sat = 0;
1667
1668    upper = ARRAY_SIZE(r->s32) - 1;
1669    t = (int64_t)b->VsrSW(upper);
1670    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1671        t += a->VsrSW(i);
1672        result.VsrSW(i) = 0;
1673    }
1674    result.VsrSW(upper) = cvtsdsw(t, &sat);
1675    *r = result;
1676
1677    if (sat) {
1678        set_vscr_sat(env);
1679    }
1680}
1681
1682void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1683{
1684    int i, j, upper;
1685    ppc_avr_t result;
1686    int sat = 0;
1687
1688    upper = 1;
1689    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1690        int64_t t = (int64_t)b->VsrSW(upper + i * 2);
1691
1692        result.VsrD(i) = 0;
1693        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1694            t += a->VsrSW(2 * i + j);
1695        }
1696        result.VsrSW(upper + i * 2) = cvtsdsw(t, &sat);
1697    }
1698
1699    *r = result;
1700    if (sat) {
1701        set_vscr_sat(env);
1702    }
1703}
1704
1705void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1706{
1707    int i, j;
1708    int sat = 0;
1709
1710    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1711        int64_t t = (int64_t)b->s32[i];
1712
1713        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1714            t += a->s8[4 * i + j];
1715        }
1716        r->s32[i] = cvtsdsw(t, &sat);
1717    }
1718
1719    if (sat) {
1720        set_vscr_sat(env);
1721    }
1722}
1723
1724void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1725{
1726    int sat = 0;
1727    int i;
1728
1729    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1730        int64_t t = (int64_t)b->s32[i];
1731
1732        t += a->s16[2 * i] + a->s16[2 * i + 1];
1733        r->s32[i] = cvtsdsw(t, &sat);
1734    }
1735
1736    if (sat) {
1737        set_vscr_sat(env);
1738    }
1739}
1740
1741void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1742{
1743    int i, j;
1744    int sat = 0;
1745
1746    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1747        uint64_t t = (uint64_t)b->u32[i];
1748
1749        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1750            t += a->u8[4 * i + j];
1751        }
1752        r->u32[i] = cvtuduw(t, &sat);
1753    }
1754
1755    if (sat) {
1756        set_vscr_sat(env);
1757    }
1758}
1759
1760#if defined(HOST_WORDS_BIGENDIAN)
1761#define UPKHI 1
1762#define UPKLO 0
1763#else
1764#define UPKHI 0
1765#define UPKLO 1
1766#endif
1767#define VUPKPX(suffix, hi)                                              \
1768    void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
1769    {                                                                   \
1770        int i;                                                          \
1771        ppc_avr_t result;                                               \
1772                                                                        \
1773        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {                      \
1774            uint16_t e = b->u16[hi ? i : i + 4];                        \
1775            uint8_t a = (e >> 15) ? 0xff : 0;                           \
1776            uint8_t r = (e >> 10) & 0x1f;                               \
1777            uint8_t g = (e >> 5) & 0x1f;                                \
1778            uint8_t b = e & 0x1f;                                       \
1779                                                                        \
1780            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
1781        }                                                               \
1782        *r = result;                                                    \
1783    }
1784VUPKPX(lpx, UPKLO)
1785VUPKPX(hpx, UPKHI)
1786#undef VUPKPX
1787
1788#define VUPK(suffix, unpacked, packee, hi)                              \
1789    void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
1790    {                                                                   \
1791        int i;                                                          \
1792        ppc_avr_t result;                                               \
1793                                                                        \
1794        if (hi) {                                                       \
1795            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
1796                result.unpacked[i] = b->packee[i];                      \
1797            }                                                           \
1798        } else {                                                        \
1799            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1800                 i++) {                                                 \
1801                result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1802            }                                                           \
1803        }                                                               \
1804        *r = result;                                                    \
1805    }
1806VUPK(hsb, s16, s8, UPKHI)
1807VUPK(hsh, s32, s16, UPKHI)
1808VUPK(hsw, s64, s32, UPKHI)
1809VUPK(lsb, s16, s8, UPKLO)
1810VUPK(lsh, s32, s16, UPKLO)
1811VUPK(lsw, s64, s32, UPKLO)
1812#undef VUPK
1813#undef UPKHI
1814#undef UPKLO
1815
1816#define VGENERIC_DO(name, element)                                      \
1817    void helper_v##name(ppc_avr_t *r, ppc_avr_t *b)                     \
1818    {                                                                   \
1819        int i;                                                          \
1820                                                                        \
1821        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1822            r->element[i] = name(b->element[i]);                        \
1823        }                                                               \
1824    }
1825
1826#define clzb(v) ((v) ? clz32((uint32_t)(v) << 24) : 8)
1827#define clzh(v) ((v) ? clz32((uint32_t)(v) << 16) : 16)
1828
1829VGENERIC_DO(clzb, u8)
1830VGENERIC_DO(clzh, u16)
1831
1832#undef clzb
1833#undef clzh
1834
1835#define ctzb(v) ((v) ? ctz32(v) : 8)
1836#define ctzh(v) ((v) ? ctz32(v) : 16)
1837#define ctzw(v) ctz32((v))
1838#define ctzd(v) ctz64((v))
1839
1840VGENERIC_DO(ctzb, u8)
1841VGENERIC_DO(ctzh, u16)
1842VGENERIC_DO(ctzw, u32)
1843VGENERIC_DO(ctzd, u64)
1844
1845#undef ctzb
1846#undef ctzh
1847#undef ctzw
1848#undef ctzd
1849
1850#define popcntb(v) ctpop8(v)
1851#define popcnth(v) ctpop16(v)
1852#define popcntw(v) ctpop32(v)
1853#define popcntd(v) ctpop64(v)
1854
1855VGENERIC_DO(popcntb, u8)
1856VGENERIC_DO(popcnth, u16)
1857VGENERIC_DO(popcntw, u32)
1858VGENERIC_DO(popcntd, u64)
1859
1860#undef popcntb
1861#undef popcnth
1862#undef popcntw
1863#undef popcntd
1864
1865#undef VGENERIC_DO
1866
1867#if defined(HOST_WORDS_BIGENDIAN)
1868#define QW_ONE { .u64 = { 0, 1 } }
1869#else
1870#define QW_ONE { .u64 = { 1, 0 } }
1871#endif
1872
1873#ifndef CONFIG_INT128
1874
1875static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a)
1876{
1877    t->u64[0] = ~a.u64[0];
1878    t->u64[1] = ~a.u64[1];
1879}
1880
1881static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b)
1882{
1883    if (a.VsrD(0) < b.VsrD(0)) {
1884        return -1;
1885    } else if (a.VsrD(0) > b.VsrD(0)) {
1886        return 1;
1887    } else if (a.VsrD(1) < b.VsrD(1)) {
1888        return -1;
1889    } else if (a.VsrD(1) > b.VsrD(1)) {
1890        return 1;
1891    } else {
1892        return 0;
1893    }
1894}
1895
1896static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
1897{
1898    t->VsrD(1) = a.VsrD(1) + b.VsrD(1);
1899    t->VsrD(0) = a.VsrD(0) + b.VsrD(0) +
1900                     (~a.VsrD(1) < b.VsrD(1));
1901}
1902
1903static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
1904{
1905    ppc_avr_t not_a;
1906    t->VsrD(1) = a.VsrD(1) + b.VsrD(1);
1907    t->VsrD(0) = a.VsrD(0) + b.VsrD(0) +
1908                     (~a.VsrD(1) < b.VsrD(1));
1909    avr_qw_not(&not_a, a);
1910    return avr_qw_cmpu(not_a, b) < 0;
1911}
1912
1913#endif
1914
1915void helper_vadduqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1916{
1917#ifdef CONFIG_INT128
1918    r->u128 = a->u128 + b->u128;
1919#else
1920    avr_qw_add(r, *a, *b);
1921#endif
1922}
1923
1924void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1925{
1926#ifdef CONFIG_INT128
1927    r->u128 = a->u128 + b->u128 + (c->u128 & 1);
1928#else
1929
1930    if (c->VsrD(1) & 1) {
1931        ppc_avr_t tmp;
1932
1933        tmp.VsrD(0) = 0;
1934        tmp.VsrD(1) = c->VsrD(1) & 1;
1935        avr_qw_add(&tmp, *a, tmp);
1936        avr_qw_add(r, tmp, *b);
1937    } else {
1938        avr_qw_add(r, *a, *b);
1939    }
1940#endif
1941}
1942
1943void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1944{
1945#ifdef CONFIG_INT128
1946    r->u128 = (~a->u128 < b->u128);
1947#else
1948    ppc_avr_t not_a;
1949
1950    avr_qw_not(&not_a, *a);
1951
1952    r->VsrD(0) = 0;
1953    r->VsrD(1) = (avr_qw_cmpu(not_a, *b) < 0);
1954#endif
1955}
1956
1957void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1958{
1959#ifdef CONFIG_INT128
1960    int carry_out = (~a->u128 < b->u128);
1961    if (!carry_out && (c->u128 & 1)) {
1962        carry_out = ((a->u128 + b->u128 + 1) == 0) &&
1963                    ((a->u128 != 0) || (b->u128 != 0));
1964    }
1965    r->u128 = carry_out;
1966#else
1967
1968    int carry_in = c->VsrD(1) & 1;
1969    int carry_out = 0;
1970    ppc_avr_t tmp;
1971
1972    carry_out = avr_qw_addc(&tmp, *a, *b);
1973
1974    if (!carry_out && carry_in) {
1975        ppc_avr_t one = QW_ONE;
1976        carry_out = avr_qw_addc(&tmp, tmp, one);
1977    }
1978    r->VsrD(0) = 0;
1979    r->VsrD(1) = carry_out;
1980#endif
1981}
1982
1983void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1984{
1985#ifdef CONFIG_INT128
1986    r->u128 = a->u128 - b->u128;
1987#else
1988    ppc_avr_t tmp;
1989    ppc_avr_t one = QW_ONE;
1990
1991    avr_qw_not(&tmp, *b);
1992    avr_qw_add(&tmp, *a, tmp);
1993    avr_qw_add(r, tmp, one);
1994#endif
1995}
1996
1997void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1998{
1999#ifdef CONFIG_INT128
2000    r->u128 = a->u128 + ~b->u128 + (c->u128 & 1);
2001#else
2002    ppc_avr_t tmp, sum;
2003
2004    avr_qw_not(&tmp, *b);
2005    avr_qw_add(&sum, *a, tmp);
2006
2007    tmp.VsrD(0) = 0;
2008    tmp.VsrD(1) = c->VsrD(1) & 1;
2009    avr_qw_add(r, sum, tmp);
2010#endif
2011}
2012
2013void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2014{
2015#ifdef CONFIG_INT128
2016    r->u128 = (~a->u128 < ~b->u128) ||
2017                 (a->u128 + ~b->u128 == (__uint128_t)-1);
2018#else
2019    int carry = (avr_qw_cmpu(*a, *b) > 0);
2020    if (!carry) {
2021        ppc_avr_t tmp;
2022        avr_qw_not(&tmp, *b);
2023        avr_qw_add(&tmp, *a, tmp);
2024        carry = ((tmp.VsrSD(0) == -1ull) && (tmp.VsrSD(1) == -1ull));
2025    }
2026    r->VsrD(0) = 0;
2027    r->VsrD(1) = carry;
2028#endif
2029}
2030
2031void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2032{
2033#ifdef CONFIG_INT128
2034    r->u128 =
2035        (~a->u128 < ~b->u128) ||
2036        ((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1));
2037#else
2038    int carry_in = c->VsrD(1) & 1;
2039    int carry_out = (avr_qw_cmpu(*a, *b) > 0);
2040    if (!carry_out && carry_in) {
2041        ppc_avr_t tmp;
2042        avr_qw_not(&tmp, *b);
2043        avr_qw_add(&tmp, *a, tmp);
2044        carry_out = ((tmp.VsrD(0) == -1ull) && (tmp.VsrD(1) == -1ull));
2045    }
2046
2047    r->VsrD(0) = 0;
2048    r->VsrD(1) = carry_out;
2049#endif
2050}
2051
2052#define BCD_PLUS_PREF_1 0xC
2053#define BCD_PLUS_PREF_2 0xF
2054#define BCD_PLUS_ALT_1  0xA
2055#define BCD_NEG_PREF    0xD
2056#define BCD_NEG_ALT     0xB
2057#define BCD_PLUS_ALT_2  0xE
2058#define NATIONAL_PLUS   0x2B
2059#define NATIONAL_NEG    0x2D
2060
2061#define BCD_DIG_BYTE(n) (15 - ((n) / 2))
2062
2063static int bcd_get_sgn(ppc_avr_t *bcd)
2064{
2065    switch (bcd->VsrB(BCD_DIG_BYTE(0)) & 0xF) {
2066    case BCD_PLUS_PREF_1:
2067    case BCD_PLUS_PREF_2:
2068    case BCD_PLUS_ALT_1:
2069    case BCD_PLUS_ALT_2:
2070    {
2071        return 1;
2072    }
2073
2074    case BCD_NEG_PREF:
2075    case BCD_NEG_ALT:
2076    {
2077        return -1;
2078    }
2079
2080    default:
2081    {
2082        return 0;
2083    }
2084    }
2085}
2086
2087static int bcd_preferred_sgn(int sgn, int ps)
2088{
2089    if (sgn >= 0) {
2090        return (ps == 0) ? BCD_PLUS_PREF_1 : BCD_PLUS_PREF_2;
2091    } else {
2092        return BCD_NEG_PREF;
2093    }
2094}
2095
2096static uint8_t bcd_get_digit(ppc_avr_t *bcd, int n, int *invalid)
2097{
2098    uint8_t result;
2099    if (n & 1) {
2100        result = bcd->VsrB(BCD_DIG_BYTE(n)) >> 4;
2101    } else {
2102       result = bcd->VsrB(BCD_DIG_BYTE(n)) & 0xF;
2103    }
2104
2105    if (unlikely(result > 9)) {
2106        *invalid = true;
2107    }
2108    return result;
2109}
2110
2111static void bcd_put_digit(ppc_avr_t *bcd, uint8_t digit, int n)
2112{
2113    if (n & 1) {
2114        bcd->VsrB(BCD_DIG_BYTE(n)) &= 0x0F;
2115        bcd->VsrB(BCD_DIG_BYTE(n)) |= (digit << 4);
2116    } else {
2117        bcd->VsrB(BCD_DIG_BYTE(n)) &= 0xF0;
2118        bcd->VsrB(BCD_DIG_BYTE(n)) |= digit;
2119    }
2120}
2121
2122static bool bcd_is_valid(ppc_avr_t *bcd)
2123{
2124    int i;
2125    int invalid = 0;
2126
2127    if (bcd_get_sgn(bcd) == 0) {
2128        return false;
2129    }
2130
2131    for (i = 1; i < 32; i++) {
2132        bcd_get_digit(bcd, i, &invalid);
2133        if (unlikely(invalid)) {
2134            return false;
2135        }
2136    }
2137    return true;
2138}
2139
2140static int bcd_cmp_zero(ppc_avr_t *bcd)
2141{
2142    if (bcd->VsrD(0) == 0 && (bcd->VsrD(1) >> 4) == 0) {
2143        return CRF_EQ;
2144    } else {
2145        return (bcd_get_sgn(bcd) == 1) ? CRF_GT : CRF_LT;
2146    }
2147}
2148
2149static uint16_t get_national_digit(ppc_avr_t *reg, int n)
2150{
2151    return reg->VsrH(7 - n);
2152}
2153
2154static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n)
2155{
2156    reg->VsrH(7 - n) = val;
2157}
2158
2159static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b)
2160{
2161    int i;
2162    int invalid = 0;
2163    for (i = 31; i > 0; i--) {
2164        uint8_t dig_a = bcd_get_digit(a, i, &invalid);
2165        uint8_t dig_b = bcd_get_digit(b, i, &invalid);
2166        if (unlikely(invalid)) {
2167            return 0; /* doesn't matter */
2168        } else if (dig_a > dig_b) {
2169            return 1;
2170        } else if (dig_a < dig_b) {
2171            return -1;
2172        }
2173    }
2174
2175    return 0;
2176}
2177
2178static int bcd_add_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
2179                       int *overflow)
2180{
2181    int carry = 0;
2182    int i;
2183    int is_zero = 1;
2184
2185    for (i = 1; i <= 31; i++) {
2186        uint8_t digit = bcd_get_digit(a, i, invalid) +
2187                        bcd_get_digit(b, i, invalid) + carry;
2188        is_zero &= (digit == 0);
2189        if (digit > 9) {
2190            carry = 1;
2191            digit -= 10;
2192        } else {
2193            carry = 0;
2194        }
2195
2196        bcd_put_digit(t, digit, i);
2197    }
2198
2199    *overflow = carry;
2200    return is_zero;
2201}
2202
2203static void bcd_sub_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
2204                       int *overflow)
2205{
2206    int carry = 0;
2207    int i;
2208
2209    for (i = 1; i <= 31; i++) {
2210        uint8_t digit = bcd_get_digit(a, i, invalid) -
2211                        bcd_get_digit(b, i, invalid) + carry;
2212        if (digit & 0x80) {
2213            carry = -1;
2214            digit += 10;
2215        } else {
2216            carry = 0;
2217        }
2218
2219        bcd_put_digit(t, digit, i);
2220    }
2221
2222    *overflow = carry;
2223}
2224
2225uint32_t helper_bcdadd(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2226{
2227
2228    int sgna = bcd_get_sgn(a);
2229    int sgnb = bcd_get_sgn(b);
2230    int invalid = (sgna == 0) || (sgnb == 0);
2231    int overflow = 0;
2232    int zero = 0;
2233    uint32_t cr = 0;
2234    ppc_avr_t result = { .u64 = { 0, 0 } };
2235
2236    if (!invalid) {
2237        if (sgna == sgnb) {
2238            result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgna, ps);
2239            zero = bcd_add_mag(&result, a, b, &invalid, &overflow);
2240            cr = (sgna > 0) ? CRF_GT : CRF_LT;
2241        } else {
2242            int magnitude = bcd_cmp_mag(a, b);
2243            if (magnitude > 0) {
2244                result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgna, ps);
2245                bcd_sub_mag(&result, a, b, &invalid, &overflow);
2246                cr = (sgna > 0) ? CRF_GT : CRF_LT;
2247            } else if (magnitude < 0) {
2248                result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgnb, ps);
2249                bcd_sub_mag(&result, b, a, &invalid, &overflow);
2250                cr = (sgnb > 0) ? CRF_GT : CRF_LT;
2251            } else {
2252                result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(0, ps);
2253                cr = CRF_EQ;
2254            }
2255        }
2256    }
2257
2258    if (unlikely(invalid)) {
2259        result.VsrD(0) = result.VsrD(1) = -1;
2260        cr = CRF_SO;
2261    } else if (overflow) {
2262        cr |= CRF_SO;
2263    } else if (zero) {
2264        cr |= CRF_EQ;
2265    }
2266
2267    *r = result;
2268
2269    return cr;
2270}
2271
2272uint32_t helper_bcdsub(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2273{
2274    ppc_avr_t bcopy = *b;
2275    int sgnb = bcd_get_sgn(b);
2276    if (sgnb < 0) {
2277        bcd_put_digit(&bcopy, BCD_PLUS_PREF_1, 0);
2278    } else if (sgnb > 0) {
2279        bcd_put_digit(&bcopy, BCD_NEG_PREF, 0);
2280    }
2281    /* else invalid ... defer to bcdadd code for proper handling */
2282
2283    return helper_bcdadd(r, a, &bcopy, ps);
2284}
2285
2286uint32_t helper_bcdcfn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2287{
2288    int i;
2289    int cr = 0;
2290    uint16_t national = 0;
2291    uint16_t sgnb = get_national_digit(b, 0);
2292    ppc_avr_t ret = { .u64 = { 0, 0 } };
2293    int invalid = (sgnb != NATIONAL_PLUS && sgnb != NATIONAL_NEG);
2294
2295    for (i = 1; i < 8; i++) {
2296        national = get_national_digit(b, i);
2297        if (unlikely(national < 0x30 || national > 0x39)) {
2298            invalid = 1;
2299            break;
2300        }
2301
2302        bcd_put_digit(&ret, national & 0xf, i);
2303    }
2304
2305    if (sgnb == NATIONAL_PLUS) {
2306        bcd_put_digit(&ret, (ps == 0) ? BCD_PLUS_PREF_1 : BCD_PLUS_PREF_2, 0);
2307    } else {
2308        bcd_put_digit(&ret, BCD_NEG_PREF, 0);
2309    }
2310
2311    cr = bcd_cmp_zero(&ret);
2312
2313    if (unlikely(invalid)) {
2314        cr = CRF_SO;
2315    }
2316
2317    *r = ret;
2318
2319    return cr;
2320}
2321
2322uint32_t helper_bcdctn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2323{
2324    int i;
2325    int cr = 0;
2326    int sgnb = bcd_get_sgn(b);
2327    int invalid = (sgnb == 0);
2328    ppc_avr_t ret = { .u64 = { 0, 0 } };
2329
2330    int ox_flag = (b->VsrD(0) != 0) || ((b->VsrD(1) >> 32) != 0);
2331
2332    for (i = 1; i < 8; i++) {
2333        set_national_digit(&ret, 0x30 + bcd_get_digit(b, i, &invalid), i);
2334
2335        if (unlikely(invalid)) {
2336            break;
2337        }
2338    }
2339    set_national_digit(&ret, (sgnb == -1) ? NATIONAL_NEG : NATIONAL_PLUS, 0);
2340
2341    cr = bcd_cmp_zero(b);
2342
2343    if (ox_flag) {
2344        cr |= CRF_SO;
2345    }
2346
2347    if (unlikely(invalid)) {
2348        cr = CRF_SO;
2349    }
2350
2351    *r = ret;
2352
2353    return cr;
2354}
2355
2356uint32_t helper_bcdcfz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2357{
2358    int i;
2359    int cr = 0;
2360    int invalid = 0;
2361    int zone_digit = 0;
2362    int zone_lead = ps ? 0xF : 0x3;
2363    int digit = 0;
2364    ppc_avr_t ret = { .u64 = { 0, 0 } };
2365    int sgnb = b->VsrB(BCD_DIG_BYTE(0)) >> 4;
2366
2367    if (unlikely((sgnb < 0xA) && ps)) {
2368        invalid = 1;
2369    }
2370
2371    for (i = 0; i < 16; i++) {
2372        zone_digit = i ? b->VsrB(BCD_DIG_BYTE(i * 2)) >> 4 : zone_lead;
2373        digit = b->VsrB(BCD_DIG_BYTE(i * 2)) & 0xF;
2374        if (unlikely(zone_digit != zone_lead || digit > 0x9)) {
2375            invalid = 1;
2376            break;
2377        }
2378
2379        bcd_put_digit(&ret, digit, i + 1);
2380    }
2381
2382    if ((ps && (sgnb == 0xB || sgnb == 0xD)) ||
2383            (!ps && (sgnb & 0x4))) {
2384        bcd_put_digit(&ret, BCD_NEG_PREF, 0);
2385    } else {
2386        bcd_put_digit(&ret, BCD_PLUS_PREF_1, 0);
2387    }
2388
2389    cr = bcd_cmp_zero(&ret);
2390
2391    if (unlikely(invalid)) {
2392        cr = CRF_SO;
2393    }
2394
2395    *r = ret;
2396
2397    return cr;
2398}
2399
2400uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2401{
2402    int i;
2403    int cr = 0;
2404    uint8_t digit = 0;
2405    int sgnb = bcd_get_sgn(b);
2406    int zone_lead = (ps) ? 0xF0 : 0x30;
2407    int invalid = (sgnb == 0);
2408    ppc_avr_t ret = { .u64 = { 0, 0 } };
2409
2410    int ox_flag = ((b->VsrD(0) >> 4) != 0);
2411
2412    for (i = 0; i < 16; i++) {
2413        digit = bcd_get_digit(b, i + 1, &invalid);
2414
2415        if (unlikely(invalid)) {
2416            break;
2417        }
2418
2419        ret.VsrB(BCD_DIG_BYTE(i * 2)) = zone_lead + digit;
2420    }
2421
2422    if (ps) {
2423        bcd_put_digit(&ret, (sgnb == 1) ? 0xC : 0xD, 1);
2424    } else {
2425        bcd_put_digit(&ret, (sgnb == 1) ? 0x3 : 0x7, 1);
2426    }
2427
2428    cr = bcd_cmp_zero(b);
2429
2430    if (ox_flag) {
2431        cr |= CRF_SO;
2432    }
2433
2434    if (unlikely(invalid)) {
2435        cr = CRF_SO;
2436    }
2437
2438    *r = ret;
2439
2440    return cr;
2441}
2442
2443uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2444{
2445    int i;
2446    int cr = 0;
2447    uint64_t lo_value;
2448    uint64_t hi_value;
2449    ppc_avr_t ret = { .u64 = { 0, 0 } };
2450
2451    if (b->VsrSD(0) < 0) {
2452        lo_value = -b->VsrSD(1);
2453        hi_value = ~b->VsrD(0) + !lo_value;
2454        bcd_put_digit(&ret, 0xD, 0);
2455    } else {
2456        lo_value = b->VsrD(1);
2457        hi_value = b->VsrD(0);
2458        bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0);
2459    }
2460
2461    if (divu128(&lo_value, &hi_value, 1000000000000000ULL) ||
2462            lo_value > 9999999999999999ULL) {
2463        cr = CRF_SO;
2464    }
2465
2466    for (i = 1; i < 16; hi_value /= 10, i++) {
2467        bcd_put_digit(&ret, hi_value % 10, i);
2468    }
2469
2470    for (; i < 32; lo_value /= 10, i++) {
2471        bcd_put_digit(&ret, lo_value % 10, i);
2472    }
2473
2474    cr |= bcd_cmp_zero(&ret);
2475
2476    *r = ret;
2477
2478    return cr;
2479}
2480
2481uint32_t helper_bcdctsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2482{
2483    uint8_t i;
2484    int cr;
2485    uint64_t carry;
2486    uint64_t unused;
2487    uint64_t lo_value;
2488    uint64_t hi_value = 0;
2489    int sgnb = bcd_get_sgn(b);
2490    int invalid = (sgnb == 0);
2491
2492    lo_value = bcd_get_digit(b, 31, &invalid);
2493    for (i = 30; i > 0; i--) {
2494        mulu64(&lo_value, &carry, lo_value, 10ULL);
2495        mulu64(&hi_value, &unused, hi_value, 10ULL);
2496        lo_value += bcd_get_digit(b, i, &invalid);
2497        hi_value += carry;
2498
2499        if (unlikely(invalid)) {
2500            break;
2501        }
2502    }
2503
2504    if (sgnb == -1) {
2505        r->VsrSD(1) = -lo_value;
2506        r->VsrSD(0) = ~hi_value + !r->VsrSD(1);
2507    } else {
2508        r->VsrSD(1) = lo_value;
2509        r->VsrSD(0) = hi_value;
2510    }
2511
2512    cr = bcd_cmp_zero(b);
2513
2514    if (unlikely(invalid)) {
2515        cr = CRF_SO;
2516    }
2517
2518    return cr;
2519}
2520
2521uint32_t helper_bcdcpsgn(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2522{
2523    int i;
2524    int invalid = 0;
2525
2526    if (bcd_get_sgn(a) == 0 || bcd_get_sgn(b) == 0) {
2527        return CRF_SO;
2528    }
2529
2530    *r = *a;
2531    bcd_put_digit(r, b->VsrB(BCD_DIG_BYTE(0)) & 0xF, 0);
2532
2533    for (i = 1; i < 32; i++) {
2534        bcd_get_digit(a, i, &invalid);
2535        bcd_get_digit(b, i, &invalid);
2536        if (unlikely(invalid)) {
2537            return CRF_SO;
2538        }
2539    }
2540
2541    return bcd_cmp_zero(r);
2542}
2543
2544uint32_t helper_bcdsetsgn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2545{
2546    int sgnb = bcd_get_sgn(b);
2547
2548    *r = *b;
2549    bcd_put_digit(r, bcd_preferred_sgn(sgnb, ps), 0);
2550
2551    if (bcd_is_valid(b) == false) {
2552        return CRF_SO;
2553    }
2554
2555    return bcd_cmp_zero(r);
2556}
2557
2558uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2559{
2560    int cr;
2561    int i = a->VsrSB(7);
2562    bool ox_flag = false;
2563    int sgnb = bcd_get_sgn(b);
2564    ppc_avr_t ret = *b;
2565    ret.VsrD(1) &= ~0xf;
2566
2567    if (bcd_is_valid(b) == false) {
2568        return CRF_SO;
2569    }
2570
2571    if (unlikely(i > 31)) {
2572        i = 31;
2573    } else if (unlikely(i < -31)) {
2574        i = -31;
2575    }
2576
2577    if (i > 0) {
2578        ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
2579    } else {
2580        urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
2581    }
2582    bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
2583
2584    *r = ret;
2585
2586    cr = bcd_cmp_zero(r);
2587    if (ox_flag) {
2588        cr |= CRF_SO;
2589    }
2590
2591    return cr;
2592}
2593
2594uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2595{
2596    int cr;
2597    int i;
2598    int invalid = 0;
2599    bool ox_flag = false;
2600    ppc_avr_t ret = *b;
2601
2602    for (i = 0; i < 32; i++) {
2603        bcd_get_digit(b, i, &invalid);
2604
2605        if (unlikely(invalid)) {
2606            return CRF_SO;
2607        }
2608    }
2609
2610    i = a->VsrSB(7);
2611    if (i >= 32) {
2612        ox_flag = true;
2613        ret.VsrD(1) = ret.VsrD(0) = 0;
2614    } else if (i <= -32) {
2615        ret.VsrD(1) = ret.VsrD(0) = 0;
2616    } else if (i > 0) {
2617        ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
2618    } else {
2619        urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
2620    }
2621    *r = ret;
2622
2623    cr = bcd_cmp_zero(r);
2624    if (ox_flag) {
2625        cr |= CRF_SO;
2626    }
2627
2628    return cr;
2629}
2630
2631uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2632{
2633    int cr;
2634    int unused = 0;
2635    int invalid = 0;
2636    bool ox_flag = false;
2637    int sgnb = bcd_get_sgn(b);
2638    ppc_avr_t ret = *b;
2639    ret.VsrD(1) &= ~0xf;
2640
2641    int i = a->VsrSB(7);
2642    ppc_avr_t bcd_one;
2643
2644    bcd_one.VsrD(0) = 0;
2645    bcd_one.VsrD(1) = 0x10;
2646
2647    if (bcd_is_valid(b) == false) {
2648        return CRF_SO;
2649    }
2650
2651    if (unlikely(i > 31)) {
2652        i = 31;
2653    } else if (unlikely(i < -31)) {
2654        i = -31;
2655    }
2656
2657    if (i > 0) {
2658        ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
2659    } else {
2660        urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
2661
2662        if (bcd_get_digit(&ret, 0, &invalid) >= 5) {
2663            bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused);
2664        }
2665    }
2666    bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
2667
2668    cr = bcd_cmp_zero(&ret);
2669    if (ox_flag) {
2670        cr |= CRF_SO;
2671    }
2672    *r = ret;
2673
2674    return cr;
2675}
2676
2677uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2678{
2679    uint64_t mask;
2680    uint32_t ox_flag = 0;
2681    int i = a->VsrSH(3) + 1;
2682    ppc_avr_t ret = *b;
2683
2684    if (bcd_is_valid(b) == false) {
2685        return CRF_SO;
2686    }
2687
2688    if (i > 16 && i < 32) {
2689        mask = (uint64_t)-1 >> (128 - i * 4);
2690        if (ret.VsrD(0) & ~mask) {
2691            ox_flag = CRF_SO;
2692        }
2693
2694        ret.VsrD(0) &= mask;
2695    } else if (i >= 0 && i <= 16) {
2696        mask = (uint64_t)-1 >> (64 - i * 4);
2697        if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) {
2698            ox_flag = CRF_SO;
2699        }
2700
2701        ret.VsrD(1) &= mask;
2702        ret.VsrD(0) = 0;
2703    }
2704    bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0);
2705    *r = ret;
2706
2707    return bcd_cmp_zero(&ret) | ox_flag;
2708}
2709
2710uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2711{
2712    int i;
2713    uint64_t mask;
2714    uint32_t ox_flag = 0;
2715    int invalid = 0;
2716    ppc_avr_t ret = *b;
2717
2718    for (i = 0; i < 32; i++) {
2719        bcd_get_digit(b, i, &invalid);
2720
2721        if (unlikely(invalid)) {
2722            return CRF_SO;
2723        }
2724    }
2725
2726    i = a->VsrSH(3);
2727    if (i > 16 && i < 33) {
2728        mask = (uint64_t)-1 >> (128 - i * 4);
2729        if (ret.VsrD(0) & ~mask) {
2730            ox_flag = CRF_SO;
2731        }
2732
2733        ret.VsrD(0) &= mask;
2734    } else if (i > 0 && i <= 16) {
2735        mask = (uint64_t)-1 >> (64 - i * 4);
2736        if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) {
2737            ox_flag = CRF_SO;
2738        }
2739
2740        ret.VsrD(1) &= mask;
2741        ret.VsrD(0) = 0;
2742    } else if (i == 0) {
2743        if (ret.VsrD(0) || ret.VsrD(1)) {
2744            ox_flag = CRF_SO;
2745        }
2746        ret.VsrD(0) = ret.VsrD(1) = 0;
2747    }
2748
2749    *r = ret;
2750    if (r->VsrD(0) == 0 && r->VsrD(1) == 0) {
2751        return ox_flag | CRF_EQ;
2752    }
2753
2754    return ox_flag | CRF_GT;
2755}
2756
2757void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
2758{
2759    int i;
2760    VECTOR_FOR_INORDER_I(i, u8) {
2761        r->u8[i] = AES_sbox[a->u8[i]];
2762    }
2763}
2764
2765void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2766{
2767    ppc_avr_t result;
2768    int i;
2769
2770    VECTOR_FOR_INORDER_I(i, u32) {
2771        result.VsrW(i) = b->VsrW(i) ^
2772            (AES_Te0[a->VsrB(AES_shifts[4 * i + 0])] ^
2773             AES_Te1[a->VsrB(AES_shifts[4 * i + 1])] ^
2774             AES_Te2[a->VsrB(AES_shifts[4 * i + 2])] ^
2775             AES_Te3[a->VsrB(AES_shifts[4 * i + 3])]);
2776    }
2777    *r = result;
2778}
2779
2780void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2781{
2782    ppc_avr_t result;
2783    int i;
2784
2785    VECTOR_FOR_INORDER_I(i, u8) {
2786        result.VsrB(i) = b->VsrB(i) ^ (AES_sbox[a->VsrB(AES_shifts[i])]);
2787    }
2788    *r = result;
2789}
2790
2791void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2792{
2793    /* This differs from what is written in ISA V2.07.  The RTL is */
2794    /* incorrect and will be fixed in V2.07B.                      */
2795    int i;
2796    ppc_avr_t tmp;
2797
2798    VECTOR_FOR_INORDER_I(i, u8) {
2799        tmp.VsrB(i) = b->VsrB(i) ^ AES_isbox[a->VsrB(AES_ishifts[i])];
2800    }
2801
2802    VECTOR_FOR_INORDER_I(i, u32) {
2803        r->VsrW(i) =
2804            AES_imc[tmp.VsrB(4 * i + 0)][0] ^
2805            AES_imc[tmp.VsrB(4 * i + 1)][1] ^
2806            AES_imc[tmp.VsrB(4 * i + 2)][2] ^
2807            AES_imc[tmp.VsrB(4 * i + 3)][3];
2808    }
2809}
2810
2811void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2812{
2813    ppc_avr_t result;
2814    int i;
2815
2816    VECTOR_FOR_INORDER_I(i, u8) {
2817        result.VsrB(i) = b->VsrB(i) ^ (AES_isbox[a->VsrB(AES_ishifts[i])]);
2818    }
2819    *r = result;
2820}
2821
2822void helper_vshasigmaw(ppc_avr_t *r,  ppc_avr_t *a, uint32_t st_six)
2823{
2824    int st = (st_six & 0x10) != 0;
2825    int six = st_six & 0xF;
2826    int i;
2827
2828    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2829        if (st == 0) {
2830            if ((six & (0x8 >> i)) == 0) {
2831                r->VsrW(i) = ror32(a->VsrW(i), 7) ^
2832                             ror32(a->VsrW(i), 18) ^
2833                             (a->VsrW(i) >> 3);
2834            } else { /* six.bit[i] == 1 */
2835                r->VsrW(i) = ror32(a->VsrW(i), 17) ^
2836                             ror32(a->VsrW(i), 19) ^
2837                             (a->VsrW(i) >> 10);
2838            }
2839        } else { /* st == 1 */
2840            if ((six & (0x8 >> i)) == 0) {
2841                r->VsrW(i) = ror32(a->VsrW(i), 2) ^
2842                             ror32(a->VsrW(i), 13) ^
2843                             ror32(a->VsrW(i), 22);
2844            } else { /* six.bit[i] == 1 */
2845                r->VsrW(i) = ror32(a->VsrW(i), 6) ^
2846                             ror32(a->VsrW(i), 11) ^
2847                             ror32(a->VsrW(i), 25);
2848            }
2849        }
2850    }
2851}
2852
2853void helper_vshasigmad(ppc_avr_t *r,  ppc_avr_t *a, uint32_t st_six)
2854{
2855    int st = (st_six & 0x10) != 0;
2856    int six = st_six & 0xF;
2857    int i;
2858
2859    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2860        if (st == 0) {
2861            if ((six & (0x8 >> (2 * i))) == 0) {
2862                r->VsrD(i) = ror64(a->VsrD(i), 1) ^
2863                             ror64(a->VsrD(i), 8) ^
2864                             (a->VsrD(i) >> 7);
2865            } else { /* six.bit[2*i] == 1 */
2866                r->VsrD(i) = ror64(a->VsrD(i), 19) ^
2867                             ror64(a->VsrD(i), 61) ^
2868                             (a->VsrD(i) >> 6);
2869            }
2870        } else { /* st == 1 */
2871            if ((six & (0x8 >> (2 * i))) == 0) {
2872                r->VsrD(i) = ror64(a->VsrD(i), 28) ^
2873                             ror64(a->VsrD(i), 34) ^
2874                             ror64(a->VsrD(i), 39);
2875            } else { /* six.bit[2*i] == 1 */
2876                r->VsrD(i) = ror64(a->VsrD(i), 14) ^
2877                             ror64(a->VsrD(i), 18) ^
2878                             ror64(a->VsrD(i), 41);
2879            }
2880        }
2881    }
2882}
2883
2884void helper_vpermxor(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2885{
2886    ppc_avr_t result;
2887    int i;
2888
2889    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2890        int indexA = c->VsrB(i) >> 4;
2891        int indexB = c->VsrB(i) & 0xF;
2892
2893        result.VsrB(i) = a->VsrB(indexA) ^ b->VsrB(indexB);
2894    }
2895    *r = result;
2896}
2897
2898#undef VECTOR_FOR_INORDER_I
2899
2900/*****************************************************************************/
2901/* SPE extension helpers */
2902/* Use a table to make this quicker */
2903static const uint8_t hbrev[16] = {
2904    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
2905    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
2906};
2907
2908static inline uint8_t byte_reverse(uint8_t val)
2909{
2910    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
2911}
2912
2913static inline uint32_t word_reverse(uint32_t val)
2914{
2915    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
2916        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
2917}
2918
2919#define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
2920target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
2921{
2922    uint32_t a, b, d, mask;
2923
2924    mask = UINT32_MAX >> (32 - MASKBITS);
2925    a = arg1 & mask;
2926    b = arg2 & mask;
2927    d = word_reverse(1 + word_reverse(a | ~b));
2928    return (arg1 & ~mask) | (d & b);
2929}
2930
2931uint32_t helper_cntlsw32(uint32_t val)
2932{
2933    if (val & 0x80000000) {
2934        return clz32(~val);
2935    } else {
2936        return clz32(val);
2937    }
2938}
2939
2940uint32_t helper_cntlzw32(uint32_t val)
2941{
2942    return clz32(val);
2943}
2944
2945/* 440 specific */
2946target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
2947                          target_ulong low, uint32_t update_Rc)
2948{
2949    target_ulong mask;
2950    int i;
2951
2952    i = 1;
2953    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
2954        if ((high & mask) == 0) {
2955            if (update_Rc) {
2956                env->crf[0] = 0x4;
2957            }
2958            goto done;
2959        }
2960        i++;
2961    }
2962    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
2963        if ((low & mask) == 0) {
2964            if (update_Rc) {
2965                env->crf[0] = 0x8;
2966            }
2967            goto done;
2968        }
2969        i++;
2970    }
2971    i = 8;
2972    if (update_Rc) {
2973        env->crf[0] = 0x2;
2974    }
2975 done:
2976    env->xer = (env->xer & ~0x7F) | i;
2977    if (update_Rc) {
2978        env->crf[0] |= xer_so;
2979    }
2980    return i;
2981}
2982