1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * PowerPC integer and vector emulation helpers for QEMU. 3fcf5ef2aSThomas Huth * 4fcf5ef2aSThomas Huth * Copyright (c) 2003-2007 Jocelyn Mayer 5fcf5ef2aSThomas Huth * 6fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 7fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 8fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 96bd039cdSChetan Pant * version 2.1 of the License, or (at your option) any later version. 10fcf5ef2aSThomas Huth * 11fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14fcf5ef2aSThomas Huth * Lesser General Public License for more details. 15fcf5ef2aSThomas Huth * 16fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 17fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18fcf5ef2aSThomas Huth */ 19db725815SMarkus Armbruster 20fcf5ef2aSThomas Huth #include "qemu/osdep.h" 21fcf5ef2aSThomas Huth #include "cpu.h" 22fcf5ef2aSThomas Huth #include "internal.h" 23fcf5ef2aSThomas Huth #include "qemu/host-utils.h" 24db725815SMarkus Armbruster #include "qemu/main-loop.h" 258a05fd9aSRichard Henderson #include "qemu/log.h" 26fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 27fcf5ef2aSThomas Huth #include "crypto/aes.h" 2824f91e81SAlex Bennée #include "fpu/softfloat.h" 293f74b632SRichard Henderson #include "qapi/error.h" 303f74b632SRichard Henderson #include "qemu/guest-random.h" 31fcf5ef2aSThomas Huth 32fcf5ef2aSThomas Huth #include "helper_regs.h" 33fcf5ef2aSThomas Huth /*****************************************************************************/ 34fcf5ef2aSThomas Huth /* Fixed point operations helpers */ 35fcf5ef2aSThomas Huth 36f32899deSNikunj A Dadhania static inline void helper_update_ov_legacy(CPUPPCState *env, int ov) 37f32899deSNikunj A Dadhania { 38f32899deSNikunj A Dadhania if (unlikely(ov)) { 39f32899deSNikunj A Dadhania env->so = env->ov = 1; 40f32899deSNikunj A Dadhania } else { 41f32899deSNikunj A Dadhania env->ov = 0; 42f32899deSNikunj A Dadhania } 43f32899deSNikunj A Dadhania } 44f32899deSNikunj A Dadhania 45fcf5ef2aSThomas Huth target_ulong helper_divweu(CPUPPCState *env, target_ulong ra, target_ulong rb, 46fcf5ef2aSThomas Huth uint32_t oe) 47fcf5ef2aSThomas Huth { 48fcf5ef2aSThomas Huth uint64_t rt = 0; 49fcf5ef2aSThomas Huth int overflow = 0; 50fcf5ef2aSThomas Huth 51fcf5ef2aSThomas Huth uint64_t dividend = (uint64_t)ra << 32; 52fcf5ef2aSThomas Huth uint64_t divisor = (uint32_t)rb; 53fcf5ef2aSThomas Huth 54fcf5ef2aSThomas Huth if (unlikely(divisor == 0)) { 55fcf5ef2aSThomas Huth overflow = 1; 56fcf5ef2aSThomas Huth } else { 57fcf5ef2aSThomas Huth rt = dividend / divisor; 58fcf5ef2aSThomas Huth overflow = rt > UINT32_MAX; 59fcf5ef2aSThomas Huth } 60fcf5ef2aSThomas Huth 61fcf5ef2aSThomas Huth if (unlikely(overflow)) { 62fcf5ef2aSThomas Huth rt = 0; /* Undefined */ 63fcf5ef2aSThomas Huth } 64fcf5ef2aSThomas Huth 65fcf5ef2aSThomas Huth if (oe) { 66f32899deSNikunj A Dadhania helper_update_ov_legacy(env, overflow); 67fcf5ef2aSThomas Huth } 68fcf5ef2aSThomas Huth 69fcf5ef2aSThomas Huth return (target_ulong)rt; 70fcf5ef2aSThomas Huth } 71fcf5ef2aSThomas Huth 72fcf5ef2aSThomas Huth target_ulong helper_divwe(CPUPPCState *env, target_ulong ra, target_ulong rb, 73fcf5ef2aSThomas Huth uint32_t oe) 74fcf5ef2aSThomas Huth { 75fcf5ef2aSThomas Huth int64_t rt = 0; 76fcf5ef2aSThomas Huth int overflow = 0; 77fcf5ef2aSThomas Huth 78fcf5ef2aSThomas Huth int64_t dividend = (int64_t)ra << 32; 79fcf5ef2aSThomas Huth int64_t divisor = (int64_t)((int32_t)rb); 80fcf5ef2aSThomas Huth 81fcf5ef2aSThomas Huth if (unlikely((divisor == 0) || 82fcf5ef2aSThomas Huth ((divisor == -1ull) && (dividend == INT64_MIN)))) { 83fcf5ef2aSThomas Huth overflow = 1; 84fcf5ef2aSThomas Huth } else { 85fcf5ef2aSThomas Huth rt = dividend / divisor; 86fcf5ef2aSThomas Huth overflow = rt != (int32_t)rt; 87fcf5ef2aSThomas Huth } 88fcf5ef2aSThomas Huth 89fcf5ef2aSThomas Huth if (unlikely(overflow)) { 90fcf5ef2aSThomas Huth rt = 0; /* Undefined */ 91fcf5ef2aSThomas Huth } 92fcf5ef2aSThomas Huth 93fcf5ef2aSThomas Huth if (oe) { 94f32899deSNikunj A Dadhania helper_update_ov_legacy(env, overflow); 95fcf5ef2aSThomas Huth } 96fcf5ef2aSThomas Huth 97fcf5ef2aSThomas Huth return (target_ulong)rt; 98fcf5ef2aSThomas Huth } 99fcf5ef2aSThomas Huth 100fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 101fcf5ef2aSThomas Huth 102fcf5ef2aSThomas Huth uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe) 103fcf5ef2aSThomas Huth { 104fcf5ef2aSThomas Huth uint64_t rt = 0; 105fcf5ef2aSThomas Huth int overflow = 0; 106fcf5ef2aSThomas Huth 1079276a31cSLuis Pires if (unlikely(rb == 0 || ra >= rb)) { 1089276a31cSLuis Pires overflow = 1; 109fcf5ef2aSThomas Huth rt = 0; /* Undefined */ 1109276a31cSLuis Pires } else { 1119276a31cSLuis Pires divu128(&rt, &ra, rb); 112fcf5ef2aSThomas Huth } 113fcf5ef2aSThomas Huth 114fcf5ef2aSThomas Huth if (oe) { 115f32899deSNikunj A Dadhania helper_update_ov_legacy(env, overflow); 116fcf5ef2aSThomas Huth } 117fcf5ef2aSThomas Huth 118fcf5ef2aSThomas Huth return rt; 119fcf5ef2aSThomas Huth } 120fcf5ef2aSThomas Huth 121fcf5ef2aSThomas Huth uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe) 122fcf5ef2aSThomas Huth { 123*40f3e79aSLuis Pires uint64_t rt = 0; 124fcf5ef2aSThomas Huth int64_t ra = (int64_t)rau; 125fcf5ef2aSThomas Huth int64_t rb = (int64_t)rbu; 1269276a31cSLuis Pires int overflow = 0; 127fcf5ef2aSThomas Huth 1289276a31cSLuis Pires if (unlikely(rb == 0 || uabs64(ra) >= uabs64(rb))) { 1299276a31cSLuis Pires overflow = 1; 130fcf5ef2aSThomas Huth rt = 0; /* Undefined */ 1319276a31cSLuis Pires } else { 1329276a31cSLuis Pires divs128(&rt, &ra, rb); 133fcf5ef2aSThomas Huth } 134fcf5ef2aSThomas Huth 135fcf5ef2aSThomas Huth if (oe) { 136f32899deSNikunj A Dadhania helper_update_ov_legacy(env, overflow); 137fcf5ef2aSThomas Huth } 138fcf5ef2aSThomas Huth 139fcf5ef2aSThomas Huth return rt; 140fcf5ef2aSThomas Huth } 141fcf5ef2aSThomas Huth 142fcf5ef2aSThomas Huth #endif 143fcf5ef2aSThomas Huth 144fcf5ef2aSThomas Huth 145fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 146fcf5ef2aSThomas Huth /* if x = 0xab, returns 0xababababababababa */ 147fcf5ef2aSThomas Huth #define pattern(x) (((x) & 0xff) * (~(target_ulong)0 / 0xff)) 148fcf5ef2aSThomas Huth 149b6cb41b2SDavid Gibson /* 150b6cb41b2SDavid Gibson * subtract 1 from each byte, and with inverse, check if MSB is set at each 151fcf5ef2aSThomas Huth * byte. 152fcf5ef2aSThomas Huth * i.e. ((0x00 - 0x01) & ~(0x00)) & 0x80 153fcf5ef2aSThomas Huth * (0xFF & 0xFF) & 0x80 = 0x80 (zero found) 154fcf5ef2aSThomas Huth */ 155fcf5ef2aSThomas Huth #define haszero(v) (((v) - pattern(0x01)) & ~(v) & pattern(0x80)) 156fcf5ef2aSThomas Huth 157fcf5ef2aSThomas Huth /* When you XOR the pattern and there is a match, that byte will be zero */ 158fcf5ef2aSThomas Huth #define hasvalue(x, n) (haszero((x) ^ pattern(n))) 159fcf5ef2aSThomas Huth 160fcf5ef2aSThomas Huth uint32_t helper_cmpeqb(target_ulong ra, target_ulong rb) 161fcf5ef2aSThomas Huth { 162efa73196SNikunj A Dadhania return hasvalue(rb, ra) ? CRF_GT : 0; 163fcf5ef2aSThomas Huth } 164fcf5ef2aSThomas Huth 165fcf5ef2aSThomas Huth #undef pattern 166fcf5ef2aSThomas Huth #undef haszero 167fcf5ef2aSThomas Huth #undef hasvalue 168fcf5ef2aSThomas Huth 169b6cb41b2SDavid Gibson /* 1703f74b632SRichard Henderson * Return a random number. 171fcf5ef2aSThomas Huth */ 1723f74b632SRichard Henderson uint64_t helper_darn32(void) 173fcf5ef2aSThomas Huth { 1743f74b632SRichard Henderson Error *err = NULL; 1753f74b632SRichard Henderson uint32_t ret; 1763f74b632SRichard Henderson 1773f74b632SRichard Henderson if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { 1783f74b632SRichard Henderson qemu_log_mask(LOG_UNIMP, "darn: Crypto failure: %s", 1793f74b632SRichard Henderson error_get_pretty(err)); 1803f74b632SRichard Henderson error_free(err); 181fcf5ef2aSThomas Huth return -1; 182fcf5ef2aSThomas Huth } 183fcf5ef2aSThomas Huth 1843f74b632SRichard Henderson return ret; 1853f74b632SRichard Henderson } 1863f74b632SRichard Henderson 1873f74b632SRichard Henderson uint64_t helper_darn64(void) 188fcf5ef2aSThomas Huth { 1893f74b632SRichard Henderson Error *err = NULL; 1903f74b632SRichard Henderson uint64_t ret; 1913f74b632SRichard Henderson 1923f74b632SRichard Henderson if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { 1933f74b632SRichard Henderson qemu_log_mask(LOG_UNIMP, "darn: Crypto failure: %s", 1943f74b632SRichard Henderson error_get_pretty(err)); 1953f74b632SRichard Henderson error_free(err); 196fcf5ef2aSThomas Huth return -1; 197fcf5ef2aSThomas Huth } 198fcf5ef2aSThomas Huth 1993f74b632SRichard Henderson return ret; 2003f74b632SRichard Henderson } 201fcf5ef2aSThomas Huth 202fcf5ef2aSThomas Huth uint64_t helper_bpermd(uint64_t rs, uint64_t rb) 203fcf5ef2aSThomas Huth { 204fcf5ef2aSThomas Huth int i; 205fcf5ef2aSThomas Huth uint64_t ra = 0; 206fcf5ef2aSThomas Huth 207fcf5ef2aSThomas Huth for (i = 0; i < 8; i++) { 208fcf5ef2aSThomas Huth int index = (rs >> (i * 8)) & 0xFF; 209fcf5ef2aSThomas Huth if (index < 64) { 210a6a444a8SCédric Le Goater if (rb & PPC_BIT(index)) { 211fcf5ef2aSThomas Huth ra |= 1 << i; 212fcf5ef2aSThomas Huth } 213fcf5ef2aSThomas Huth } 214fcf5ef2aSThomas Huth } 215fcf5ef2aSThomas Huth return ra; 216fcf5ef2aSThomas Huth } 217fcf5ef2aSThomas Huth 218fcf5ef2aSThomas Huth #endif 219fcf5ef2aSThomas Huth 220fcf5ef2aSThomas Huth target_ulong helper_cmpb(target_ulong rs, target_ulong rb) 221fcf5ef2aSThomas Huth { 222fcf5ef2aSThomas Huth target_ulong mask = 0xff; 223fcf5ef2aSThomas Huth target_ulong ra = 0; 224fcf5ef2aSThomas Huth int i; 225fcf5ef2aSThomas Huth 226fcf5ef2aSThomas Huth for (i = 0; i < sizeof(target_ulong); i++) { 227fcf5ef2aSThomas Huth if ((rs & mask) == (rb & mask)) { 228fcf5ef2aSThomas Huth ra |= mask; 229fcf5ef2aSThomas Huth } 230fcf5ef2aSThomas Huth mask <<= 8; 231fcf5ef2aSThomas Huth } 232fcf5ef2aSThomas Huth return ra; 233fcf5ef2aSThomas Huth } 234fcf5ef2aSThomas Huth 235fcf5ef2aSThomas Huth /* shift right arithmetic helper */ 236fcf5ef2aSThomas Huth target_ulong helper_sraw(CPUPPCState *env, target_ulong value, 237fcf5ef2aSThomas Huth target_ulong shift) 238fcf5ef2aSThomas Huth { 239fcf5ef2aSThomas Huth int32_t ret; 240fcf5ef2aSThomas Huth 241fcf5ef2aSThomas Huth if (likely(!(shift & 0x20))) { 242fcf5ef2aSThomas Huth if (likely((uint32_t)shift != 0)) { 243fcf5ef2aSThomas Huth shift &= 0x1f; 244fcf5ef2aSThomas Huth ret = (int32_t)value >> shift; 245fcf5ef2aSThomas Huth if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) { 246af1c259fSSandipan Das env->ca32 = env->ca = 0; 247fcf5ef2aSThomas Huth } else { 248af1c259fSSandipan Das env->ca32 = env->ca = 1; 249fcf5ef2aSThomas Huth } 250fcf5ef2aSThomas Huth } else { 251fcf5ef2aSThomas Huth ret = (int32_t)value; 252af1c259fSSandipan Das env->ca32 = env->ca = 0; 253fcf5ef2aSThomas Huth } 254fcf5ef2aSThomas Huth } else { 255fcf5ef2aSThomas Huth ret = (int32_t)value >> 31; 256af1c259fSSandipan Das env->ca32 = env->ca = (ret != 0); 257fcf5ef2aSThomas Huth } 258fcf5ef2aSThomas Huth return (target_long)ret; 259fcf5ef2aSThomas Huth } 260fcf5ef2aSThomas Huth 261fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 262fcf5ef2aSThomas Huth target_ulong helper_srad(CPUPPCState *env, target_ulong value, 263fcf5ef2aSThomas Huth target_ulong shift) 264fcf5ef2aSThomas Huth { 265fcf5ef2aSThomas Huth int64_t ret; 266fcf5ef2aSThomas Huth 267fcf5ef2aSThomas Huth if (likely(!(shift & 0x40))) { 268fcf5ef2aSThomas Huth if (likely((uint64_t)shift != 0)) { 269fcf5ef2aSThomas Huth shift &= 0x3f; 270fcf5ef2aSThomas Huth ret = (int64_t)value >> shift; 271fcf5ef2aSThomas Huth if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) { 272af1c259fSSandipan Das env->ca32 = env->ca = 0; 273fcf5ef2aSThomas Huth } else { 274af1c259fSSandipan Das env->ca32 = env->ca = 1; 275fcf5ef2aSThomas Huth } 276fcf5ef2aSThomas Huth } else { 277fcf5ef2aSThomas Huth ret = (int64_t)value; 278af1c259fSSandipan Das env->ca32 = env->ca = 0; 279fcf5ef2aSThomas Huth } 280fcf5ef2aSThomas Huth } else { 281fcf5ef2aSThomas Huth ret = (int64_t)value >> 63; 282af1c259fSSandipan Das env->ca32 = env->ca = (ret != 0); 283fcf5ef2aSThomas Huth } 284fcf5ef2aSThomas Huth return ret; 285fcf5ef2aSThomas Huth } 286fcf5ef2aSThomas Huth #endif 287fcf5ef2aSThomas Huth 288fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 289fcf5ef2aSThomas Huth target_ulong helper_popcntb(target_ulong val) 290fcf5ef2aSThomas Huth { 29179770002SRichard Henderson /* Note that we don't fold past bytes */ 292fcf5ef2aSThomas Huth val = (val & 0x5555555555555555ULL) + ((val >> 1) & 293fcf5ef2aSThomas Huth 0x5555555555555555ULL); 294fcf5ef2aSThomas Huth val = (val & 0x3333333333333333ULL) + ((val >> 2) & 295fcf5ef2aSThomas Huth 0x3333333333333333ULL); 296fcf5ef2aSThomas Huth val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 297fcf5ef2aSThomas Huth 0x0f0f0f0f0f0f0f0fULL); 298fcf5ef2aSThomas Huth return val; 299fcf5ef2aSThomas Huth } 300fcf5ef2aSThomas Huth 301fcf5ef2aSThomas Huth target_ulong helper_popcntw(target_ulong val) 302fcf5ef2aSThomas Huth { 30379770002SRichard Henderson /* Note that we don't fold past words. */ 304fcf5ef2aSThomas Huth val = (val & 0x5555555555555555ULL) + ((val >> 1) & 305fcf5ef2aSThomas Huth 0x5555555555555555ULL); 306fcf5ef2aSThomas Huth val = (val & 0x3333333333333333ULL) + ((val >> 2) & 307fcf5ef2aSThomas Huth 0x3333333333333333ULL); 308fcf5ef2aSThomas Huth val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 309fcf5ef2aSThomas Huth 0x0f0f0f0f0f0f0f0fULL); 310fcf5ef2aSThomas Huth val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 311fcf5ef2aSThomas Huth 0x00ff00ff00ff00ffULL); 312fcf5ef2aSThomas Huth val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 313fcf5ef2aSThomas Huth 0x0000ffff0000ffffULL); 314fcf5ef2aSThomas Huth return val; 315fcf5ef2aSThomas Huth } 316fcf5ef2aSThomas Huth #else 317fcf5ef2aSThomas Huth target_ulong helper_popcntb(target_ulong val) 318fcf5ef2aSThomas Huth { 31979770002SRichard Henderson /* Note that we don't fold past bytes */ 320fcf5ef2aSThomas Huth val = (val & 0x55555555) + ((val >> 1) & 0x55555555); 321fcf5ef2aSThomas Huth val = (val & 0x33333333) + ((val >> 2) & 0x33333333); 322fcf5ef2aSThomas Huth val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f); 323fcf5ef2aSThomas Huth return val; 324fcf5ef2aSThomas Huth } 325fcf5ef2aSThomas Huth #endif 326fcf5ef2aSThomas Huth 32789ccd7dcSMatheus Ferst uint64_t helper_cfuged(uint64_t src, uint64_t mask) 32889ccd7dcSMatheus Ferst { 32989ccd7dcSMatheus Ferst /* 33089ccd7dcSMatheus Ferst * Instead of processing the mask bit-by-bit from the most significant to 33189ccd7dcSMatheus Ferst * the least significant bit, as described in PowerISA, we'll handle it in 33289ccd7dcSMatheus Ferst * blocks of 'n' zeros/ones from LSB to MSB. To avoid the decision to use 33389ccd7dcSMatheus Ferst * ctz or cto, we negate the mask at the end of the loop. 33489ccd7dcSMatheus Ferst */ 33589ccd7dcSMatheus Ferst target_ulong m, left = 0, right = 0; 33689ccd7dcSMatheus Ferst unsigned int n, i = 64; 33789ccd7dcSMatheus Ferst bool bit = false; /* tracks if we are processing zeros or ones */ 33889ccd7dcSMatheus Ferst 33989ccd7dcSMatheus Ferst if (mask == 0 || mask == -1) { 34089ccd7dcSMatheus Ferst return src; 34189ccd7dcSMatheus Ferst } 34289ccd7dcSMatheus Ferst 34389ccd7dcSMatheus Ferst /* Processes the mask in blocks, from LSB to MSB */ 34489ccd7dcSMatheus Ferst while (i) { 34589ccd7dcSMatheus Ferst /* Find how many bits we should take */ 34689ccd7dcSMatheus Ferst n = ctz64(mask); 34789ccd7dcSMatheus Ferst if (n > i) { 34889ccd7dcSMatheus Ferst n = i; 34989ccd7dcSMatheus Ferst } 35089ccd7dcSMatheus Ferst 35189ccd7dcSMatheus Ferst /* 35289ccd7dcSMatheus Ferst * Extracts 'n' trailing bits of src and put them on the leading 'n' 35389ccd7dcSMatheus Ferst * bits of 'right' or 'left', pushing down the previously extracted 35489ccd7dcSMatheus Ferst * values. 35589ccd7dcSMatheus Ferst */ 35689ccd7dcSMatheus Ferst m = (1ll << n) - 1; 35789ccd7dcSMatheus Ferst if (bit) { 35889ccd7dcSMatheus Ferst right = ror64(right | (src & m), n); 35989ccd7dcSMatheus Ferst } else { 36089ccd7dcSMatheus Ferst left = ror64(left | (src & m), n); 36189ccd7dcSMatheus Ferst } 36289ccd7dcSMatheus Ferst 36389ccd7dcSMatheus Ferst /* 36489ccd7dcSMatheus Ferst * Discards the processed bits from 'src' and 'mask'. Note that we are 36589ccd7dcSMatheus Ferst * removing 'n' trailing zeros from 'mask', but the logical shift will 36689ccd7dcSMatheus Ferst * add 'n' leading zeros back, so the population count of 'mask' is kept 36789ccd7dcSMatheus Ferst * the same. 36889ccd7dcSMatheus Ferst */ 36989ccd7dcSMatheus Ferst src >>= n; 37089ccd7dcSMatheus Ferst mask >>= n; 37189ccd7dcSMatheus Ferst i -= n; 37289ccd7dcSMatheus Ferst bit = !bit; 37389ccd7dcSMatheus Ferst mask = ~mask; 37489ccd7dcSMatheus Ferst } 37589ccd7dcSMatheus Ferst 37689ccd7dcSMatheus Ferst /* 37789ccd7dcSMatheus Ferst * At the end, right was ror'ed ctpop(mask) times. To put it back in place, 37889ccd7dcSMatheus Ferst * we'll shift it more 64-ctpop(mask) times. 37989ccd7dcSMatheus Ferst */ 38089ccd7dcSMatheus Ferst if (bit) { 38189ccd7dcSMatheus Ferst n = ctpop64(mask); 38289ccd7dcSMatheus Ferst } else { 38389ccd7dcSMatheus Ferst n = 64 - ctpop64(mask); 38489ccd7dcSMatheus Ferst } 38589ccd7dcSMatheus Ferst 38689ccd7dcSMatheus Ferst return left | (right >> n); 38789ccd7dcSMatheus Ferst } 38889ccd7dcSMatheus Ferst 389fcf5ef2aSThomas Huth /*****************************************************************************/ 390fcf5ef2aSThomas Huth /* PowerPC 601 specific instructions (POWER bridge) */ 391fcf5ef2aSThomas Huth target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2) 392fcf5ef2aSThomas Huth { 393fcf5ef2aSThomas Huth uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ]; 394fcf5ef2aSThomas Huth 395fcf5ef2aSThomas Huth if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || 396fcf5ef2aSThomas Huth (int32_t)arg2 == 0) { 397fcf5ef2aSThomas Huth env->spr[SPR_MQ] = 0; 398fcf5ef2aSThomas Huth return INT32_MIN; 399fcf5ef2aSThomas Huth } else { 400fcf5ef2aSThomas Huth env->spr[SPR_MQ] = tmp % arg2; 401fcf5ef2aSThomas Huth return tmp / (int32_t)arg2; 402fcf5ef2aSThomas Huth } 403fcf5ef2aSThomas Huth } 404fcf5ef2aSThomas Huth 405fcf5ef2aSThomas Huth target_ulong helper_divo(CPUPPCState *env, target_ulong arg1, 406fcf5ef2aSThomas Huth target_ulong arg2) 407fcf5ef2aSThomas Huth { 408fcf5ef2aSThomas Huth uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ]; 409fcf5ef2aSThomas Huth 410fcf5ef2aSThomas Huth if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || 411fcf5ef2aSThomas Huth (int32_t)arg2 == 0) { 412fcf5ef2aSThomas Huth env->so = env->ov = 1; 413fcf5ef2aSThomas Huth env->spr[SPR_MQ] = 0; 414fcf5ef2aSThomas Huth return INT32_MIN; 415fcf5ef2aSThomas Huth } else { 416fcf5ef2aSThomas Huth env->spr[SPR_MQ] = tmp % arg2; 417fcf5ef2aSThomas Huth tmp /= (int32_t)arg2; 418fcf5ef2aSThomas Huth if ((int32_t)tmp != tmp) { 419fcf5ef2aSThomas Huth env->so = env->ov = 1; 420fcf5ef2aSThomas Huth } else { 421fcf5ef2aSThomas Huth env->ov = 0; 422fcf5ef2aSThomas Huth } 423fcf5ef2aSThomas Huth return tmp; 424fcf5ef2aSThomas Huth } 425fcf5ef2aSThomas Huth } 426fcf5ef2aSThomas Huth 427fcf5ef2aSThomas Huth target_ulong helper_divs(CPUPPCState *env, target_ulong arg1, 428fcf5ef2aSThomas Huth target_ulong arg2) 429fcf5ef2aSThomas Huth { 430fcf5ef2aSThomas Huth if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || 431fcf5ef2aSThomas Huth (int32_t)arg2 == 0) { 432fcf5ef2aSThomas Huth env->spr[SPR_MQ] = 0; 433fcf5ef2aSThomas Huth return INT32_MIN; 434fcf5ef2aSThomas Huth } else { 435fcf5ef2aSThomas Huth env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2; 436fcf5ef2aSThomas Huth return (int32_t)arg1 / (int32_t)arg2; 437fcf5ef2aSThomas Huth } 438fcf5ef2aSThomas Huth } 439fcf5ef2aSThomas Huth 440fcf5ef2aSThomas Huth target_ulong helper_divso(CPUPPCState *env, target_ulong arg1, 441fcf5ef2aSThomas Huth target_ulong arg2) 442fcf5ef2aSThomas Huth { 443fcf5ef2aSThomas Huth if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || 444fcf5ef2aSThomas Huth (int32_t)arg2 == 0) { 445fcf5ef2aSThomas Huth env->so = env->ov = 1; 446fcf5ef2aSThomas Huth env->spr[SPR_MQ] = 0; 447fcf5ef2aSThomas Huth return INT32_MIN; 448fcf5ef2aSThomas Huth } else { 449fcf5ef2aSThomas Huth env->ov = 0; 450fcf5ef2aSThomas Huth env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2; 451fcf5ef2aSThomas Huth return (int32_t)arg1 / (int32_t)arg2; 452fcf5ef2aSThomas Huth } 453fcf5ef2aSThomas Huth } 454fcf5ef2aSThomas Huth 455fcf5ef2aSThomas Huth /*****************************************************************************/ 456fcf5ef2aSThomas Huth /* 602 specific instructions */ 457fcf5ef2aSThomas Huth /* mfrom is the most crazy instruction ever seen, imho ! */ 458fcf5ef2aSThomas Huth /* Real implementation uses a ROM table. Do the same */ 459b6cb41b2SDavid Gibson /* 460b6cb41b2SDavid Gibson * Extremely decomposed: 461fcf5ef2aSThomas Huth * -arg / 256 462fcf5ef2aSThomas Huth * return 256 * log10(10 + 1.0) + 0.5 463fcf5ef2aSThomas Huth */ 464fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 465fcf5ef2aSThomas Huth target_ulong helper_602_mfrom(target_ulong arg) 466fcf5ef2aSThomas Huth { 467fcf5ef2aSThomas Huth if (likely(arg < 602)) { 468139c1837SPaolo Bonzini #include "mfrom_table.c.inc" 469fcf5ef2aSThomas Huth return mfrom_ROM_table[arg]; 470fcf5ef2aSThomas Huth } else { 471fcf5ef2aSThomas Huth return 0; 472fcf5ef2aSThomas Huth } 473fcf5ef2aSThomas Huth } 474fcf5ef2aSThomas Huth #endif 475fcf5ef2aSThomas Huth 476fcf5ef2aSThomas Huth /*****************************************************************************/ 477fcf5ef2aSThomas Huth /* Altivec extension helpers */ 478fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 479fcf5ef2aSThomas Huth #define VECTOR_FOR_INORDER_I(index, element) \ 480fcf5ef2aSThomas Huth for (index = 0; index < ARRAY_SIZE(r->element); index++) 481fcf5ef2aSThomas Huth #else 482fcf5ef2aSThomas Huth #define VECTOR_FOR_INORDER_I(index, element) \ 483fcf5ef2aSThomas Huth for (index = ARRAY_SIZE(r->element) - 1; index >= 0; index--) 484fcf5ef2aSThomas Huth #endif 485fcf5ef2aSThomas Huth 486fcf5ef2aSThomas Huth /* Saturating arithmetic helpers. */ 487fcf5ef2aSThomas Huth #define SATCVT(from, to, from_type, to_type, min, max) \ 488fcf5ef2aSThomas Huth static inline to_type cvt##from##to(from_type x, int *sat) \ 489fcf5ef2aSThomas Huth { \ 490fcf5ef2aSThomas Huth to_type r; \ 491fcf5ef2aSThomas Huth \ 492fcf5ef2aSThomas Huth if (x < (from_type)min) { \ 493fcf5ef2aSThomas Huth r = min; \ 494fcf5ef2aSThomas Huth *sat = 1; \ 495fcf5ef2aSThomas Huth } else if (x > (from_type)max) { \ 496fcf5ef2aSThomas Huth r = max; \ 497fcf5ef2aSThomas Huth *sat = 1; \ 498fcf5ef2aSThomas Huth } else { \ 499fcf5ef2aSThomas Huth r = x; \ 500fcf5ef2aSThomas Huth } \ 501fcf5ef2aSThomas Huth return r; \ 502fcf5ef2aSThomas Huth } 503fcf5ef2aSThomas Huth #define SATCVTU(from, to, from_type, to_type, min, max) \ 504fcf5ef2aSThomas Huth static inline to_type cvt##from##to(from_type x, int *sat) \ 505fcf5ef2aSThomas Huth { \ 506fcf5ef2aSThomas Huth to_type r; \ 507fcf5ef2aSThomas Huth \ 508fcf5ef2aSThomas Huth if (x > (from_type)max) { \ 509fcf5ef2aSThomas Huth r = max; \ 510fcf5ef2aSThomas Huth *sat = 1; \ 511fcf5ef2aSThomas Huth } else { \ 512fcf5ef2aSThomas Huth r = x; \ 513fcf5ef2aSThomas Huth } \ 514fcf5ef2aSThomas Huth return r; \ 515fcf5ef2aSThomas Huth } 516fcf5ef2aSThomas Huth SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX) 517fcf5ef2aSThomas Huth SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX) 518fcf5ef2aSThomas Huth SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX) 519fcf5ef2aSThomas Huth 520fcf5ef2aSThomas Huth SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX) 521fcf5ef2aSThomas Huth SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX) 522fcf5ef2aSThomas Huth SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX) 523fcf5ef2aSThomas Huth SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX) 524fcf5ef2aSThomas Huth SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX) 525fcf5ef2aSThomas Huth SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX) 526fcf5ef2aSThomas Huth #undef SATCVT 527fcf5ef2aSThomas Huth #undef SATCVTU 528fcf5ef2aSThomas Huth 529dedfaac7SRichard Henderson void helper_mtvscr(CPUPPCState *env, uint32_t vscr) 530fcf5ef2aSThomas Huth { 531c19940dbSBruno Larsen (billionai) ppc_store_vscr(env, vscr); 532fcf5ef2aSThomas Huth } 533fcf5ef2aSThomas Huth 534cc2b90d7SRichard Henderson uint32_t helper_mfvscr(CPUPPCState *env) 535cc2b90d7SRichard Henderson { 536c19940dbSBruno Larsen (billionai) return ppc_get_vscr(env); 537cc2b90d7SRichard Henderson } 538cc2b90d7SRichard Henderson 5396175f5a0SRichard Henderson static inline void set_vscr_sat(CPUPPCState *env) 5406175f5a0SRichard Henderson { 5419b5b74daSRichard Henderson /* The choice of non-zero value is arbitrary. */ 5429b5b74daSRichard Henderson env->vscr_sat.u32[0] = 1; 5436175f5a0SRichard Henderson } 5446175f5a0SRichard Henderson 545fcf5ef2aSThomas Huth void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 546fcf5ef2aSThomas Huth { 547fcf5ef2aSThomas Huth int i; 548fcf5ef2aSThomas Huth 549fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u32); i++) { 550fcf5ef2aSThomas Huth r->u32[i] = ~a->u32[i] < b->u32[i]; 551fcf5ef2aSThomas Huth } 552fcf5ef2aSThomas Huth } 553fcf5ef2aSThomas Huth 554fcf5ef2aSThomas Huth /* vprtybw */ 555fcf5ef2aSThomas Huth void helper_vprtybw(ppc_avr_t *r, ppc_avr_t *b) 556fcf5ef2aSThomas Huth { 557fcf5ef2aSThomas Huth int i; 558fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u32); i++) { 559fcf5ef2aSThomas Huth uint64_t res = b->u32[i] ^ (b->u32[i] >> 16); 560fcf5ef2aSThomas Huth res ^= res >> 8; 561fcf5ef2aSThomas Huth r->u32[i] = res & 1; 562fcf5ef2aSThomas Huth } 563fcf5ef2aSThomas Huth } 564fcf5ef2aSThomas Huth 565fcf5ef2aSThomas Huth /* vprtybd */ 566fcf5ef2aSThomas Huth void helper_vprtybd(ppc_avr_t *r, ppc_avr_t *b) 567fcf5ef2aSThomas Huth { 568fcf5ef2aSThomas Huth int i; 569fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u64); i++) { 570fcf5ef2aSThomas Huth uint64_t res = b->u64[i] ^ (b->u64[i] >> 32); 571fcf5ef2aSThomas Huth res ^= res >> 16; 572fcf5ef2aSThomas Huth res ^= res >> 8; 573fcf5ef2aSThomas Huth r->u64[i] = res & 1; 574fcf5ef2aSThomas Huth } 575fcf5ef2aSThomas Huth } 576fcf5ef2aSThomas Huth 577fcf5ef2aSThomas Huth /* vprtybq */ 578fcf5ef2aSThomas Huth void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b) 579fcf5ef2aSThomas Huth { 580fcf5ef2aSThomas Huth uint64_t res = b->u64[0] ^ b->u64[1]; 581fcf5ef2aSThomas Huth res ^= res >> 32; 582fcf5ef2aSThomas Huth res ^= res >> 16; 583fcf5ef2aSThomas Huth res ^= res >> 8; 5843c385a93SMark Cave-Ayland r->VsrD(1) = res & 1; 5853c385a93SMark Cave-Ayland r->VsrD(0) = 0; 586fcf5ef2aSThomas Huth } 587fcf5ef2aSThomas Huth 588fcf5ef2aSThomas Huth #define VARITHFP(suffix, func) \ 589fcf5ef2aSThomas Huth void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \ 590fcf5ef2aSThomas Huth ppc_avr_t *b) \ 591fcf5ef2aSThomas Huth { \ 592fcf5ef2aSThomas Huth int i; \ 593fcf5ef2aSThomas Huth \ 59405ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ 59505ee3e8aSMark Cave-Ayland r->f32[i] = func(a->f32[i], b->f32[i], &env->vec_status); \ 596fcf5ef2aSThomas Huth } \ 597fcf5ef2aSThomas Huth } 598fcf5ef2aSThomas Huth VARITHFP(addfp, float32_add) 599fcf5ef2aSThomas Huth VARITHFP(subfp, float32_sub) 600fcf5ef2aSThomas Huth VARITHFP(minfp, float32_min) 601fcf5ef2aSThomas Huth VARITHFP(maxfp, float32_max) 602fcf5ef2aSThomas Huth #undef VARITHFP 603fcf5ef2aSThomas Huth 604fcf5ef2aSThomas Huth #define VARITHFPFMA(suffix, type) \ 605fcf5ef2aSThomas Huth void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \ 606fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) \ 607fcf5ef2aSThomas Huth { \ 608fcf5ef2aSThomas Huth int i; \ 60905ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ 61005ee3e8aSMark Cave-Ayland r->f32[i] = float32_muladd(a->f32[i], c->f32[i], b->f32[i], \ 611fcf5ef2aSThomas Huth type, &env->vec_status); \ 612fcf5ef2aSThomas Huth } \ 613fcf5ef2aSThomas Huth } 614fcf5ef2aSThomas Huth VARITHFPFMA(maddfp, 0); 615fcf5ef2aSThomas Huth VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c); 616fcf5ef2aSThomas Huth #undef VARITHFPFMA 617fcf5ef2aSThomas Huth 618fcf5ef2aSThomas Huth #define VARITHSAT_CASE(type, op, cvt, element) \ 619fcf5ef2aSThomas Huth { \ 620fcf5ef2aSThomas Huth type result = (type)a->element[i] op (type)b->element[i]; \ 621fcf5ef2aSThomas Huth r->element[i] = cvt(result, &sat); \ 622fcf5ef2aSThomas Huth } 623fcf5ef2aSThomas Huth 624fcf5ef2aSThomas Huth #define VARITHSAT_DO(name, op, optype, cvt, element) \ 625fb11ae7dSRichard Henderson void helper_v##name(ppc_avr_t *r, ppc_avr_t *vscr_sat, \ 626fb11ae7dSRichard Henderson ppc_avr_t *a, ppc_avr_t *b, uint32_t desc) \ 627fcf5ef2aSThomas Huth { \ 628fcf5ef2aSThomas Huth int sat = 0; \ 629fcf5ef2aSThomas Huth int i; \ 630fcf5ef2aSThomas Huth \ 631fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 632fcf5ef2aSThomas Huth VARITHSAT_CASE(optype, op, cvt, element); \ 633fcf5ef2aSThomas Huth } \ 634fcf5ef2aSThomas Huth if (sat) { \ 635fb11ae7dSRichard Henderson vscr_sat->u32[0] = 1; \ 636fcf5ef2aSThomas Huth } \ 637fcf5ef2aSThomas Huth } 638fcf5ef2aSThomas Huth #define VARITHSAT_SIGNED(suffix, element, optype, cvt) \ 639fcf5ef2aSThomas Huth VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \ 640fcf5ef2aSThomas Huth VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element) 641fcf5ef2aSThomas Huth #define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \ 642fcf5ef2aSThomas Huth VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \ 643fcf5ef2aSThomas Huth VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element) 644fcf5ef2aSThomas Huth VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb) 645fcf5ef2aSThomas Huth VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh) 646fcf5ef2aSThomas Huth VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw) 647fcf5ef2aSThomas Huth VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub) 648fcf5ef2aSThomas Huth VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh) 649fcf5ef2aSThomas Huth VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw) 650fcf5ef2aSThomas Huth #undef VARITHSAT_CASE 651fcf5ef2aSThomas Huth #undef VARITHSAT_DO 652fcf5ef2aSThomas Huth #undef VARITHSAT_SIGNED 653fcf5ef2aSThomas Huth #undef VARITHSAT_UNSIGNED 654fcf5ef2aSThomas Huth 655fcf5ef2aSThomas Huth #define VAVG_DO(name, element, etype) \ 656fcf5ef2aSThomas Huth void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 657fcf5ef2aSThomas Huth { \ 658fcf5ef2aSThomas Huth int i; \ 659fcf5ef2aSThomas Huth \ 660fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 661fcf5ef2aSThomas Huth etype x = (etype)a->element[i] + (etype)b->element[i] + 1; \ 662fcf5ef2aSThomas Huth r->element[i] = x >> 1; \ 663fcf5ef2aSThomas Huth } \ 664fcf5ef2aSThomas Huth } 665fcf5ef2aSThomas Huth 666fcf5ef2aSThomas Huth #define VAVG(type, signed_element, signed_type, unsigned_element, \ 667fcf5ef2aSThomas Huth unsigned_type) \ 668fcf5ef2aSThomas Huth VAVG_DO(avgs##type, signed_element, signed_type) \ 669fcf5ef2aSThomas Huth VAVG_DO(avgu##type, unsigned_element, unsigned_type) 670fcf5ef2aSThomas Huth VAVG(b, s8, int16_t, u8, uint16_t) 671fcf5ef2aSThomas Huth VAVG(h, s16, int32_t, u16, uint32_t) 672fcf5ef2aSThomas Huth VAVG(w, s32, int64_t, u32, uint64_t) 673fcf5ef2aSThomas Huth #undef VAVG_DO 674fcf5ef2aSThomas Huth #undef VAVG 675fcf5ef2aSThomas Huth 676fcf5ef2aSThomas Huth #define VABSDU_DO(name, element) \ 677fcf5ef2aSThomas Huth void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 678fcf5ef2aSThomas Huth { \ 679fcf5ef2aSThomas Huth int i; \ 680fcf5ef2aSThomas Huth \ 681fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 682fcf5ef2aSThomas Huth r->element[i] = (a->element[i] > b->element[i]) ? \ 683fcf5ef2aSThomas Huth (a->element[i] - b->element[i]) : \ 684fcf5ef2aSThomas Huth (b->element[i] - a->element[i]); \ 685fcf5ef2aSThomas Huth } \ 686fcf5ef2aSThomas Huth } 687fcf5ef2aSThomas Huth 688b6cb41b2SDavid Gibson /* 689b6cb41b2SDavid Gibson * VABSDU - Vector absolute difference unsigned 690fcf5ef2aSThomas Huth * name - instruction mnemonic suffix (b: byte, h: halfword, w: word) 691fcf5ef2aSThomas Huth * element - element type to access from vector 692fcf5ef2aSThomas Huth */ 693fcf5ef2aSThomas Huth #define VABSDU(type, element) \ 694fcf5ef2aSThomas Huth VABSDU_DO(absdu##type, element) 695fcf5ef2aSThomas Huth VABSDU(b, u8) 696fcf5ef2aSThomas Huth VABSDU(h, u16) 697fcf5ef2aSThomas Huth VABSDU(w, u32) 698fcf5ef2aSThomas Huth #undef VABSDU_DO 699fcf5ef2aSThomas Huth #undef VABSDU 700fcf5ef2aSThomas Huth 701fcf5ef2aSThomas Huth #define VCF(suffix, cvt, element) \ 702fcf5ef2aSThomas Huth void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r, \ 703fcf5ef2aSThomas Huth ppc_avr_t *b, uint32_t uim) \ 704fcf5ef2aSThomas Huth { \ 705fcf5ef2aSThomas Huth int i; \ 706fcf5ef2aSThomas Huth \ 70705ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ 708fcf5ef2aSThomas Huth float32 t = cvt(b->element[i], &env->vec_status); \ 70905ee3e8aSMark Cave-Ayland r->f32[i] = float32_scalbn(t, -uim, &env->vec_status); \ 710fcf5ef2aSThomas Huth } \ 711fcf5ef2aSThomas Huth } 712fcf5ef2aSThomas Huth VCF(ux, uint32_to_float32, u32) 713fcf5ef2aSThomas Huth VCF(sx, int32_to_float32, s32) 714fcf5ef2aSThomas Huth #undef VCF 715fcf5ef2aSThomas Huth 716fcf5ef2aSThomas Huth #define VCMP_DO(suffix, compare, element, record) \ 717fcf5ef2aSThomas Huth void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \ 718fcf5ef2aSThomas Huth ppc_avr_t *a, ppc_avr_t *b) \ 719fcf5ef2aSThomas Huth { \ 720fcf5ef2aSThomas Huth uint64_t ones = (uint64_t)-1; \ 721fcf5ef2aSThomas Huth uint64_t all = ones; \ 722fcf5ef2aSThomas Huth uint64_t none = 0; \ 723fcf5ef2aSThomas Huth int i; \ 724fcf5ef2aSThomas Huth \ 725fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 726fcf5ef2aSThomas Huth uint64_t result = (a->element[i] compare b->element[i] ? \ 727fcf5ef2aSThomas Huth ones : 0x0); \ 728fcf5ef2aSThomas Huth switch (sizeof(a->element[0])) { \ 729fcf5ef2aSThomas Huth case 8: \ 730fcf5ef2aSThomas Huth r->u64[i] = result; \ 731fcf5ef2aSThomas Huth break; \ 732fcf5ef2aSThomas Huth case 4: \ 733fcf5ef2aSThomas Huth r->u32[i] = result; \ 734fcf5ef2aSThomas Huth break; \ 735fcf5ef2aSThomas Huth case 2: \ 736fcf5ef2aSThomas Huth r->u16[i] = result; \ 737fcf5ef2aSThomas Huth break; \ 738fcf5ef2aSThomas Huth case 1: \ 739fcf5ef2aSThomas Huth r->u8[i] = result; \ 740fcf5ef2aSThomas Huth break; \ 741fcf5ef2aSThomas Huth } \ 742fcf5ef2aSThomas Huth all &= result; \ 743fcf5ef2aSThomas Huth none |= result; \ 744fcf5ef2aSThomas Huth } \ 745fcf5ef2aSThomas Huth if (record) { \ 746fcf5ef2aSThomas Huth env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \ 747fcf5ef2aSThomas Huth } \ 748fcf5ef2aSThomas Huth } 749fcf5ef2aSThomas Huth #define VCMP(suffix, compare, element) \ 750fcf5ef2aSThomas Huth VCMP_DO(suffix, compare, element, 0) \ 751fcf5ef2aSThomas Huth VCMP_DO(suffix##_dot, compare, element, 1) 752fcf5ef2aSThomas Huth VCMP(equb, ==, u8) 753fcf5ef2aSThomas Huth VCMP(equh, ==, u16) 754fcf5ef2aSThomas Huth VCMP(equw, ==, u32) 755fcf5ef2aSThomas Huth VCMP(equd, ==, u64) 756fcf5ef2aSThomas Huth VCMP(gtub, >, u8) 757fcf5ef2aSThomas Huth VCMP(gtuh, >, u16) 758fcf5ef2aSThomas Huth VCMP(gtuw, >, u32) 759fcf5ef2aSThomas Huth VCMP(gtud, >, u64) 760fcf5ef2aSThomas Huth VCMP(gtsb, >, s8) 761fcf5ef2aSThomas Huth VCMP(gtsh, >, s16) 762fcf5ef2aSThomas Huth VCMP(gtsw, >, s32) 763fcf5ef2aSThomas Huth VCMP(gtsd, >, s64) 764fcf5ef2aSThomas Huth #undef VCMP_DO 765fcf5ef2aSThomas Huth #undef VCMP 766fcf5ef2aSThomas Huth 767fcf5ef2aSThomas Huth #define VCMPNE_DO(suffix, element, etype, cmpzero, record) \ 768fcf5ef2aSThomas Huth void helper_vcmpne##suffix(CPUPPCState *env, ppc_avr_t *r, \ 769fcf5ef2aSThomas Huth ppc_avr_t *a, ppc_avr_t *b) \ 770fcf5ef2aSThomas Huth { \ 771fcf5ef2aSThomas Huth etype ones = (etype)-1; \ 772fcf5ef2aSThomas Huth etype all = ones; \ 773fcf5ef2aSThomas Huth etype result, none = 0; \ 774fcf5ef2aSThomas Huth int i; \ 775fcf5ef2aSThomas Huth \ 776fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 777fcf5ef2aSThomas Huth if (cmpzero) { \ 778fcf5ef2aSThomas Huth result = ((a->element[i] == 0) \ 779fcf5ef2aSThomas Huth || (b->element[i] == 0) \ 780fcf5ef2aSThomas Huth || (a->element[i] != b->element[i]) ? \ 781fcf5ef2aSThomas Huth ones : 0x0); \ 782fcf5ef2aSThomas Huth } else { \ 783fcf5ef2aSThomas Huth result = (a->element[i] != b->element[i]) ? ones : 0x0; \ 784fcf5ef2aSThomas Huth } \ 785fcf5ef2aSThomas Huth r->element[i] = result; \ 786fcf5ef2aSThomas Huth all &= result; \ 787fcf5ef2aSThomas Huth none |= result; \ 788fcf5ef2aSThomas Huth } \ 789fcf5ef2aSThomas Huth if (record) { \ 790fcf5ef2aSThomas Huth env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \ 791fcf5ef2aSThomas Huth } \ 792fcf5ef2aSThomas Huth } 793fcf5ef2aSThomas Huth 794b6cb41b2SDavid Gibson /* 795b6cb41b2SDavid Gibson * VCMPNEZ - Vector compare not equal to zero 796fcf5ef2aSThomas Huth * suffix - instruction mnemonic suffix (b: byte, h: halfword, w: word) 797fcf5ef2aSThomas Huth * element - element type to access from vector 798fcf5ef2aSThomas Huth */ 799fcf5ef2aSThomas Huth #define VCMPNE(suffix, element, etype, cmpzero) \ 800fcf5ef2aSThomas Huth VCMPNE_DO(suffix, element, etype, cmpzero, 0) \ 801fcf5ef2aSThomas Huth VCMPNE_DO(suffix##_dot, element, etype, cmpzero, 1) 802fcf5ef2aSThomas Huth VCMPNE(zb, u8, uint8_t, 1) 803fcf5ef2aSThomas Huth VCMPNE(zh, u16, uint16_t, 1) 804fcf5ef2aSThomas Huth VCMPNE(zw, u32, uint32_t, 1) 805fcf5ef2aSThomas Huth VCMPNE(b, u8, uint8_t, 0) 806fcf5ef2aSThomas Huth VCMPNE(h, u16, uint16_t, 0) 807fcf5ef2aSThomas Huth VCMPNE(w, u32, uint32_t, 0) 808fcf5ef2aSThomas Huth #undef VCMPNE_DO 809fcf5ef2aSThomas Huth #undef VCMPNE 810fcf5ef2aSThomas Huth 811fcf5ef2aSThomas Huth #define VCMPFP_DO(suffix, compare, order, record) \ 812fcf5ef2aSThomas Huth void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \ 813fcf5ef2aSThomas Huth ppc_avr_t *a, ppc_avr_t *b) \ 814fcf5ef2aSThomas Huth { \ 815fcf5ef2aSThomas Huth uint32_t ones = (uint32_t)-1; \ 816fcf5ef2aSThomas Huth uint32_t all = ones; \ 817fcf5ef2aSThomas Huth uint32_t none = 0; \ 818fcf5ef2aSThomas Huth int i; \ 819fcf5ef2aSThomas Huth \ 82005ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ 821fcf5ef2aSThomas Huth uint32_t result; \ 82271bfd65cSRichard Henderson FloatRelation rel = \ 82371bfd65cSRichard Henderson float32_compare_quiet(a->f32[i], b->f32[i], \ 824fcf5ef2aSThomas Huth &env->vec_status); \ 825fcf5ef2aSThomas Huth if (rel == float_relation_unordered) { \ 826fcf5ef2aSThomas Huth result = 0; \ 827fcf5ef2aSThomas Huth } else if (rel compare order) { \ 828fcf5ef2aSThomas Huth result = ones; \ 829fcf5ef2aSThomas Huth } else { \ 830fcf5ef2aSThomas Huth result = 0; \ 831fcf5ef2aSThomas Huth } \ 832fcf5ef2aSThomas Huth r->u32[i] = result; \ 833fcf5ef2aSThomas Huth all &= result; \ 834fcf5ef2aSThomas Huth none |= result; \ 835fcf5ef2aSThomas Huth } \ 836fcf5ef2aSThomas Huth if (record) { \ 837fcf5ef2aSThomas Huth env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \ 838fcf5ef2aSThomas Huth } \ 839fcf5ef2aSThomas Huth } 840fcf5ef2aSThomas Huth #define VCMPFP(suffix, compare, order) \ 841fcf5ef2aSThomas Huth VCMPFP_DO(suffix, compare, order, 0) \ 842fcf5ef2aSThomas Huth VCMPFP_DO(suffix##_dot, compare, order, 1) 843fcf5ef2aSThomas Huth VCMPFP(eqfp, ==, float_relation_equal) 844fcf5ef2aSThomas Huth VCMPFP(gefp, !=, float_relation_less) 845fcf5ef2aSThomas Huth VCMPFP(gtfp, ==, float_relation_greater) 846fcf5ef2aSThomas Huth #undef VCMPFP_DO 847fcf5ef2aSThomas Huth #undef VCMPFP 848fcf5ef2aSThomas Huth 849fcf5ef2aSThomas Huth static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r, 850fcf5ef2aSThomas Huth ppc_avr_t *a, ppc_avr_t *b, int record) 851fcf5ef2aSThomas Huth { 852fcf5ef2aSThomas Huth int i; 853fcf5ef2aSThomas Huth int all_in = 0; 854fcf5ef2aSThomas Huth 85505ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { 85671bfd65cSRichard Henderson FloatRelation le_rel = float32_compare_quiet(a->f32[i], b->f32[i], 85705ee3e8aSMark Cave-Ayland &env->vec_status); 858fcf5ef2aSThomas Huth if (le_rel == float_relation_unordered) { 859fcf5ef2aSThomas Huth r->u32[i] = 0xc0000000; 860fcf5ef2aSThomas Huth all_in = 1; 861fcf5ef2aSThomas Huth } else { 86205ee3e8aSMark Cave-Ayland float32 bneg = float32_chs(b->f32[i]); 86371bfd65cSRichard Henderson FloatRelation ge_rel = float32_compare_quiet(a->f32[i], bneg, 86405ee3e8aSMark Cave-Ayland &env->vec_status); 865fcf5ef2aSThomas Huth int le = le_rel != float_relation_greater; 866fcf5ef2aSThomas Huth int ge = ge_rel != float_relation_less; 867fcf5ef2aSThomas Huth 868fcf5ef2aSThomas Huth r->u32[i] = ((!le) << 31) | ((!ge) << 30); 869fcf5ef2aSThomas Huth all_in |= (!le | !ge); 870fcf5ef2aSThomas Huth } 871fcf5ef2aSThomas Huth } 872fcf5ef2aSThomas Huth if (record) { 873fcf5ef2aSThomas Huth env->crf[6] = (all_in == 0) << 1; 874fcf5ef2aSThomas Huth } 875fcf5ef2aSThomas Huth } 876fcf5ef2aSThomas Huth 877fcf5ef2aSThomas Huth void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 878fcf5ef2aSThomas Huth { 879fcf5ef2aSThomas Huth vcmpbfp_internal(env, r, a, b, 0); 880fcf5ef2aSThomas Huth } 881fcf5ef2aSThomas Huth 882fcf5ef2aSThomas Huth void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 883fcf5ef2aSThomas Huth ppc_avr_t *b) 884fcf5ef2aSThomas Huth { 885fcf5ef2aSThomas Huth vcmpbfp_internal(env, r, a, b, 1); 886fcf5ef2aSThomas Huth } 887fcf5ef2aSThomas Huth 888fcf5ef2aSThomas Huth #define VCT(suffix, satcvt, element) \ 889fcf5ef2aSThomas Huth void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r, \ 890fcf5ef2aSThomas Huth ppc_avr_t *b, uint32_t uim) \ 891fcf5ef2aSThomas Huth { \ 892fcf5ef2aSThomas Huth int i; \ 893fcf5ef2aSThomas Huth int sat = 0; \ 894fcf5ef2aSThomas Huth float_status s = env->vec_status; \ 895fcf5ef2aSThomas Huth \ 896fcf5ef2aSThomas Huth set_float_rounding_mode(float_round_to_zero, &s); \ 89705ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ 89805ee3e8aSMark Cave-Ayland if (float32_is_any_nan(b->f32[i])) { \ 899fcf5ef2aSThomas Huth r->element[i] = 0; \ 900fcf5ef2aSThomas Huth } else { \ 90105ee3e8aSMark Cave-Ayland float64 t = float32_to_float64(b->f32[i], &s); \ 902fcf5ef2aSThomas Huth int64_t j; \ 903fcf5ef2aSThomas Huth \ 904fcf5ef2aSThomas Huth t = float64_scalbn(t, uim, &s); \ 905fcf5ef2aSThomas Huth j = float64_to_int64(t, &s); \ 906fcf5ef2aSThomas Huth r->element[i] = satcvt(j, &sat); \ 907fcf5ef2aSThomas Huth } \ 908fcf5ef2aSThomas Huth } \ 909fcf5ef2aSThomas Huth if (sat) { \ 9106175f5a0SRichard Henderson set_vscr_sat(env); \ 911fcf5ef2aSThomas Huth } \ 912fcf5ef2aSThomas Huth } 913fcf5ef2aSThomas Huth VCT(uxs, cvtsduw, u32) 914fcf5ef2aSThomas Huth VCT(sxs, cvtsdsw, s32) 915fcf5ef2aSThomas Huth #undef VCT 916fcf5ef2aSThomas Huth 917fcf5ef2aSThomas Huth target_ulong helper_vclzlsbb(ppc_avr_t *r) 918fcf5ef2aSThomas Huth { 919fcf5ef2aSThomas Huth target_ulong count = 0; 920fcf5ef2aSThomas Huth int i; 92160594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->u8); i++) { 92260594feaSMark Cave-Ayland if (r->VsrB(i) & 0x01) { 923fcf5ef2aSThomas Huth break; 924fcf5ef2aSThomas Huth } 925fcf5ef2aSThomas Huth count++; 926fcf5ef2aSThomas Huth } 927fcf5ef2aSThomas Huth return count; 928fcf5ef2aSThomas Huth } 929fcf5ef2aSThomas Huth 930fcf5ef2aSThomas Huth target_ulong helper_vctzlsbb(ppc_avr_t *r) 931fcf5ef2aSThomas Huth { 932fcf5ef2aSThomas Huth target_ulong count = 0; 933fcf5ef2aSThomas Huth int i; 934fcf5ef2aSThomas Huth for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { 93560594feaSMark Cave-Ayland if (r->VsrB(i) & 0x01) { 936fcf5ef2aSThomas Huth break; 937fcf5ef2aSThomas Huth } 938fcf5ef2aSThomas Huth count++; 939fcf5ef2aSThomas Huth } 940fcf5ef2aSThomas Huth return count; 941fcf5ef2aSThomas Huth } 942fcf5ef2aSThomas Huth 943fcf5ef2aSThomas Huth void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 944fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 945fcf5ef2aSThomas Huth { 946fcf5ef2aSThomas Huth int sat = 0; 947fcf5ef2aSThomas Huth int i; 948fcf5ef2aSThomas Huth 949fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s16); i++) { 950fcf5ef2aSThomas Huth int32_t prod = a->s16[i] * b->s16[i]; 951fcf5ef2aSThomas Huth int32_t t = (int32_t)c->s16[i] + (prod >> 15); 952fcf5ef2aSThomas Huth 953fcf5ef2aSThomas Huth r->s16[i] = cvtswsh(t, &sat); 954fcf5ef2aSThomas Huth } 955fcf5ef2aSThomas Huth 956fcf5ef2aSThomas Huth if (sat) { 9576175f5a0SRichard Henderson set_vscr_sat(env); 958fcf5ef2aSThomas Huth } 959fcf5ef2aSThomas Huth } 960fcf5ef2aSThomas Huth 961fcf5ef2aSThomas Huth void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 962fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 963fcf5ef2aSThomas Huth { 964fcf5ef2aSThomas Huth int sat = 0; 965fcf5ef2aSThomas Huth int i; 966fcf5ef2aSThomas Huth 967fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s16); i++) { 968fcf5ef2aSThomas Huth int32_t prod = a->s16[i] * b->s16[i] + 0x00004000; 969fcf5ef2aSThomas Huth int32_t t = (int32_t)c->s16[i] + (prod >> 15); 970fcf5ef2aSThomas Huth r->s16[i] = cvtswsh(t, &sat); 971fcf5ef2aSThomas Huth } 972fcf5ef2aSThomas Huth 973fcf5ef2aSThomas Huth if (sat) { 9746175f5a0SRichard Henderson set_vscr_sat(env); 975fcf5ef2aSThomas Huth } 976fcf5ef2aSThomas Huth } 977fcf5ef2aSThomas Huth 978fcf5ef2aSThomas Huth void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) 979fcf5ef2aSThomas Huth { 980fcf5ef2aSThomas Huth int i; 981fcf5ef2aSThomas Huth 982fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s16); i++) { 983fcf5ef2aSThomas Huth int32_t prod = a->s16[i] * b->s16[i]; 984fcf5ef2aSThomas Huth r->s16[i] = (int16_t) (prod + c->s16[i]); 985fcf5ef2aSThomas Huth } 986fcf5ef2aSThomas Huth } 987fcf5ef2aSThomas Huth 988d81c2040SMark Cave-Ayland #define VMRG_DO(name, element, access, ofs) \ 989fcf5ef2aSThomas Huth void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 990fcf5ef2aSThomas Huth { \ 991fcf5ef2aSThomas Huth ppc_avr_t result; \ 992d81c2040SMark Cave-Ayland int i, half = ARRAY_SIZE(r->element) / 2; \ 993fcf5ef2aSThomas Huth \ 994d81c2040SMark Cave-Ayland for (i = 0; i < half; i++) { \ 995d81c2040SMark Cave-Ayland result.access(i * 2 + 0) = a->access(i + ofs); \ 996d81c2040SMark Cave-Ayland result.access(i * 2 + 1) = b->access(i + ofs); \ 997fcf5ef2aSThomas Huth } \ 998fcf5ef2aSThomas Huth *r = result; \ 999fcf5ef2aSThomas Huth } 1000d81c2040SMark Cave-Ayland 1001d81c2040SMark Cave-Ayland #define VMRG(suffix, element, access) \ 1002d81c2040SMark Cave-Ayland VMRG_DO(mrgl##suffix, element, access, half) \ 1003d81c2040SMark Cave-Ayland VMRG_DO(mrgh##suffix, element, access, 0) 1004d81c2040SMark Cave-Ayland VMRG(b, u8, VsrB) 1005d81c2040SMark Cave-Ayland VMRG(h, u16, VsrH) 1006d81c2040SMark Cave-Ayland VMRG(w, u32, VsrW) 1007fcf5ef2aSThomas Huth #undef VMRG_DO 1008fcf5ef2aSThomas Huth #undef VMRG 1009fcf5ef2aSThomas Huth 1010fcf5ef2aSThomas Huth void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 1011fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 1012fcf5ef2aSThomas Huth { 1013fcf5ef2aSThomas Huth int32_t prod[16]; 1014fcf5ef2aSThomas Huth int i; 1015fcf5ef2aSThomas Huth 1016fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s8); i++) { 1017fcf5ef2aSThomas Huth prod[i] = (int32_t)a->s8[i] * b->u8[i]; 1018fcf5ef2aSThomas Huth } 1019fcf5ef2aSThomas Huth 1020fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, s32) { 1021fcf5ef2aSThomas Huth r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] + 1022fcf5ef2aSThomas Huth prod[4 * i + 2] + prod[4 * i + 3]; 1023fcf5ef2aSThomas Huth } 1024fcf5ef2aSThomas Huth } 1025fcf5ef2aSThomas Huth 1026fcf5ef2aSThomas Huth void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 1027fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 1028fcf5ef2aSThomas Huth { 1029fcf5ef2aSThomas Huth int32_t prod[8]; 1030fcf5ef2aSThomas Huth int i; 1031fcf5ef2aSThomas Huth 1032fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s16); i++) { 1033fcf5ef2aSThomas Huth prod[i] = a->s16[i] * b->s16[i]; 1034fcf5ef2aSThomas Huth } 1035fcf5ef2aSThomas Huth 1036fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, s32) { 1037fcf5ef2aSThomas Huth r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1]; 1038fcf5ef2aSThomas Huth } 1039fcf5ef2aSThomas Huth } 1040fcf5ef2aSThomas Huth 1041fcf5ef2aSThomas Huth void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 1042fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 1043fcf5ef2aSThomas Huth { 1044fcf5ef2aSThomas Huth int32_t prod[8]; 1045fcf5ef2aSThomas Huth int i; 1046fcf5ef2aSThomas Huth int sat = 0; 1047fcf5ef2aSThomas Huth 1048fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s16); i++) { 1049fcf5ef2aSThomas Huth prod[i] = (int32_t)a->s16[i] * b->s16[i]; 1050fcf5ef2aSThomas Huth } 1051fcf5ef2aSThomas Huth 1052fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, s32) { 1053fcf5ef2aSThomas Huth int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1]; 1054fcf5ef2aSThomas Huth 1055fcf5ef2aSThomas Huth r->u32[i] = cvtsdsw(t, &sat); 1056fcf5ef2aSThomas Huth } 1057fcf5ef2aSThomas Huth 1058fcf5ef2aSThomas Huth if (sat) { 10596175f5a0SRichard Henderson set_vscr_sat(env); 1060fcf5ef2aSThomas Huth } 1061fcf5ef2aSThomas Huth } 1062fcf5ef2aSThomas Huth 1063fcf5ef2aSThomas Huth void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 1064fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 1065fcf5ef2aSThomas Huth { 1066fcf5ef2aSThomas Huth uint16_t prod[16]; 1067fcf5ef2aSThomas Huth int i; 1068fcf5ef2aSThomas Huth 1069fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u8); i++) { 1070fcf5ef2aSThomas Huth prod[i] = a->u8[i] * b->u8[i]; 1071fcf5ef2aSThomas Huth } 1072fcf5ef2aSThomas Huth 1073fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u32) { 1074fcf5ef2aSThomas Huth r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] + 1075fcf5ef2aSThomas Huth prod[4 * i + 2] + prod[4 * i + 3]; 1076fcf5ef2aSThomas Huth } 1077fcf5ef2aSThomas Huth } 1078fcf5ef2aSThomas Huth 1079fcf5ef2aSThomas Huth void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 1080fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 1081fcf5ef2aSThomas Huth { 1082fcf5ef2aSThomas Huth uint32_t prod[8]; 1083fcf5ef2aSThomas Huth int i; 1084fcf5ef2aSThomas Huth 1085fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u16); i++) { 1086fcf5ef2aSThomas Huth prod[i] = a->u16[i] * b->u16[i]; 1087fcf5ef2aSThomas Huth } 1088fcf5ef2aSThomas Huth 1089fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u32) { 1090fcf5ef2aSThomas Huth r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1]; 1091fcf5ef2aSThomas Huth } 1092fcf5ef2aSThomas Huth } 1093fcf5ef2aSThomas Huth 1094fcf5ef2aSThomas Huth void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, 1095fcf5ef2aSThomas Huth ppc_avr_t *b, ppc_avr_t *c) 1096fcf5ef2aSThomas Huth { 1097fcf5ef2aSThomas Huth uint32_t prod[8]; 1098fcf5ef2aSThomas Huth int i; 1099fcf5ef2aSThomas Huth int sat = 0; 1100fcf5ef2aSThomas Huth 1101fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u16); i++) { 1102fcf5ef2aSThomas Huth prod[i] = a->u16[i] * b->u16[i]; 1103fcf5ef2aSThomas Huth } 1104fcf5ef2aSThomas Huth 1105fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, s32) { 1106fcf5ef2aSThomas Huth uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1]; 1107fcf5ef2aSThomas Huth 1108fcf5ef2aSThomas Huth r->u32[i] = cvtuduw(t, &sat); 1109fcf5ef2aSThomas Huth } 1110fcf5ef2aSThomas Huth 1111fcf5ef2aSThomas Huth if (sat) { 11126175f5a0SRichard Henderson set_vscr_sat(env); 1113fcf5ef2aSThomas Huth } 1114fcf5ef2aSThomas Huth } 1115fcf5ef2aSThomas Huth 11164fbc89edSMark Cave-Ayland #define VMUL_DO_EVN(name, mul_element, mul_access, prod_access, cast) \ 1117fcf5ef2aSThomas Huth void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 1118fcf5ef2aSThomas Huth { \ 1119fcf5ef2aSThomas Huth int i; \ 1120fcf5ef2aSThomas Huth \ 11214fbc89edSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \ 11224fbc89edSMark Cave-Ayland r->prod_access(i >> 1) = (cast)a->mul_access(i) * \ 11234fbc89edSMark Cave-Ayland (cast)b->mul_access(i); \ 1124fcf5ef2aSThomas Huth } \ 1125fcf5ef2aSThomas Huth } 11264fbc89edSMark Cave-Ayland 11274fbc89edSMark Cave-Ayland #define VMUL_DO_ODD(name, mul_element, mul_access, prod_access, cast) \ 11284fbc89edSMark Cave-Ayland void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 11294fbc89edSMark Cave-Ayland { \ 11304fbc89edSMark Cave-Ayland int i; \ 11314fbc89edSMark Cave-Ayland \ 11324fbc89edSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \ 11334fbc89edSMark Cave-Ayland r->prod_access(i >> 1) = (cast)a->mul_access(i + 1) * \ 11344fbc89edSMark Cave-Ayland (cast)b->mul_access(i + 1); \ 11354fbc89edSMark Cave-Ayland } \ 11364fbc89edSMark Cave-Ayland } 11374fbc89edSMark Cave-Ayland 11384fbc89edSMark Cave-Ayland #define VMUL(suffix, mul_element, mul_access, prod_access, cast) \ 11394fbc89edSMark Cave-Ayland VMUL_DO_EVN(mule##suffix, mul_element, mul_access, prod_access, cast) \ 11404fbc89edSMark Cave-Ayland VMUL_DO_ODD(mulo##suffix, mul_element, mul_access, prod_access, cast) 11414fbc89edSMark Cave-Ayland VMUL(sb, s8, VsrSB, VsrSH, int16_t) 11424fbc89edSMark Cave-Ayland VMUL(sh, s16, VsrSH, VsrSW, int32_t) 11434fbc89edSMark Cave-Ayland VMUL(sw, s32, VsrSW, VsrSD, int64_t) 11444fbc89edSMark Cave-Ayland VMUL(ub, u8, VsrB, VsrH, uint16_t) 11454fbc89edSMark Cave-Ayland VMUL(uh, u16, VsrH, VsrW, uint32_t) 11464fbc89edSMark Cave-Ayland VMUL(uw, u32, VsrW, VsrD, uint64_t) 11474fbc89edSMark Cave-Ayland #undef VMUL_DO_EVN 11484fbc89edSMark Cave-Ayland #undef VMUL_DO_ODD 1149fcf5ef2aSThomas Huth #undef VMUL 1150fcf5ef2aSThomas Huth 1151f3e0d864SLijun Pan void helper_vmulhsw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1152f3e0d864SLijun Pan { 1153f3e0d864SLijun Pan int i; 1154f3e0d864SLijun Pan 1155f3e0d864SLijun Pan for (i = 0; i < 4; i++) { 1156f3e0d864SLijun Pan r->s32[i] = (int32_t)(((int64_t)a->s32[i] * (int64_t)b->s32[i]) >> 32); 1157f3e0d864SLijun Pan } 1158f3e0d864SLijun Pan } 1159f3e0d864SLijun Pan 1160f3e0d864SLijun Pan void helper_vmulhuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1161f3e0d864SLijun Pan { 1162f3e0d864SLijun Pan int i; 1163f3e0d864SLijun Pan 1164f3e0d864SLijun Pan for (i = 0; i < 4; i++) { 1165f3e0d864SLijun Pan r->u32[i] = (uint32_t)(((uint64_t)a->u32[i] * 1166f3e0d864SLijun Pan (uint64_t)b->u32[i]) >> 32); 1167f3e0d864SLijun Pan } 1168f3e0d864SLijun Pan } 1169f3e0d864SLijun Pan 1170c4b8b49dSLijun Pan void helper_vmulhsd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1171c4b8b49dSLijun Pan { 1172c4b8b49dSLijun Pan uint64_t discard; 1173c4b8b49dSLijun Pan 1174c4b8b49dSLijun Pan muls64(&discard, &r->u64[0], a->s64[0], b->s64[0]); 1175c4b8b49dSLijun Pan muls64(&discard, &r->u64[1], a->s64[1], b->s64[1]); 1176c4b8b49dSLijun Pan } 1177c4b8b49dSLijun Pan 1178c4b8b49dSLijun Pan void helper_vmulhud(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1179c4b8b49dSLijun Pan { 1180c4b8b49dSLijun Pan uint64_t discard; 1181c4b8b49dSLijun Pan 1182c4b8b49dSLijun Pan mulu64(&discard, &r->u64[0], a->u64[0], b->u64[0]); 1183c4b8b49dSLijun Pan mulu64(&discard, &r->u64[1], a->u64[1], b->u64[1]); 1184c4b8b49dSLijun Pan } 1185c4b8b49dSLijun Pan 1186fcf5ef2aSThomas Huth void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, 1187fcf5ef2aSThomas Huth ppc_avr_t *c) 1188fcf5ef2aSThomas Huth { 1189fcf5ef2aSThomas Huth ppc_avr_t result; 1190fcf5ef2aSThomas Huth int i; 1191fcf5ef2aSThomas Huth 119260594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->u8); i++) { 119360594feaSMark Cave-Ayland int s = c->VsrB(i) & 0x1f; 1194fcf5ef2aSThomas Huth int index = s & 0xf; 1195fcf5ef2aSThomas Huth 1196fcf5ef2aSThomas Huth if (s & 0x10) { 119760594feaSMark Cave-Ayland result.VsrB(i) = b->VsrB(index); 1198fcf5ef2aSThomas Huth } else { 119960594feaSMark Cave-Ayland result.VsrB(i) = a->VsrB(index); 1200fcf5ef2aSThomas Huth } 1201fcf5ef2aSThomas Huth } 1202fcf5ef2aSThomas Huth *r = result; 1203fcf5ef2aSThomas Huth } 1204fcf5ef2aSThomas Huth 1205fcf5ef2aSThomas Huth void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, 1206fcf5ef2aSThomas Huth ppc_avr_t *c) 1207fcf5ef2aSThomas Huth { 1208fcf5ef2aSThomas Huth ppc_avr_t result; 1209fcf5ef2aSThomas Huth int i; 1210fcf5ef2aSThomas Huth 121160594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->u8); i++) { 121260594feaSMark Cave-Ayland int s = c->VsrB(i) & 0x1f; 1213fcf5ef2aSThomas Huth int index = 15 - (s & 0xf); 1214fcf5ef2aSThomas Huth 1215fcf5ef2aSThomas Huth if (s & 0x10) { 121660594feaSMark Cave-Ayland result.VsrB(i) = a->VsrB(index); 1217fcf5ef2aSThomas Huth } else { 121860594feaSMark Cave-Ayland result.VsrB(i) = b->VsrB(index); 1219fcf5ef2aSThomas Huth } 1220fcf5ef2aSThomas Huth } 1221fcf5ef2aSThomas Huth *r = result; 1222fcf5ef2aSThomas Huth } 1223fcf5ef2aSThomas Huth 1224fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1225fcf5ef2aSThomas Huth #define VBPERMQ_INDEX(avr, i) ((avr)->u8[(i)]) 1226fcf5ef2aSThomas Huth #define VBPERMD_INDEX(i) (i) 1227fcf5ef2aSThomas Huth #define VBPERMQ_DW(index) (((index) & 0x40) != 0) 1228fcf5ef2aSThomas Huth #define EXTRACT_BIT(avr, i, index) (extract64((avr)->u64[i], index, 1)) 1229fcf5ef2aSThomas Huth #else 1230fcf5ef2aSThomas Huth #define VBPERMQ_INDEX(avr, i) ((avr)->u8[15 - (i)]) 1231fcf5ef2aSThomas Huth #define VBPERMD_INDEX(i) (1 - i) 1232fcf5ef2aSThomas Huth #define VBPERMQ_DW(index) (((index) & 0x40) == 0) 1233fcf5ef2aSThomas Huth #define EXTRACT_BIT(avr, i, index) \ 1234fcf5ef2aSThomas Huth (extract64((avr)->u64[1 - i], 63 - index, 1)) 1235fcf5ef2aSThomas Huth #endif 1236fcf5ef2aSThomas Huth 1237fcf5ef2aSThomas Huth void helper_vbpermd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1238fcf5ef2aSThomas Huth { 1239fcf5ef2aSThomas Huth int i, j; 1240fcf5ef2aSThomas Huth ppc_avr_t result = { .u64 = { 0, 0 } }; 1241fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u64) { 1242fcf5ef2aSThomas Huth for (j = 0; j < 8; j++) { 1243fcf5ef2aSThomas Huth int index = VBPERMQ_INDEX(b, (i * 8) + j); 1244fcf5ef2aSThomas Huth if (index < 64 && EXTRACT_BIT(a, i, index)) { 1245fcf5ef2aSThomas Huth result.u64[VBPERMD_INDEX(i)] |= (0x80 >> j); 1246fcf5ef2aSThomas Huth } 1247fcf5ef2aSThomas Huth } 1248fcf5ef2aSThomas Huth } 1249fcf5ef2aSThomas Huth *r = result; 1250fcf5ef2aSThomas Huth } 1251fcf5ef2aSThomas Huth 1252fcf5ef2aSThomas Huth void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1253fcf5ef2aSThomas Huth { 1254fcf5ef2aSThomas Huth int i; 1255fcf5ef2aSThomas Huth uint64_t perm = 0; 1256fcf5ef2aSThomas Huth 1257fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u8) { 1258fcf5ef2aSThomas Huth int index = VBPERMQ_INDEX(b, i); 1259fcf5ef2aSThomas Huth 1260fcf5ef2aSThomas Huth if (index < 128) { 1261fcf5ef2aSThomas Huth uint64_t mask = (1ull << (63 - (index & 0x3F))); 1262fcf5ef2aSThomas Huth if (a->u64[VBPERMQ_DW(index)] & mask) { 1263fcf5ef2aSThomas Huth perm |= (0x8000 >> i); 1264fcf5ef2aSThomas Huth } 1265fcf5ef2aSThomas Huth } 1266fcf5ef2aSThomas Huth } 1267fcf5ef2aSThomas Huth 12683c385a93SMark Cave-Ayland r->VsrD(0) = perm; 12693c385a93SMark Cave-Ayland r->VsrD(1) = 0; 1270fcf5ef2aSThomas Huth } 1271fcf5ef2aSThomas Huth 1272fcf5ef2aSThomas Huth #undef VBPERMQ_INDEX 1273fcf5ef2aSThomas Huth #undef VBPERMQ_DW 1274fcf5ef2aSThomas Huth 1275fcf5ef2aSThomas Huth #define PMSUM(name, srcfld, trgfld, trgtyp) \ 1276fcf5ef2aSThomas Huth void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 1277fcf5ef2aSThomas Huth { \ 1278fcf5ef2aSThomas Huth int i, j; \ 1279fcf5ef2aSThomas Huth trgtyp prod[sizeof(ppc_avr_t) / sizeof(a->srcfld[0])]; \ 1280fcf5ef2aSThomas Huth \ 1281fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, srcfld) { \ 1282fcf5ef2aSThomas Huth prod[i] = 0; \ 1283fcf5ef2aSThomas Huth for (j = 0; j < sizeof(a->srcfld[0]) * 8; j++) { \ 1284fcf5ef2aSThomas Huth if (a->srcfld[i] & (1ull << j)) { \ 1285fcf5ef2aSThomas Huth prod[i] ^= ((trgtyp)b->srcfld[i] << j); \ 1286fcf5ef2aSThomas Huth } \ 1287fcf5ef2aSThomas Huth } \ 1288fcf5ef2aSThomas Huth } \ 1289fcf5ef2aSThomas Huth \ 1290fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, trgfld) { \ 1291fcf5ef2aSThomas Huth r->trgfld[i] = prod[2 * i] ^ prod[2 * i + 1]; \ 1292fcf5ef2aSThomas Huth } \ 1293fcf5ef2aSThomas Huth } 1294fcf5ef2aSThomas Huth 1295fcf5ef2aSThomas Huth PMSUM(vpmsumb, u8, u16, uint16_t) 1296fcf5ef2aSThomas Huth PMSUM(vpmsumh, u16, u32, uint32_t) 1297fcf5ef2aSThomas Huth PMSUM(vpmsumw, u32, u64, uint64_t) 1298fcf5ef2aSThomas Huth 1299fcf5ef2aSThomas Huth void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1300fcf5ef2aSThomas Huth { 1301fcf5ef2aSThomas Huth 1302fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 1303fcf5ef2aSThomas Huth int i, j; 1304fcf5ef2aSThomas Huth __uint128_t prod[2]; 1305fcf5ef2aSThomas Huth 1306fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u64) { 1307fcf5ef2aSThomas Huth prod[i] = 0; 1308fcf5ef2aSThomas Huth for (j = 0; j < 64; j++) { 1309fcf5ef2aSThomas Huth if (a->u64[i] & (1ull << j)) { 1310fcf5ef2aSThomas Huth prod[i] ^= (((__uint128_t)b->u64[i]) << j); 1311fcf5ef2aSThomas Huth } 1312fcf5ef2aSThomas Huth } 1313fcf5ef2aSThomas Huth } 1314fcf5ef2aSThomas Huth 1315fcf5ef2aSThomas Huth r->u128 = prod[0] ^ prod[1]; 1316fcf5ef2aSThomas Huth 1317fcf5ef2aSThomas Huth #else 1318fcf5ef2aSThomas Huth int i, j; 1319fcf5ef2aSThomas Huth ppc_avr_t prod[2]; 1320fcf5ef2aSThomas Huth 1321fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u64) { 13223c385a93SMark Cave-Ayland prod[i].VsrD(1) = prod[i].VsrD(0) = 0; 1323fcf5ef2aSThomas Huth for (j = 0; j < 64; j++) { 1324fcf5ef2aSThomas Huth if (a->u64[i] & (1ull << j)) { 1325fcf5ef2aSThomas Huth ppc_avr_t bshift; 1326fcf5ef2aSThomas Huth if (j == 0) { 13273c385a93SMark Cave-Ayland bshift.VsrD(0) = 0; 13283c385a93SMark Cave-Ayland bshift.VsrD(1) = b->u64[i]; 1329fcf5ef2aSThomas Huth } else { 13303c385a93SMark Cave-Ayland bshift.VsrD(0) = b->u64[i] >> (64 - j); 13313c385a93SMark Cave-Ayland bshift.VsrD(1) = b->u64[i] << j; 1332fcf5ef2aSThomas Huth } 13333c385a93SMark Cave-Ayland prod[i].VsrD(1) ^= bshift.VsrD(1); 13343c385a93SMark Cave-Ayland prod[i].VsrD(0) ^= bshift.VsrD(0); 1335fcf5ef2aSThomas Huth } 1336fcf5ef2aSThomas Huth } 1337fcf5ef2aSThomas Huth } 1338fcf5ef2aSThomas Huth 13393c385a93SMark Cave-Ayland r->VsrD(1) = prod[0].VsrD(1) ^ prod[1].VsrD(1); 13403c385a93SMark Cave-Ayland r->VsrD(0) = prod[0].VsrD(0) ^ prod[1].VsrD(0); 1341fcf5ef2aSThomas Huth #endif 1342fcf5ef2aSThomas Huth } 1343fcf5ef2aSThomas Huth 1344fcf5ef2aSThomas Huth 1345fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1346fcf5ef2aSThomas Huth #define PKBIG 1 1347fcf5ef2aSThomas Huth #else 1348fcf5ef2aSThomas Huth #define PKBIG 0 1349fcf5ef2aSThomas Huth #endif 1350fcf5ef2aSThomas Huth void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1351fcf5ef2aSThomas Huth { 1352fcf5ef2aSThomas Huth int i, j; 1353fcf5ef2aSThomas Huth ppc_avr_t result; 1354fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1355fcf5ef2aSThomas Huth const ppc_avr_t *x[2] = { a, b }; 1356fcf5ef2aSThomas Huth #else 1357fcf5ef2aSThomas Huth const ppc_avr_t *x[2] = { b, a }; 1358fcf5ef2aSThomas Huth #endif 1359fcf5ef2aSThomas Huth 1360fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u64) { 1361fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(j, u32) { 1362fcf5ef2aSThomas Huth uint32_t e = x[i]->u32[j]; 1363fcf5ef2aSThomas Huth 1364fcf5ef2aSThomas Huth result.u16[4 * i + j] = (((e >> 9) & 0xfc00) | 1365fcf5ef2aSThomas Huth ((e >> 6) & 0x3e0) | 1366fcf5ef2aSThomas Huth ((e >> 3) & 0x1f)); 1367fcf5ef2aSThomas Huth } 1368fcf5ef2aSThomas Huth } 1369fcf5ef2aSThomas Huth *r = result; 1370fcf5ef2aSThomas Huth } 1371fcf5ef2aSThomas Huth 1372fcf5ef2aSThomas Huth #define VPK(suffix, from, to, cvt, dosat) \ 1373fcf5ef2aSThomas Huth void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r, \ 1374fcf5ef2aSThomas Huth ppc_avr_t *a, ppc_avr_t *b) \ 1375fcf5ef2aSThomas Huth { \ 1376fcf5ef2aSThomas Huth int i; \ 1377fcf5ef2aSThomas Huth int sat = 0; \ 1378fcf5ef2aSThomas Huth ppc_avr_t result; \ 1379fcf5ef2aSThomas Huth ppc_avr_t *a0 = PKBIG ? a : b; \ 1380fcf5ef2aSThomas Huth ppc_avr_t *a1 = PKBIG ? b : a; \ 1381fcf5ef2aSThomas Huth \ 1382fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, from) { \ 1383fcf5ef2aSThomas Huth result.to[i] = cvt(a0->from[i], &sat); \ 1384fcf5ef2aSThomas Huth result.to[i + ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);\ 1385fcf5ef2aSThomas Huth } \ 1386fcf5ef2aSThomas Huth *r = result; \ 1387fcf5ef2aSThomas Huth if (dosat && sat) { \ 13886175f5a0SRichard Henderson set_vscr_sat(env); \ 1389fcf5ef2aSThomas Huth } \ 1390fcf5ef2aSThomas Huth } 1391fcf5ef2aSThomas Huth #define I(x, y) (x) 1392fcf5ef2aSThomas Huth VPK(shss, s16, s8, cvtshsb, 1) 1393fcf5ef2aSThomas Huth VPK(shus, s16, u8, cvtshub, 1) 1394fcf5ef2aSThomas Huth VPK(swss, s32, s16, cvtswsh, 1) 1395fcf5ef2aSThomas Huth VPK(swus, s32, u16, cvtswuh, 1) 1396fcf5ef2aSThomas Huth VPK(sdss, s64, s32, cvtsdsw, 1) 1397fcf5ef2aSThomas Huth VPK(sdus, s64, u32, cvtsduw, 1) 1398fcf5ef2aSThomas Huth VPK(uhus, u16, u8, cvtuhub, 1) 1399fcf5ef2aSThomas Huth VPK(uwus, u32, u16, cvtuwuh, 1) 1400fcf5ef2aSThomas Huth VPK(udus, u64, u32, cvtuduw, 1) 1401fcf5ef2aSThomas Huth VPK(uhum, u16, u8, I, 0) 1402fcf5ef2aSThomas Huth VPK(uwum, u32, u16, I, 0) 1403fcf5ef2aSThomas Huth VPK(udum, u64, u32, I, 0) 1404fcf5ef2aSThomas Huth #undef I 1405fcf5ef2aSThomas Huth #undef VPK 1406fcf5ef2aSThomas Huth #undef PKBIG 1407fcf5ef2aSThomas Huth 1408fcf5ef2aSThomas Huth void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) 1409fcf5ef2aSThomas Huth { 1410fcf5ef2aSThomas Huth int i; 1411fcf5ef2aSThomas Huth 141205ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { 141305ee3e8aSMark Cave-Ayland r->f32[i] = float32_div(float32_one, b->f32[i], &env->vec_status); 1414fcf5ef2aSThomas Huth } 1415fcf5ef2aSThomas Huth } 1416fcf5ef2aSThomas Huth 1417fcf5ef2aSThomas Huth #define VRFI(suffix, rounding) \ 1418fcf5ef2aSThomas Huth void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r, \ 1419fcf5ef2aSThomas Huth ppc_avr_t *b) \ 1420fcf5ef2aSThomas Huth { \ 1421fcf5ef2aSThomas Huth int i; \ 1422fcf5ef2aSThomas Huth float_status s = env->vec_status; \ 1423fcf5ef2aSThomas Huth \ 1424fcf5ef2aSThomas Huth set_float_rounding_mode(rounding, &s); \ 142505ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \ 142605ee3e8aSMark Cave-Ayland r->f32[i] = float32_round_to_int (b->f32[i], &s); \ 1427fcf5ef2aSThomas Huth } \ 1428fcf5ef2aSThomas Huth } 1429fcf5ef2aSThomas Huth VRFI(n, float_round_nearest_even) 1430fcf5ef2aSThomas Huth VRFI(m, float_round_down) 1431fcf5ef2aSThomas Huth VRFI(p, float_round_up) 1432fcf5ef2aSThomas Huth VRFI(z, float_round_to_zero) 1433fcf5ef2aSThomas Huth #undef VRFI 1434fcf5ef2aSThomas Huth 1435fcf5ef2aSThomas Huth void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) 1436fcf5ef2aSThomas Huth { 1437fcf5ef2aSThomas Huth int i; 1438fcf5ef2aSThomas Huth 143905ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { 144005ee3e8aSMark Cave-Ayland float32 t = float32_sqrt(b->f32[i], &env->vec_status); 1441fcf5ef2aSThomas Huth 144205ee3e8aSMark Cave-Ayland r->f32[i] = float32_div(float32_one, t, &env->vec_status); 1443fcf5ef2aSThomas Huth } 1444fcf5ef2aSThomas Huth } 1445fcf5ef2aSThomas Huth 1446fcf5ef2aSThomas Huth #define VRLMI(name, size, element, insert) \ 1447fcf5ef2aSThomas Huth void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ 1448fcf5ef2aSThomas Huth { \ 1449fcf5ef2aSThomas Huth int i; \ 1450fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 1451fcf5ef2aSThomas Huth uint##size##_t src1 = a->element[i]; \ 1452fcf5ef2aSThomas Huth uint##size##_t src2 = b->element[i]; \ 1453fcf5ef2aSThomas Huth uint##size##_t src3 = r->element[i]; \ 1454fcf5ef2aSThomas Huth uint##size##_t begin, end, shift, mask, rot_val; \ 1455fcf5ef2aSThomas Huth \ 1456fcf5ef2aSThomas Huth shift = extract##size(src2, 0, 6); \ 1457fcf5ef2aSThomas Huth end = extract##size(src2, 8, 6); \ 1458fcf5ef2aSThomas Huth begin = extract##size(src2, 16, 6); \ 1459fcf5ef2aSThomas Huth rot_val = rol##size(src1, shift); \ 1460fcf5ef2aSThomas Huth mask = mask_u##size(begin, end); \ 1461fcf5ef2aSThomas Huth if (insert) { \ 1462fcf5ef2aSThomas Huth r->element[i] = (rot_val & mask) | (src3 & ~mask); \ 1463fcf5ef2aSThomas Huth } else { \ 1464fcf5ef2aSThomas Huth r->element[i] = (rot_val & mask); \ 1465fcf5ef2aSThomas Huth } \ 1466fcf5ef2aSThomas Huth } \ 1467fcf5ef2aSThomas Huth } 1468fcf5ef2aSThomas Huth 1469fcf5ef2aSThomas Huth VRLMI(vrldmi, 64, u64, 1); 1470fcf5ef2aSThomas Huth VRLMI(vrlwmi, 32, u32, 1); 1471fcf5ef2aSThomas Huth VRLMI(vrldnm, 64, u64, 0); 1472fcf5ef2aSThomas Huth VRLMI(vrlwnm, 32, u32, 0); 1473fcf5ef2aSThomas Huth 1474fcf5ef2aSThomas Huth void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, 1475fcf5ef2aSThomas Huth ppc_avr_t *c) 1476fcf5ef2aSThomas Huth { 1477fcf5ef2aSThomas Huth r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]); 1478fcf5ef2aSThomas Huth r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]); 1479fcf5ef2aSThomas Huth } 1480fcf5ef2aSThomas Huth 1481fcf5ef2aSThomas Huth void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) 1482fcf5ef2aSThomas Huth { 1483fcf5ef2aSThomas Huth int i; 1484fcf5ef2aSThomas Huth 148505ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { 148605ee3e8aSMark Cave-Ayland r->f32[i] = float32_exp2(b->f32[i], &env->vec_status); 1487fcf5ef2aSThomas Huth } 1488fcf5ef2aSThomas Huth } 1489fcf5ef2aSThomas Huth 1490fcf5ef2aSThomas Huth void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) 1491fcf5ef2aSThomas Huth { 1492fcf5ef2aSThomas Huth int i; 1493fcf5ef2aSThomas Huth 149405ee3e8aSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->f32); i++) { 149505ee3e8aSMark Cave-Ayland r->f32[i] = float32_log2(b->f32[i], &env->vec_status); 1496fcf5ef2aSThomas Huth } 1497fcf5ef2aSThomas Huth } 1498fcf5ef2aSThomas Huth 149960caf221SAvinesh Kumar #define VEXTU_X_DO(name, size, left) \ 150060caf221SAvinesh Kumar target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b) \ 150160caf221SAvinesh Kumar { \ 1502f297c4c6SMatheus Ferst int index = (a & 0xf) * 8; \ 150360caf221SAvinesh Kumar if (left) { \ 1504f297c4c6SMatheus Ferst index = 128 - index - size; \ 150560caf221SAvinesh Kumar } \ 150660caf221SAvinesh Kumar return int128_getlo(int128_rshift(b->s128, index)) & \ 150760caf221SAvinesh Kumar MAKE_64BIT_MASK(0, size); \ 150860caf221SAvinesh Kumar } 150960caf221SAvinesh Kumar VEXTU_X_DO(vextublx, 8, 1) 151060caf221SAvinesh Kumar VEXTU_X_DO(vextuhlx, 16, 1) 151160caf221SAvinesh Kumar VEXTU_X_DO(vextuwlx, 32, 1) 151260caf221SAvinesh Kumar VEXTU_X_DO(vextubrx, 8, 0) 151360caf221SAvinesh Kumar VEXTU_X_DO(vextuhrx, 16, 0) 151460caf221SAvinesh Kumar VEXTU_X_DO(vextuwrx, 32, 0) 151560caf221SAvinesh Kumar #undef VEXTU_X_DO 151660caf221SAvinesh Kumar 1517fcf5ef2aSThomas Huth void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1518fcf5ef2aSThomas Huth { 1519fcf5ef2aSThomas Huth int i; 1520fcf5ef2aSThomas Huth unsigned int shift, bytes, size; 1521fcf5ef2aSThomas Huth 1522fcf5ef2aSThomas Huth size = ARRAY_SIZE(r->u8); 1523fcf5ef2aSThomas Huth for (i = 0; i < size; i++) { 152463be02fcSAnton Blanchard shift = b->VsrB(i) & 0x7; /* extract shift value */ 152563be02fcSAnton Blanchard bytes = (a->VsrB(i) << 8) + /* extract adjacent bytes */ 152663be02fcSAnton Blanchard (((i + 1) < size) ? a->VsrB(i + 1) : 0); 152763be02fcSAnton Blanchard r->VsrB(i) = (bytes << shift) >> 8; /* shift and store result */ 1528fcf5ef2aSThomas Huth } 1529fcf5ef2aSThomas Huth } 1530fcf5ef2aSThomas Huth 1531fcf5ef2aSThomas Huth void helper_vsrv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1532fcf5ef2aSThomas Huth { 1533fcf5ef2aSThomas Huth int i; 1534fcf5ef2aSThomas Huth unsigned int shift, bytes; 1535fcf5ef2aSThomas Huth 1536b6cb41b2SDavid Gibson /* 1537b6cb41b2SDavid Gibson * Use reverse order, as destination and source register can be 1538b6cb41b2SDavid Gibson * same. Its being modified in place saving temporary, reverse 1539b6cb41b2SDavid Gibson * order will guarantee that computed result is not fed back. 1540fcf5ef2aSThomas Huth */ 1541fcf5ef2aSThomas Huth for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { 154263be02fcSAnton Blanchard shift = b->VsrB(i) & 0x7; /* extract shift value */ 154363be02fcSAnton Blanchard bytes = ((i ? a->VsrB(i - 1) : 0) << 8) + a->VsrB(i); 1544fcf5ef2aSThomas Huth /* extract adjacent bytes */ 154563be02fcSAnton Blanchard r->VsrB(i) = (bytes >> shift) & 0xFF; /* shift and store result */ 1546fcf5ef2aSThomas Huth } 1547fcf5ef2aSThomas Huth } 1548fcf5ef2aSThomas Huth 1549fcf5ef2aSThomas Huth void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift) 1550fcf5ef2aSThomas Huth { 1551fcf5ef2aSThomas Huth int sh = shift & 0xf; 1552fcf5ef2aSThomas Huth int i; 1553fcf5ef2aSThomas Huth ppc_avr_t result; 1554fcf5ef2aSThomas Huth 1555fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u8); i++) { 1556fcf5ef2aSThomas Huth int index = sh + i; 1557fcf5ef2aSThomas Huth if (index > 0xf) { 155860594feaSMark Cave-Ayland result.VsrB(i) = b->VsrB(index - 0x10); 1559fcf5ef2aSThomas Huth } else { 156060594feaSMark Cave-Ayland result.VsrB(i) = a->VsrB(index); 1561fcf5ef2aSThomas Huth } 1562fcf5ef2aSThomas Huth } 1563fcf5ef2aSThomas Huth *r = result; 1564fcf5ef2aSThomas Huth } 1565fcf5ef2aSThomas Huth 1566fcf5ef2aSThomas Huth void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1567fcf5ef2aSThomas Huth { 15683c385a93SMark Cave-Ayland int sh = (b->VsrB(0xf) >> 3) & 0xf; 1569fcf5ef2aSThomas Huth 1570fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1571fcf5ef2aSThomas Huth memmove(&r->u8[0], &a->u8[sh], 16 - sh); 1572fcf5ef2aSThomas Huth memset(&r->u8[16 - sh], 0, sh); 1573fcf5ef2aSThomas Huth #else 1574fcf5ef2aSThomas Huth memmove(&r->u8[sh], &a->u8[0], 16 - sh); 1575fcf5ef2aSThomas Huth memset(&r->u8[0], 0, sh); 1576fcf5ef2aSThomas Huth #endif 1577fcf5ef2aSThomas Huth } 1578fcf5ef2aSThomas Huth 1579fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1580fcf5ef2aSThomas Huth #define VINSERT(suffix, element) \ 1581fcf5ef2aSThomas Huth void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \ 1582fcf5ef2aSThomas Huth { \ 15834fff7218SLaurent Vivier memmove(&r->u8[index], &b->u8[8 - sizeof(r->element[0])], \ 1584fcf5ef2aSThomas Huth sizeof(r->element[0])); \ 1585fcf5ef2aSThomas Huth } 1586fcf5ef2aSThomas Huth #else 1587fcf5ef2aSThomas Huth #define VINSERT(suffix, element) \ 1588fcf5ef2aSThomas Huth void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \ 1589fcf5ef2aSThomas Huth { \ 1590fcf5ef2aSThomas Huth uint32_t d = (16 - index) - sizeof(r->element[0]); \ 1591fcf5ef2aSThomas Huth memmove(&r->u8[d], &b->u8[8], sizeof(r->element[0])); \ 1592fcf5ef2aSThomas Huth } 1593fcf5ef2aSThomas Huth #endif 1594fcf5ef2aSThomas Huth VINSERT(b, u8) 1595fcf5ef2aSThomas Huth VINSERT(h, u16) 1596fcf5ef2aSThomas Huth VINSERT(w, u32) 1597fcf5ef2aSThomas Huth VINSERT(d, u64) 1598fcf5ef2aSThomas Huth #undef VINSERT 1599fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1600fcf5ef2aSThomas Huth #define VEXTRACT(suffix, element) \ 1601fcf5ef2aSThomas Huth void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \ 1602fcf5ef2aSThomas Huth { \ 1603fcf5ef2aSThomas Huth uint32_t es = sizeof(r->element[0]); \ 1604fcf5ef2aSThomas Huth memmove(&r->u8[8 - es], &b->u8[index], es); \ 1605fcf5ef2aSThomas Huth memset(&r->u8[8], 0, 8); \ 1606fcf5ef2aSThomas Huth memset(&r->u8[0], 0, 8 - es); \ 1607fcf5ef2aSThomas Huth } 1608fcf5ef2aSThomas Huth #else 1609fcf5ef2aSThomas Huth #define VEXTRACT(suffix, element) \ 1610fcf5ef2aSThomas Huth void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \ 1611fcf5ef2aSThomas Huth { \ 1612fcf5ef2aSThomas Huth uint32_t es = sizeof(r->element[0]); \ 1613fcf5ef2aSThomas Huth uint32_t s = (16 - index) - es; \ 1614fcf5ef2aSThomas Huth memmove(&r->u8[8], &b->u8[s], es); \ 1615fcf5ef2aSThomas Huth memset(&r->u8[0], 0, 8); \ 1616fcf5ef2aSThomas Huth memset(&r->u8[8 + es], 0, 8 - es); \ 1617fcf5ef2aSThomas Huth } 1618fcf5ef2aSThomas Huth #endif 1619fcf5ef2aSThomas Huth VEXTRACT(ub, u8) 1620fcf5ef2aSThomas Huth VEXTRACT(uh, u16) 1621fcf5ef2aSThomas Huth VEXTRACT(uw, u32) 1622fcf5ef2aSThomas Huth VEXTRACT(d, u64) 1623fcf5ef2aSThomas Huth #undef VEXTRACT 1624fcf5ef2aSThomas Huth 16255ba5335dSMark Cave-Ayland void helper_xxextractuw(CPUPPCState *env, ppc_vsr_t *xt, 16265ba5335dSMark Cave-Ayland ppc_vsr_t *xb, uint32_t index) 16278ad901e5SNikunj A Dadhania { 162803b32c09SMark Cave-Ayland ppc_vsr_t t = { }; 16298ad901e5SNikunj A Dadhania size_t es = sizeof(uint32_t); 16308ad901e5SNikunj A Dadhania uint32_t ext_index; 16318ad901e5SNikunj A Dadhania int i; 16328ad901e5SNikunj A Dadhania 16338ad901e5SNikunj A Dadhania ext_index = index; 16348ad901e5SNikunj A Dadhania for (i = 0; i < es; i++, ext_index++) { 163503b32c09SMark Cave-Ayland t.VsrB(8 - es + i) = xb->VsrB(ext_index % 16); 16368ad901e5SNikunj A Dadhania } 16378ad901e5SNikunj A Dadhania 163803b32c09SMark Cave-Ayland *xt = t; 16398ad901e5SNikunj A Dadhania } 16408ad901e5SNikunj A Dadhania 16415ba5335dSMark Cave-Ayland void helper_xxinsertw(CPUPPCState *env, ppc_vsr_t *xt, 16425ba5335dSMark Cave-Ayland ppc_vsr_t *xb, uint32_t index) 16433398b742SNikunj A Dadhania { 164403b32c09SMark Cave-Ayland ppc_vsr_t t = *xt; 16453398b742SNikunj A Dadhania size_t es = sizeof(uint32_t); 16463398b742SNikunj A Dadhania int ins_index, i = 0; 16473398b742SNikunj A Dadhania 16483398b742SNikunj A Dadhania ins_index = index; 16493398b742SNikunj A Dadhania for (i = 0; i < es && ins_index < 16; i++, ins_index++) { 165003b32c09SMark Cave-Ayland t.VsrB(ins_index) = xb->VsrB(8 - es + i); 16513398b742SNikunj A Dadhania } 16523398b742SNikunj A Dadhania 165303b32c09SMark Cave-Ayland *xt = t; 16543398b742SNikunj A Dadhania } 16553398b742SNikunj A Dadhania 1656634c5835SMark Cave-Ayland #define VEXT_SIGNED(name, element, cast) \ 1657fcf5ef2aSThomas Huth void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ 1658fcf5ef2aSThomas Huth { \ 1659fcf5ef2aSThomas Huth int i; \ 166060594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 1661634c5835SMark Cave-Ayland r->element[i] = (cast)b->element[i]; \ 1662fcf5ef2aSThomas Huth } \ 1663fcf5ef2aSThomas Huth } 1664634c5835SMark Cave-Ayland VEXT_SIGNED(vextsb2w, s32, int8_t) 1665634c5835SMark Cave-Ayland VEXT_SIGNED(vextsb2d, s64, int8_t) 1666634c5835SMark Cave-Ayland VEXT_SIGNED(vextsh2w, s32, int16_t) 1667634c5835SMark Cave-Ayland VEXT_SIGNED(vextsh2d, s64, int16_t) 1668634c5835SMark Cave-Ayland VEXT_SIGNED(vextsw2d, s64, int32_t) 1669fcf5ef2aSThomas Huth #undef VEXT_SIGNED 1670fcf5ef2aSThomas Huth 1671fcf5ef2aSThomas Huth #define VNEG(name, element) \ 1672fcf5ef2aSThomas Huth void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ 1673fcf5ef2aSThomas Huth { \ 1674fcf5ef2aSThomas Huth int i; \ 167560594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 1676fcf5ef2aSThomas Huth r->element[i] = -b->element[i]; \ 1677fcf5ef2aSThomas Huth } \ 1678fcf5ef2aSThomas Huth } 1679fcf5ef2aSThomas Huth VNEG(vnegw, s32) 1680fcf5ef2aSThomas Huth VNEG(vnegd, s64) 1681fcf5ef2aSThomas Huth #undef VNEG 1682fcf5ef2aSThomas Huth 1683fcf5ef2aSThomas Huth void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1684fcf5ef2aSThomas Huth { 16853c385a93SMark Cave-Ayland int sh = (b->VsrB(0xf) >> 3) & 0xf; 1686fcf5ef2aSThomas Huth 1687fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1688fcf5ef2aSThomas Huth memmove(&r->u8[sh], &a->u8[0], 16 - sh); 1689fcf5ef2aSThomas Huth memset(&r->u8[0], 0, sh); 1690fcf5ef2aSThomas Huth #else 1691fcf5ef2aSThomas Huth memmove(&r->u8[0], &a->u8[sh], 16 - sh); 1692fcf5ef2aSThomas Huth memset(&r->u8[16 - sh], 0, sh); 1693fcf5ef2aSThomas Huth #endif 1694fcf5ef2aSThomas Huth } 1695fcf5ef2aSThomas Huth 1696fcf5ef2aSThomas Huth void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1697fcf5ef2aSThomas Huth { 1698fcf5ef2aSThomas Huth int i; 1699fcf5ef2aSThomas Huth 1700fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u32); i++) { 1701fcf5ef2aSThomas Huth r->u32[i] = a->u32[i] >= b->u32[i]; 1702fcf5ef2aSThomas Huth } 1703fcf5ef2aSThomas Huth } 1704fcf5ef2aSThomas Huth 1705fcf5ef2aSThomas Huth void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1706fcf5ef2aSThomas Huth { 1707fcf5ef2aSThomas Huth int64_t t; 1708fcf5ef2aSThomas Huth int i, upper; 1709fcf5ef2aSThomas Huth ppc_avr_t result; 1710fcf5ef2aSThomas Huth int sat = 0; 1711fcf5ef2aSThomas Huth 1712fcf5ef2aSThomas Huth upper = ARRAY_SIZE(r->s32) - 1; 171360594feaSMark Cave-Ayland t = (int64_t)b->VsrSW(upper); 1714fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s32); i++) { 171560594feaSMark Cave-Ayland t += a->VsrSW(i); 171660594feaSMark Cave-Ayland result.VsrSW(i) = 0; 1717fcf5ef2aSThomas Huth } 171860594feaSMark Cave-Ayland result.VsrSW(upper) = cvtsdsw(t, &sat); 1719fcf5ef2aSThomas Huth *r = result; 1720fcf5ef2aSThomas Huth 1721fcf5ef2aSThomas Huth if (sat) { 17226175f5a0SRichard Henderson set_vscr_sat(env); 1723fcf5ef2aSThomas Huth } 1724fcf5ef2aSThomas Huth } 1725fcf5ef2aSThomas Huth 1726fcf5ef2aSThomas Huth void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1727fcf5ef2aSThomas Huth { 1728fcf5ef2aSThomas Huth int i, j, upper; 1729fcf5ef2aSThomas Huth ppc_avr_t result; 1730fcf5ef2aSThomas Huth int sat = 0; 1731fcf5ef2aSThomas Huth 1732fcf5ef2aSThomas Huth upper = 1; 1733fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u64); i++) { 173460594feaSMark Cave-Ayland int64_t t = (int64_t)b->VsrSW(upper + i * 2); 1735fcf5ef2aSThomas Huth 17367fa0ddc1SAnton Blanchard result.VsrD(i) = 0; 1737fcf5ef2aSThomas Huth for (j = 0; j < ARRAY_SIZE(r->u64); j++) { 173860594feaSMark Cave-Ayland t += a->VsrSW(2 * i + j); 1739fcf5ef2aSThomas Huth } 174060594feaSMark Cave-Ayland result.VsrSW(upper + i * 2) = cvtsdsw(t, &sat); 1741fcf5ef2aSThomas Huth } 1742fcf5ef2aSThomas Huth 1743fcf5ef2aSThomas Huth *r = result; 1744fcf5ef2aSThomas Huth if (sat) { 17456175f5a0SRichard Henderson set_vscr_sat(env); 1746fcf5ef2aSThomas Huth } 1747fcf5ef2aSThomas Huth } 1748fcf5ef2aSThomas Huth 1749fcf5ef2aSThomas Huth void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1750fcf5ef2aSThomas Huth { 1751fcf5ef2aSThomas Huth int i, j; 1752fcf5ef2aSThomas Huth int sat = 0; 1753fcf5ef2aSThomas Huth 1754fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s32); i++) { 1755fcf5ef2aSThomas Huth int64_t t = (int64_t)b->s32[i]; 1756fcf5ef2aSThomas Huth 1757fcf5ef2aSThomas Huth for (j = 0; j < ARRAY_SIZE(r->s32); j++) { 1758fcf5ef2aSThomas Huth t += a->s8[4 * i + j]; 1759fcf5ef2aSThomas Huth } 1760fcf5ef2aSThomas Huth r->s32[i] = cvtsdsw(t, &sat); 1761fcf5ef2aSThomas Huth } 1762fcf5ef2aSThomas Huth 1763fcf5ef2aSThomas Huth if (sat) { 17646175f5a0SRichard Henderson set_vscr_sat(env); 1765fcf5ef2aSThomas Huth } 1766fcf5ef2aSThomas Huth } 1767fcf5ef2aSThomas Huth 1768fcf5ef2aSThomas Huth void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1769fcf5ef2aSThomas Huth { 1770fcf5ef2aSThomas Huth int sat = 0; 1771fcf5ef2aSThomas Huth int i; 1772fcf5ef2aSThomas Huth 1773fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->s32); i++) { 1774fcf5ef2aSThomas Huth int64_t t = (int64_t)b->s32[i]; 1775fcf5ef2aSThomas Huth 1776fcf5ef2aSThomas Huth t += a->s16[2 * i] + a->s16[2 * i + 1]; 1777fcf5ef2aSThomas Huth r->s32[i] = cvtsdsw(t, &sat); 1778fcf5ef2aSThomas Huth } 1779fcf5ef2aSThomas Huth 1780fcf5ef2aSThomas Huth if (sat) { 17816175f5a0SRichard Henderson set_vscr_sat(env); 1782fcf5ef2aSThomas Huth } 1783fcf5ef2aSThomas Huth } 1784fcf5ef2aSThomas Huth 1785fcf5ef2aSThomas Huth void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1786fcf5ef2aSThomas Huth { 1787fcf5ef2aSThomas Huth int i, j; 1788fcf5ef2aSThomas Huth int sat = 0; 1789fcf5ef2aSThomas Huth 1790fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u32); i++) { 1791fcf5ef2aSThomas Huth uint64_t t = (uint64_t)b->u32[i]; 1792fcf5ef2aSThomas Huth 1793fcf5ef2aSThomas Huth for (j = 0; j < ARRAY_SIZE(r->u32); j++) { 1794fcf5ef2aSThomas Huth t += a->u8[4 * i + j]; 1795fcf5ef2aSThomas Huth } 1796fcf5ef2aSThomas Huth r->u32[i] = cvtuduw(t, &sat); 1797fcf5ef2aSThomas Huth } 1798fcf5ef2aSThomas Huth 1799fcf5ef2aSThomas Huth if (sat) { 18006175f5a0SRichard Henderson set_vscr_sat(env); 1801fcf5ef2aSThomas Huth } 1802fcf5ef2aSThomas Huth } 1803fcf5ef2aSThomas Huth 1804fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1805fcf5ef2aSThomas Huth #define UPKHI 1 1806fcf5ef2aSThomas Huth #define UPKLO 0 1807fcf5ef2aSThomas Huth #else 1808fcf5ef2aSThomas Huth #define UPKHI 0 1809fcf5ef2aSThomas Huth #define UPKLO 1 1810fcf5ef2aSThomas Huth #endif 1811fcf5ef2aSThomas Huth #define VUPKPX(suffix, hi) \ 1812fcf5ef2aSThomas Huth void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \ 1813fcf5ef2aSThomas Huth { \ 1814fcf5ef2aSThomas Huth int i; \ 1815fcf5ef2aSThomas Huth ppc_avr_t result; \ 1816fcf5ef2aSThomas Huth \ 1817fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \ 1818fcf5ef2aSThomas Huth uint16_t e = b->u16[hi ? i : i + 4]; \ 1819fcf5ef2aSThomas Huth uint8_t a = (e >> 15) ? 0xff : 0; \ 1820fcf5ef2aSThomas Huth uint8_t r = (e >> 10) & 0x1f; \ 1821fcf5ef2aSThomas Huth uint8_t g = (e >> 5) & 0x1f; \ 1822fcf5ef2aSThomas Huth uint8_t b = e & 0x1f; \ 1823fcf5ef2aSThomas Huth \ 1824fcf5ef2aSThomas Huth result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \ 1825fcf5ef2aSThomas Huth } \ 1826fcf5ef2aSThomas Huth *r = result; \ 1827fcf5ef2aSThomas Huth } 1828fcf5ef2aSThomas Huth VUPKPX(lpx, UPKLO) 1829fcf5ef2aSThomas Huth VUPKPX(hpx, UPKHI) 1830fcf5ef2aSThomas Huth #undef VUPKPX 1831fcf5ef2aSThomas Huth 1832fcf5ef2aSThomas Huth #define VUPK(suffix, unpacked, packee, hi) \ 1833fcf5ef2aSThomas Huth void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \ 1834fcf5ef2aSThomas Huth { \ 1835fcf5ef2aSThomas Huth int i; \ 1836fcf5ef2aSThomas Huth ppc_avr_t result; \ 1837fcf5ef2aSThomas Huth \ 1838fcf5ef2aSThomas Huth if (hi) { \ 1839fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) { \ 1840fcf5ef2aSThomas Huth result.unpacked[i] = b->packee[i]; \ 1841fcf5ef2aSThomas Huth } \ 1842fcf5ef2aSThomas Huth } else { \ 1843fcf5ef2aSThomas Huth for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \ 1844fcf5ef2aSThomas Huth i++) { \ 1845fcf5ef2aSThomas Huth result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \ 1846fcf5ef2aSThomas Huth } \ 1847fcf5ef2aSThomas Huth } \ 1848fcf5ef2aSThomas Huth *r = result; \ 1849fcf5ef2aSThomas Huth } 1850fcf5ef2aSThomas Huth VUPK(hsb, s16, s8, UPKHI) 1851fcf5ef2aSThomas Huth VUPK(hsh, s32, s16, UPKHI) 1852fcf5ef2aSThomas Huth VUPK(hsw, s64, s32, UPKHI) 1853fcf5ef2aSThomas Huth VUPK(lsb, s16, s8, UPKLO) 1854fcf5ef2aSThomas Huth VUPK(lsh, s32, s16, UPKLO) 1855fcf5ef2aSThomas Huth VUPK(lsw, s64, s32, UPKLO) 1856fcf5ef2aSThomas Huth #undef VUPK 1857fcf5ef2aSThomas Huth #undef UPKHI 1858fcf5ef2aSThomas Huth #undef UPKLO 1859fcf5ef2aSThomas Huth 1860fcf5ef2aSThomas Huth #define VGENERIC_DO(name, element) \ 1861fcf5ef2aSThomas Huth void helper_v##name(ppc_avr_t *r, ppc_avr_t *b) \ 1862fcf5ef2aSThomas Huth { \ 1863fcf5ef2aSThomas Huth int i; \ 1864fcf5ef2aSThomas Huth \ 186560594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ 1866fcf5ef2aSThomas Huth r->element[i] = name(b->element[i]); \ 1867fcf5ef2aSThomas Huth } \ 1868fcf5ef2aSThomas Huth } 1869fcf5ef2aSThomas Huth 1870fcf5ef2aSThomas Huth #define clzb(v) ((v) ? clz32((uint32_t)(v) << 24) : 8) 1871fcf5ef2aSThomas Huth #define clzh(v) ((v) ? clz32((uint32_t)(v) << 16) : 16) 1872fcf5ef2aSThomas Huth 1873fcf5ef2aSThomas Huth VGENERIC_DO(clzb, u8) 1874fcf5ef2aSThomas Huth VGENERIC_DO(clzh, u16) 1875fcf5ef2aSThomas Huth 1876fcf5ef2aSThomas Huth #undef clzb 1877fcf5ef2aSThomas Huth #undef clzh 1878fcf5ef2aSThomas Huth 1879fcf5ef2aSThomas Huth #define ctzb(v) ((v) ? ctz32(v) : 8) 1880fcf5ef2aSThomas Huth #define ctzh(v) ((v) ? ctz32(v) : 16) 1881fcf5ef2aSThomas Huth #define ctzw(v) ctz32((v)) 1882fcf5ef2aSThomas Huth #define ctzd(v) ctz64((v)) 1883fcf5ef2aSThomas Huth 1884fcf5ef2aSThomas Huth VGENERIC_DO(ctzb, u8) 1885fcf5ef2aSThomas Huth VGENERIC_DO(ctzh, u16) 1886fcf5ef2aSThomas Huth VGENERIC_DO(ctzw, u32) 1887fcf5ef2aSThomas Huth VGENERIC_DO(ctzd, u64) 1888fcf5ef2aSThomas Huth 1889fcf5ef2aSThomas Huth #undef ctzb 1890fcf5ef2aSThomas Huth #undef ctzh 1891fcf5ef2aSThomas Huth #undef ctzw 1892fcf5ef2aSThomas Huth #undef ctzd 1893fcf5ef2aSThomas Huth 1894fcf5ef2aSThomas Huth #define popcntb(v) ctpop8(v) 1895fcf5ef2aSThomas Huth #define popcnth(v) ctpop16(v) 1896fcf5ef2aSThomas Huth #define popcntw(v) ctpop32(v) 1897fcf5ef2aSThomas Huth #define popcntd(v) ctpop64(v) 1898fcf5ef2aSThomas Huth 1899fcf5ef2aSThomas Huth VGENERIC_DO(popcntb, u8) 1900fcf5ef2aSThomas Huth VGENERIC_DO(popcnth, u16) 1901fcf5ef2aSThomas Huth VGENERIC_DO(popcntw, u32) 1902fcf5ef2aSThomas Huth VGENERIC_DO(popcntd, u64) 1903fcf5ef2aSThomas Huth 1904fcf5ef2aSThomas Huth #undef popcntb 1905fcf5ef2aSThomas Huth #undef popcnth 1906fcf5ef2aSThomas Huth #undef popcntw 1907fcf5ef2aSThomas Huth #undef popcntd 1908fcf5ef2aSThomas Huth 1909fcf5ef2aSThomas Huth #undef VGENERIC_DO 1910fcf5ef2aSThomas Huth 1911fcf5ef2aSThomas Huth #if defined(HOST_WORDS_BIGENDIAN) 1912fcf5ef2aSThomas Huth #define QW_ONE { .u64 = { 0, 1 } } 1913fcf5ef2aSThomas Huth #else 1914fcf5ef2aSThomas Huth #define QW_ONE { .u64 = { 1, 0 } } 1915fcf5ef2aSThomas Huth #endif 1916fcf5ef2aSThomas Huth 1917fcf5ef2aSThomas Huth #ifndef CONFIG_INT128 1918fcf5ef2aSThomas Huth 1919fcf5ef2aSThomas Huth static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a) 1920fcf5ef2aSThomas Huth { 1921fcf5ef2aSThomas Huth t->u64[0] = ~a.u64[0]; 1922fcf5ef2aSThomas Huth t->u64[1] = ~a.u64[1]; 1923fcf5ef2aSThomas Huth } 1924fcf5ef2aSThomas Huth 1925fcf5ef2aSThomas Huth static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b) 1926fcf5ef2aSThomas Huth { 19273c385a93SMark Cave-Ayland if (a.VsrD(0) < b.VsrD(0)) { 1928fcf5ef2aSThomas Huth return -1; 19293c385a93SMark Cave-Ayland } else if (a.VsrD(0) > b.VsrD(0)) { 1930fcf5ef2aSThomas Huth return 1; 19313c385a93SMark Cave-Ayland } else if (a.VsrD(1) < b.VsrD(1)) { 1932fcf5ef2aSThomas Huth return -1; 19333c385a93SMark Cave-Ayland } else if (a.VsrD(1) > b.VsrD(1)) { 1934fcf5ef2aSThomas Huth return 1; 1935fcf5ef2aSThomas Huth } else { 1936fcf5ef2aSThomas Huth return 0; 1937fcf5ef2aSThomas Huth } 1938fcf5ef2aSThomas Huth } 1939fcf5ef2aSThomas Huth 1940fcf5ef2aSThomas Huth static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) 1941fcf5ef2aSThomas Huth { 19423c385a93SMark Cave-Ayland t->VsrD(1) = a.VsrD(1) + b.VsrD(1); 19433c385a93SMark Cave-Ayland t->VsrD(0) = a.VsrD(0) + b.VsrD(0) + 19443c385a93SMark Cave-Ayland (~a.VsrD(1) < b.VsrD(1)); 1945fcf5ef2aSThomas Huth } 1946fcf5ef2aSThomas Huth 1947fcf5ef2aSThomas Huth static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) 1948fcf5ef2aSThomas Huth { 1949fcf5ef2aSThomas Huth ppc_avr_t not_a; 19503c385a93SMark Cave-Ayland t->VsrD(1) = a.VsrD(1) + b.VsrD(1); 19513c385a93SMark Cave-Ayland t->VsrD(0) = a.VsrD(0) + b.VsrD(0) + 19523c385a93SMark Cave-Ayland (~a.VsrD(1) < b.VsrD(1)); 1953fcf5ef2aSThomas Huth avr_qw_not(¬_a, a); 1954fcf5ef2aSThomas Huth return avr_qw_cmpu(not_a, b) < 0; 1955fcf5ef2aSThomas Huth } 1956fcf5ef2aSThomas Huth 1957fcf5ef2aSThomas Huth #endif 1958fcf5ef2aSThomas Huth 1959fcf5ef2aSThomas Huth void helper_vadduqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1960fcf5ef2aSThomas Huth { 1961fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 1962fcf5ef2aSThomas Huth r->u128 = a->u128 + b->u128; 1963fcf5ef2aSThomas Huth #else 1964fcf5ef2aSThomas Huth avr_qw_add(r, *a, *b); 1965fcf5ef2aSThomas Huth #endif 1966fcf5ef2aSThomas Huth } 1967fcf5ef2aSThomas Huth 1968fcf5ef2aSThomas Huth void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) 1969fcf5ef2aSThomas Huth { 1970fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 1971fcf5ef2aSThomas Huth r->u128 = a->u128 + b->u128 + (c->u128 & 1); 1972fcf5ef2aSThomas Huth #else 1973fcf5ef2aSThomas Huth 19743c385a93SMark Cave-Ayland if (c->VsrD(1) & 1) { 1975fcf5ef2aSThomas Huth ppc_avr_t tmp; 1976fcf5ef2aSThomas Huth 19773c385a93SMark Cave-Ayland tmp.VsrD(0) = 0; 19783c385a93SMark Cave-Ayland tmp.VsrD(1) = c->VsrD(1) & 1; 1979fcf5ef2aSThomas Huth avr_qw_add(&tmp, *a, tmp); 1980fcf5ef2aSThomas Huth avr_qw_add(r, tmp, *b); 1981fcf5ef2aSThomas Huth } else { 1982fcf5ef2aSThomas Huth avr_qw_add(r, *a, *b); 1983fcf5ef2aSThomas Huth } 1984fcf5ef2aSThomas Huth #endif 1985fcf5ef2aSThomas Huth } 1986fcf5ef2aSThomas Huth 1987fcf5ef2aSThomas Huth void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 1988fcf5ef2aSThomas Huth { 1989fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 1990fcf5ef2aSThomas Huth r->u128 = (~a->u128 < b->u128); 1991fcf5ef2aSThomas Huth #else 1992fcf5ef2aSThomas Huth ppc_avr_t not_a; 1993fcf5ef2aSThomas Huth 1994fcf5ef2aSThomas Huth avr_qw_not(¬_a, *a); 1995fcf5ef2aSThomas Huth 19963c385a93SMark Cave-Ayland r->VsrD(0) = 0; 19973c385a93SMark Cave-Ayland r->VsrD(1) = (avr_qw_cmpu(not_a, *b) < 0); 1998fcf5ef2aSThomas Huth #endif 1999fcf5ef2aSThomas Huth } 2000fcf5ef2aSThomas Huth 2001fcf5ef2aSThomas Huth void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) 2002fcf5ef2aSThomas Huth { 2003fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 2004fcf5ef2aSThomas Huth int carry_out = (~a->u128 < b->u128); 2005fcf5ef2aSThomas Huth if (!carry_out && (c->u128 & 1)) { 2006fcf5ef2aSThomas Huth carry_out = ((a->u128 + b->u128 + 1) == 0) && 2007fcf5ef2aSThomas Huth ((a->u128 != 0) || (b->u128 != 0)); 2008fcf5ef2aSThomas Huth } 2009fcf5ef2aSThomas Huth r->u128 = carry_out; 2010fcf5ef2aSThomas Huth #else 2011fcf5ef2aSThomas Huth 20123c385a93SMark Cave-Ayland int carry_in = c->VsrD(1) & 1; 2013fcf5ef2aSThomas Huth int carry_out = 0; 2014fcf5ef2aSThomas Huth ppc_avr_t tmp; 2015fcf5ef2aSThomas Huth 2016fcf5ef2aSThomas Huth carry_out = avr_qw_addc(&tmp, *a, *b); 2017fcf5ef2aSThomas Huth 2018fcf5ef2aSThomas Huth if (!carry_out && carry_in) { 2019fcf5ef2aSThomas Huth ppc_avr_t one = QW_ONE; 2020fcf5ef2aSThomas Huth carry_out = avr_qw_addc(&tmp, tmp, one); 2021fcf5ef2aSThomas Huth } 20223c385a93SMark Cave-Ayland r->VsrD(0) = 0; 20233c385a93SMark Cave-Ayland r->VsrD(1) = carry_out; 2024fcf5ef2aSThomas Huth #endif 2025fcf5ef2aSThomas Huth } 2026fcf5ef2aSThomas Huth 2027fcf5ef2aSThomas Huth void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 2028fcf5ef2aSThomas Huth { 2029fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 2030fcf5ef2aSThomas Huth r->u128 = a->u128 - b->u128; 2031fcf5ef2aSThomas Huth #else 2032fcf5ef2aSThomas Huth ppc_avr_t tmp; 2033fcf5ef2aSThomas Huth ppc_avr_t one = QW_ONE; 2034fcf5ef2aSThomas Huth 2035fcf5ef2aSThomas Huth avr_qw_not(&tmp, *b); 2036fcf5ef2aSThomas Huth avr_qw_add(&tmp, *a, tmp); 2037fcf5ef2aSThomas Huth avr_qw_add(r, tmp, one); 2038fcf5ef2aSThomas Huth #endif 2039fcf5ef2aSThomas Huth } 2040fcf5ef2aSThomas Huth 2041fcf5ef2aSThomas Huth void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) 2042fcf5ef2aSThomas Huth { 2043fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 2044fcf5ef2aSThomas Huth r->u128 = a->u128 + ~b->u128 + (c->u128 & 1); 2045fcf5ef2aSThomas Huth #else 2046fcf5ef2aSThomas Huth ppc_avr_t tmp, sum; 2047fcf5ef2aSThomas Huth 2048fcf5ef2aSThomas Huth avr_qw_not(&tmp, *b); 2049fcf5ef2aSThomas Huth avr_qw_add(&sum, *a, tmp); 2050fcf5ef2aSThomas Huth 20513c385a93SMark Cave-Ayland tmp.VsrD(0) = 0; 20523c385a93SMark Cave-Ayland tmp.VsrD(1) = c->VsrD(1) & 1; 2053fcf5ef2aSThomas Huth avr_qw_add(r, sum, tmp); 2054fcf5ef2aSThomas Huth #endif 2055fcf5ef2aSThomas Huth } 2056fcf5ef2aSThomas Huth 2057fcf5ef2aSThomas Huth void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 2058fcf5ef2aSThomas Huth { 2059fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 2060fcf5ef2aSThomas Huth r->u128 = (~a->u128 < ~b->u128) || 2061fcf5ef2aSThomas Huth (a->u128 + ~b->u128 == (__uint128_t)-1); 2062fcf5ef2aSThomas Huth #else 2063fcf5ef2aSThomas Huth int carry = (avr_qw_cmpu(*a, *b) > 0); 2064fcf5ef2aSThomas Huth if (!carry) { 2065fcf5ef2aSThomas Huth ppc_avr_t tmp; 2066fcf5ef2aSThomas Huth avr_qw_not(&tmp, *b); 2067fcf5ef2aSThomas Huth avr_qw_add(&tmp, *a, tmp); 20683c385a93SMark Cave-Ayland carry = ((tmp.VsrSD(0) == -1ull) && (tmp.VsrSD(1) == -1ull)); 2069fcf5ef2aSThomas Huth } 20703c385a93SMark Cave-Ayland r->VsrD(0) = 0; 20713c385a93SMark Cave-Ayland r->VsrD(1) = carry; 2072fcf5ef2aSThomas Huth #endif 2073fcf5ef2aSThomas Huth } 2074fcf5ef2aSThomas Huth 2075fcf5ef2aSThomas Huth void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) 2076fcf5ef2aSThomas Huth { 2077fcf5ef2aSThomas Huth #ifdef CONFIG_INT128 2078fcf5ef2aSThomas Huth r->u128 = 2079fcf5ef2aSThomas Huth (~a->u128 < ~b->u128) || 2080fcf5ef2aSThomas Huth ((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1)); 2081fcf5ef2aSThomas Huth #else 20823c385a93SMark Cave-Ayland int carry_in = c->VsrD(1) & 1; 2083fcf5ef2aSThomas Huth int carry_out = (avr_qw_cmpu(*a, *b) > 0); 2084fcf5ef2aSThomas Huth if (!carry_out && carry_in) { 2085fcf5ef2aSThomas Huth ppc_avr_t tmp; 2086fcf5ef2aSThomas Huth avr_qw_not(&tmp, *b); 2087fcf5ef2aSThomas Huth avr_qw_add(&tmp, *a, tmp); 20883c385a93SMark Cave-Ayland carry_out = ((tmp.VsrD(0) == -1ull) && (tmp.VsrD(1) == -1ull)); 2089fcf5ef2aSThomas Huth } 2090fcf5ef2aSThomas Huth 20913c385a93SMark Cave-Ayland r->VsrD(0) = 0; 20923c385a93SMark Cave-Ayland r->VsrD(1) = carry_out; 2093fcf5ef2aSThomas Huth #endif 2094fcf5ef2aSThomas Huth } 2095fcf5ef2aSThomas Huth 2096fcf5ef2aSThomas Huth #define BCD_PLUS_PREF_1 0xC 2097fcf5ef2aSThomas Huth #define BCD_PLUS_PREF_2 0xF 2098fcf5ef2aSThomas Huth #define BCD_PLUS_ALT_1 0xA 2099fcf5ef2aSThomas Huth #define BCD_NEG_PREF 0xD 2100fcf5ef2aSThomas Huth #define BCD_NEG_ALT 0xB 2101fcf5ef2aSThomas Huth #define BCD_PLUS_ALT_2 0xE 2102fcf5ef2aSThomas Huth #define NATIONAL_PLUS 0x2B 2103fcf5ef2aSThomas Huth #define NATIONAL_NEG 0x2D 2104fcf5ef2aSThomas Huth 2105365206aeSJose Ricardo Ziviani #define BCD_DIG_BYTE(n) (15 - ((n) / 2)) 2106fcf5ef2aSThomas Huth 2107fcf5ef2aSThomas Huth static int bcd_get_sgn(ppc_avr_t *bcd) 2108fcf5ef2aSThomas Huth { 2109428115c3SMark Cave-Ayland switch (bcd->VsrB(BCD_DIG_BYTE(0)) & 0xF) { 2110fcf5ef2aSThomas Huth case BCD_PLUS_PREF_1: 2111fcf5ef2aSThomas Huth case BCD_PLUS_PREF_2: 2112fcf5ef2aSThomas Huth case BCD_PLUS_ALT_1: 2113fcf5ef2aSThomas Huth case BCD_PLUS_ALT_2: 2114fcf5ef2aSThomas Huth { 2115fcf5ef2aSThomas Huth return 1; 2116fcf5ef2aSThomas Huth } 2117fcf5ef2aSThomas Huth 2118fcf5ef2aSThomas Huth case BCD_NEG_PREF: 2119fcf5ef2aSThomas Huth case BCD_NEG_ALT: 2120fcf5ef2aSThomas Huth { 2121fcf5ef2aSThomas Huth return -1; 2122fcf5ef2aSThomas Huth } 2123fcf5ef2aSThomas Huth 2124fcf5ef2aSThomas Huth default: 2125fcf5ef2aSThomas Huth { 2126fcf5ef2aSThomas Huth return 0; 2127fcf5ef2aSThomas Huth } 2128fcf5ef2aSThomas Huth } 2129fcf5ef2aSThomas Huth } 2130fcf5ef2aSThomas Huth 2131fcf5ef2aSThomas Huth static int bcd_preferred_sgn(int sgn, int ps) 2132fcf5ef2aSThomas Huth { 2133fcf5ef2aSThomas Huth if (sgn >= 0) { 2134fcf5ef2aSThomas Huth return (ps == 0) ? BCD_PLUS_PREF_1 : BCD_PLUS_PREF_2; 2135fcf5ef2aSThomas Huth } else { 2136fcf5ef2aSThomas Huth return BCD_NEG_PREF; 2137fcf5ef2aSThomas Huth } 2138fcf5ef2aSThomas Huth } 2139fcf5ef2aSThomas Huth 2140fcf5ef2aSThomas Huth static uint8_t bcd_get_digit(ppc_avr_t *bcd, int n, int *invalid) 2141fcf5ef2aSThomas Huth { 2142fcf5ef2aSThomas Huth uint8_t result; 2143fcf5ef2aSThomas Huth if (n & 1) { 2144428115c3SMark Cave-Ayland result = bcd->VsrB(BCD_DIG_BYTE(n)) >> 4; 2145fcf5ef2aSThomas Huth } else { 2146428115c3SMark Cave-Ayland result = bcd->VsrB(BCD_DIG_BYTE(n)) & 0xF; 2147fcf5ef2aSThomas Huth } 2148fcf5ef2aSThomas Huth 2149fcf5ef2aSThomas Huth if (unlikely(result > 9)) { 2150fcf5ef2aSThomas Huth *invalid = true; 2151fcf5ef2aSThomas Huth } 2152fcf5ef2aSThomas Huth return result; 2153fcf5ef2aSThomas Huth } 2154fcf5ef2aSThomas Huth 2155fcf5ef2aSThomas Huth static void bcd_put_digit(ppc_avr_t *bcd, uint8_t digit, int n) 2156fcf5ef2aSThomas Huth { 2157fcf5ef2aSThomas Huth if (n & 1) { 2158428115c3SMark Cave-Ayland bcd->VsrB(BCD_DIG_BYTE(n)) &= 0x0F; 2159428115c3SMark Cave-Ayland bcd->VsrB(BCD_DIG_BYTE(n)) |= (digit << 4); 2160fcf5ef2aSThomas Huth } else { 2161428115c3SMark Cave-Ayland bcd->VsrB(BCD_DIG_BYTE(n)) &= 0xF0; 2162428115c3SMark Cave-Ayland bcd->VsrB(BCD_DIG_BYTE(n)) |= digit; 2163fcf5ef2aSThomas Huth } 2164fcf5ef2aSThomas Huth } 2165fcf5ef2aSThomas Huth 2166071663dfSJose Ricardo Ziviani static bool bcd_is_valid(ppc_avr_t *bcd) 2167071663dfSJose Ricardo Ziviani { 2168071663dfSJose Ricardo Ziviani int i; 2169071663dfSJose Ricardo Ziviani int invalid = 0; 2170071663dfSJose Ricardo Ziviani 2171071663dfSJose Ricardo Ziviani if (bcd_get_sgn(bcd) == 0) { 2172071663dfSJose Ricardo Ziviani return false; 2173071663dfSJose Ricardo Ziviani } 2174071663dfSJose Ricardo Ziviani 2175071663dfSJose Ricardo Ziviani for (i = 1; i < 32; i++) { 2176071663dfSJose Ricardo Ziviani bcd_get_digit(bcd, i, &invalid); 2177071663dfSJose Ricardo Ziviani if (unlikely(invalid)) { 2178071663dfSJose Ricardo Ziviani return false; 2179071663dfSJose Ricardo Ziviani } 2180071663dfSJose Ricardo Ziviani } 2181071663dfSJose Ricardo Ziviani return true; 2182071663dfSJose Ricardo Ziviani } 2183071663dfSJose Ricardo Ziviani 2184fcf5ef2aSThomas Huth static int bcd_cmp_zero(ppc_avr_t *bcd) 2185fcf5ef2aSThomas Huth { 21863c385a93SMark Cave-Ayland if (bcd->VsrD(0) == 0 && (bcd->VsrD(1) >> 4) == 0) { 2187efa73196SNikunj A Dadhania return CRF_EQ; 2188fcf5ef2aSThomas Huth } else { 2189efa73196SNikunj A Dadhania return (bcd_get_sgn(bcd) == 1) ? CRF_GT : CRF_LT; 2190fcf5ef2aSThomas Huth } 2191fcf5ef2aSThomas Huth } 2192fcf5ef2aSThomas Huth 2193fcf5ef2aSThomas Huth static uint16_t get_national_digit(ppc_avr_t *reg, int n) 2194fcf5ef2aSThomas Huth { 219560594feaSMark Cave-Ayland return reg->VsrH(7 - n); 2196fcf5ef2aSThomas Huth } 2197fcf5ef2aSThomas Huth 2198fcf5ef2aSThomas Huth static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n) 2199fcf5ef2aSThomas Huth { 220060594feaSMark Cave-Ayland reg->VsrH(7 - n) = val; 2201fcf5ef2aSThomas Huth } 2202fcf5ef2aSThomas Huth 2203fcf5ef2aSThomas Huth static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b) 2204fcf5ef2aSThomas Huth { 2205fcf5ef2aSThomas Huth int i; 2206fcf5ef2aSThomas Huth int invalid = 0; 2207fcf5ef2aSThomas Huth for (i = 31; i > 0; i--) { 2208fcf5ef2aSThomas Huth uint8_t dig_a = bcd_get_digit(a, i, &invalid); 2209fcf5ef2aSThomas Huth uint8_t dig_b = bcd_get_digit(b, i, &invalid); 2210fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2211fcf5ef2aSThomas Huth return 0; /* doesn't matter */ 2212fcf5ef2aSThomas Huth } else if (dig_a > dig_b) { 2213fcf5ef2aSThomas Huth return 1; 2214fcf5ef2aSThomas Huth } else if (dig_a < dig_b) { 2215fcf5ef2aSThomas Huth return -1; 2216fcf5ef2aSThomas Huth } 2217fcf5ef2aSThomas Huth } 2218fcf5ef2aSThomas Huth 2219fcf5ef2aSThomas Huth return 0; 2220fcf5ef2aSThomas Huth } 2221fcf5ef2aSThomas Huth 2222936fda4dSFabiano Rosas static int bcd_add_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid, 2223fcf5ef2aSThomas Huth int *overflow) 2224fcf5ef2aSThomas Huth { 2225fcf5ef2aSThomas Huth int carry = 0; 2226fcf5ef2aSThomas Huth int i; 2227936fda4dSFabiano Rosas int is_zero = 1; 2228936fda4dSFabiano Rosas 2229fcf5ef2aSThomas Huth for (i = 1; i <= 31; i++) { 2230fcf5ef2aSThomas Huth uint8_t digit = bcd_get_digit(a, i, invalid) + 2231fcf5ef2aSThomas Huth bcd_get_digit(b, i, invalid) + carry; 2232936fda4dSFabiano Rosas is_zero &= (digit == 0); 2233fcf5ef2aSThomas Huth if (digit > 9) { 2234fcf5ef2aSThomas Huth carry = 1; 2235fcf5ef2aSThomas Huth digit -= 10; 2236fcf5ef2aSThomas Huth } else { 2237fcf5ef2aSThomas Huth carry = 0; 2238fcf5ef2aSThomas Huth } 2239fcf5ef2aSThomas Huth 2240fcf5ef2aSThomas Huth bcd_put_digit(t, digit, i); 2241fcf5ef2aSThomas Huth } 2242fcf5ef2aSThomas Huth 2243fcf5ef2aSThomas Huth *overflow = carry; 2244936fda4dSFabiano Rosas return is_zero; 2245fcf5ef2aSThomas Huth } 2246fcf5ef2aSThomas Huth 2247d03b174aSYasmin Beatriz static void bcd_sub_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid, 2248fcf5ef2aSThomas Huth int *overflow) 2249fcf5ef2aSThomas Huth { 2250fcf5ef2aSThomas Huth int carry = 0; 2251fcf5ef2aSThomas Huth int i; 2252d03b174aSYasmin Beatriz 2253fcf5ef2aSThomas Huth for (i = 1; i <= 31; i++) { 2254fcf5ef2aSThomas Huth uint8_t digit = bcd_get_digit(a, i, invalid) - 2255fcf5ef2aSThomas Huth bcd_get_digit(b, i, invalid) + carry; 2256fcf5ef2aSThomas Huth if (digit & 0x80) { 2257fcf5ef2aSThomas Huth carry = -1; 2258fcf5ef2aSThomas Huth digit += 10; 2259fcf5ef2aSThomas Huth } else { 2260fcf5ef2aSThomas Huth carry = 0; 2261fcf5ef2aSThomas Huth } 2262fcf5ef2aSThomas Huth 2263fcf5ef2aSThomas Huth bcd_put_digit(t, digit, i); 2264fcf5ef2aSThomas Huth } 2265fcf5ef2aSThomas Huth 2266fcf5ef2aSThomas Huth *overflow = carry; 2267fcf5ef2aSThomas Huth } 2268fcf5ef2aSThomas Huth 2269fcf5ef2aSThomas Huth uint32_t helper_bcdadd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 2270fcf5ef2aSThomas Huth { 2271fcf5ef2aSThomas Huth 2272fcf5ef2aSThomas Huth int sgna = bcd_get_sgn(a); 2273fcf5ef2aSThomas Huth int sgnb = bcd_get_sgn(b); 2274fcf5ef2aSThomas Huth int invalid = (sgna == 0) || (sgnb == 0); 2275fcf5ef2aSThomas Huth int overflow = 0; 2276936fda4dSFabiano Rosas int zero = 0; 2277fcf5ef2aSThomas Huth uint32_t cr = 0; 2278fcf5ef2aSThomas Huth ppc_avr_t result = { .u64 = { 0, 0 } }; 2279fcf5ef2aSThomas Huth 2280fcf5ef2aSThomas Huth if (!invalid) { 2281fcf5ef2aSThomas Huth if (sgna == sgnb) { 2282428115c3SMark Cave-Ayland result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgna, ps); 2283936fda4dSFabiano Rosas zero = bcd_add_mag(&result, a, b, &invalid, &overflow); 2284936fda4dSFabiano Rosas cr = (sgna > 0) ? CRF_GT : CRF_LT; 2285fcf5ef2aSThomas Huth } else { 2286d03b174aSYasmin Beatriz int magnitude = bcd_cmp_mag(a, b); 2287d03b174aSYasmin Beatriz if (magnitude > 0) { 2288428115c3SMark Cave-Ayland result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgna, ps); 2289d03b174aSYasmin Beatriz bcd_sub_mag(&result, a, b, &invalid, &overflow); 2290d03b174aSYasmin Beatriz cr = (sgna > 0) ? CRF_GT : CRF_LT; 2291d03b174aSYasmin Beatriz } else if (magnitude < 0) { 2292428115c3SMark Cave-Ayland result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgnb, ps); 2293d03b174aSYasmin Beatriz bcd_sub_mag(&result, b, a, &invalid, &overflow); 2294efa73196SNikunj A Dadhania cr = (sgnb > 0) ? CRF_GT : CRF_LT; 2295d03b174aSYasmin Beatriz } else { 2296428115c3SMark Cave-Ayland result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(0, ps); 2297d03b174aSYasmin Beatriz cr = CRF_EQ; 2298d03b174aSYasmin Beatriz } 2299fcf5ef2aSThomas Huth } 2300fcf5ef2aSThomas Huth } 2301fcf5ef2aSThomas Huth 2302fcf5ef2aSThomas Huth if (unlikely(invalid)) { 23033c385a93SMark Cave-Ayland result.VsrD(0) = result.VsrD(1) = -1; 2304efa73196SNikunj A Dadhania cr = CRF_SO; 2305fcf5ef2aSThomas Huth } else if (overflow) { 2306efa73196SNikunj A Dadhania cr |= CRF_SO; 2307936fda4dSFabiano Rosas } else if (zero) { 2308936fda4dSFabiano Rosas cr |= CRF_EQ; 2309fcf5ef2aSThomas Huth } 2310fcf5ef2aSThomas Huth 2311fcf5ef2aSThomas Huth *r = result; 2312fcf5ef2aSThomas Huth 2313fcf5ef2aSThomas Huth return cr; 2314fcf5ef2aSThomas Huth } 2315fcf5ef2aSThomas Huth 2316fcf5ef2aSThomas Huth uint32_t helper_bcdsub(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 2317fcf5ef2aSThomas Huth { 2318fcf5ef2aSThomas Huth ppc_avr_t bcopy = *b; 2319fcf5ef2aSThomas Huth int sgnb = bcd_get_sgn(b); 2320fcf5ef2aSThomas Huth if (sgnb < 0) { 2321fcf5ef2aSThomas Huth bcd_put_digit(&bcopy, BCD_PLUS_PREF_1, 0); 2322fcf5ef2aSThomas Huth } else if (sgnb > 0) { 2323fcf5ef2aSThomas Huth bcd_put_digit(&bcopy, BCD_NEG_PREF, 0); 2324fcf5ef2aSThomas Huth } 2325fcf5ef2aSThomas Huth /* else invalid ... defer to bcdadd code for proper handling */ 2326fcf5ef2aSThomas Huth 2327fcf5ef2aSThomas Huth return helper_bcdadd(r, a, &bcopy, ps); 2328fcf5ef2aSThomas Huth } 2329fcf5ef2aSThomas Huth 2330fcf5ef2aSThomas Huth uint32_t helper_bcdcfn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2331fcf5ef2aSThomas Huth { 2332fcf5ef2aSThomas Huth int i; 2333fcf5ef2aSThomas Huth int cr = 0; 2334fcf5ef2aSThomas Huth uint16_t national = 0; 2335fcf5ef2aSThomas Huth uint16_t sgnb = get_national_digit(b, 0); 2336fcf5ef2aSThomas Huth ppc_avr_t ret = { .u64 = { 0, 0 } }; 2337fcf5ef2aSThomas Huth int invalid = (sgnb != NATIONAL_PLUS && sgnb != NATIONAL_NEG); 2338fcf5ef2aSThomas Huth 2339fcf5ef2aSThomas Huth for (i = 1; i < 8; i++) { 2340fcf5ef2aSThomas Huth national = get_national_digit(b, i); 2341fcf5ef2aSThomas Huth if (unlikely(national < 0x30 || national > 0x39)) { 2342fcf5ef2aSThomas Huth invalid = 1; 2343fcf5ef2aSThomas Huth break; 2344fcf5ef2aSThomas Huth } 2345fcf5ef2aSThomas Huth 2346fcf5ef2aSThomas Huth bcd_put_digit(&ret, national & 0xf, i); 2347fcf5ef2aSThomas Huth } 2348fcf5ef2aSThomas Huth 2349fcf5ef2aSThomas Huth if (sgnb == NATIONAL_PLUS) { 2350fcf5ef2aSThomas Huth bcd_put_digit(&ret, (ps == 0) ? BCD_PLUS_PREF_1 : BCD_PLUS_PREF_2, 0); 2351fcf5ef2aSThomas Huth } else { 2352fcf5ef2aSThomas Huth bcd_put_digit(&ret, BCD_NEG_PREF, 0); 2353fcf5ef2aSThomas Huth } 2354fcf5ef2aSThomas Huth 2355fcf5ef2aSThomas Huth cr = bcd_cmp_zero(&ret); 2356fcf5ef2aSThomas Huth 2357fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2358efa73196SNikunj A Dadhania cr = CRF_SO; 2359fcf5ef2aSThomas Huth } 2360fcf5ef2aSThomas Huth 2361fcf5ef2aSThomas Huth *r = ret; 2362fcf5ef2aSThomas Huth 2363fcf5ef2aSThomas Huth return cr; 2364fcf5ef2aSThomas Huth } 2365fcf5ef2aSThomas Huth 2366fcf5ef2aSThomas Huth uint32_t helper_bcdctn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2367fcf5ef2aSThomas Huth { 2368fcf5ef2aSThomas Huth int i; 2369fcf5ef2aSThomas Huth int cr = 0; 2370fcf5ef2aSThomas Huth int sgnb = bcd_get_sgn(b); 2371fcf5ef2aSThomas Huth int invalid = (sgnb == 0); 2372fcf5ef2aSThomas Huth ppc_avr_t ret = { .u64 = { 0, 0 } }; 2373fcf5ef2aSThomas Huth 23743c385a93SMark Cave-Ayland int ox_flag = (b->VsrD(0) != 0) || ((b->VsrD(1) >> 32) != 0); 2375fcf5ef2aSThomas Huth 2376fcf5ef2aSThomas Huth for (i = 1; i < 8; i++) { 2377fcf5ef2aSThomas Huth set_national_digit(&ret, 0x30 + bcd_get_digit(b, i, &invalid), i); 2378fcf5ef2aSThomas Huth 2379fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2380fcf5ef2aSThomas Huth break; 2381fcf5ef2aSThomas Huth } 2382fcf5ef2aSThomas Huth } 2383fcf5ef2aSThomas Huth set_national_digit(&ret, (sgnb == -1) ? NATIONAL_NEG : NATIONAL_PLUS, 0); 2384fcf5ef2aSThomas Huth 2385fcf5ef2aSThomas Huth cr = bcd_cmp_zero(b); 2386fcf5ef2aSThomas Huth 2387fcf5ef2aSThomas Huth if (ox_flag) { 2388efa73196SNikunj A Dadhania cr |= CRF_SO; 2389fcf5ef2aSThomas Huth } 2390fcf5ef2aSThomas Huth 2391fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2392efa73196SNikunj A Dadhania cr = CRF_SO; 2393fcf5ef2aSThomas Huth } 2394fcf5ef2aSThomas Huth 2395fcf5ef2aSThomas Huth *r = ret; 2396fcf5ef2aSThomas Huth 2397fcf5ef2aSThomas Huth return cr; 2398fcf5ef2aSThomas Huth } 2399fcf5ef2aSThomas Huth 2400fcf5ef2aSThomas Huth uint32_t helper_bcdcfz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2401fcf5ef2aSThomas Huth { 2402fcf5ef2aSThomas Huth int i; 2403fcf5ef2aSThomas Huth int cr = 0; 2404fcf5ef2aSThomas Huth int invalid = 0; 2405fcf5ef2aSThomas Huth int zone_digit = 0; 2406fcf5ef2aSThomas Huth int zone_lead = ps ? 0xF : 0x3; 2407fcf5ef2aSThomas Huth int digit = 0; 2408fcf5ef2aSThomas Huth ppc_avr_t ret = { .u64 = { 0, 0 } }; 2409428115c3SMark Cave-Ayland int sgnb = b->VsrB(BCD_DIG_BYTE(0)) >> 4; 2410fcf5ef2aSThomas Huth 2411fcf5ef2aSThomas Huth if (unlikely((sgnb < 0xA) && ps)) { 2412fcf5ef2aSThomas Huth invalid = 1; 2413fcf5ef2aSThomas Huth } 2414fcf5ef2aSThomas Huth 2415fcf5ef2aSThomas Huth for (i = 0; i < 16; i++) { 2416428115c3SMark Cave-Ayland zone_digit = i ? b->VsrB(BCD_DIG_BYTE(i * 2)) >> 4 : zone_lead; 2417428115c3SMark Cave-Ayland digit = b->VsrB(BCD_DIG_BYTE(i * 2)) & 0xF; 2418fcf5ef2aSThomas Huth if (unlikely(zone_digit != zone_lead || digit > 0x9)) { 2419fcf5ef2aSThomas Huth invalid = 1; 2420fcf5ef2aSThomas Huth break; 2421fcf5ef2aSThomas Huth } 2422fcf5ef2aSThomas Huth 2423fcf5ef2aSThomas Huth bcd_put_digit(&ret, digit, i + 1); 2424fcf5ef2aSThomas Huth } 2425fcf5ef2aSThomas Huth 2426fcf5ef2aSThomas Huth if ((ps && (sgnb == 0xB || sgnb == 0xD)) || 2427fcf5ef2aSThomas Huth (!ps && (sgnb & 0x4))) { 2428fcf5ef2aSThomas Huth bcd_put_digit(&ret, BCD_NEG_PREF, 0); 2429fcf5ef2aSThomas Huth } else { 2430fcf5ef2aSThomas Huth bcd_put_digit(&ret, BCD_PLUS_PREF_1, 0); 2431fcf5ef2aSThomas Huth } 2432fcf5ef2aSThomas Huth 2433fcf5ef2aSThomas Huth cr = bcd_cmp_zero(&ret); 2434fcf5ef2aSThomas Huth 2435fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2436efa73196SNikunj A Dadhania cr = CRF_SO; 2437fcf5ef2aSThomas Huth } 2438fcf5ef2aSThomas Huth 2439fcf5ef2aSThomas Huth *r = ret; 2440fcf5ef2aSThomas Huth 2441fcf5ef2aSThomas Huth return cr; 2442fcf5ef2aSThomas Huth } 2443fcf5ef2aSThomas Huth 2444fcf5ef2aSThomas Huth uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2445fcf5ef2aSThomas Huth { 2446fcf5ef2aSThomas Huth int i; 2447fcf5ef2aSThomas Huth int cr = 0; 2448fcf5ef2aSThomas Huth uint8_t digit = 0; 2449fcf5ef2aSThomas Huth int sgnb = bcd_get_sgn(b); 2450fcf5ef2aSThomas Huth int zone_lead = (ps) ? 0xF0 : 0x30; 2451fcf5ef2aSThomas Huth int invalid = (sgnb == 0); 2452fcf5ef2aSThomas Huth ppc_avr_t ret = { .u64 = { 0, 0 } }; 2453fcf5ef2aSThomas Huth 24543c385a93SMark Cave-Ayland int ox_flag = ((b->VsrD(0) >> 4) != 0); 2455fcf5ef2aSThomas Huth 2456fcf5ef2aSThomas Huth for (i = 0; i < 16; i++) { 2457fcf5ef2aSThomas Huth digit = bcd_get_digit(b, i + 1, &invalid); 2458fcf5ef2aSThomas Huth 2459fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2460fcf5ef2aSThomas Huth break; 2461fcf5ef2aSThomas Huth } 2462fcf5ef2aSThomas Huth 2463428115c3SMark Cave-Ayland ret.VsrB(BCD_DIG_BYTE(i * 2)) = zone_lead + digit; 2464fcf5ef2aSThomas Huth } 2465fcf5ef2aSThomas Huth 2466fcf5ef2aSThomas Huth if (ps) { 2467fcf5ef2aSThomas Huth bcd_put_digit(&ret, (sgnb == 1) ? 0xC : 0xD, 1); 2468fcf5ef2aSThomas Huth } else { 2469fcf5ef2aSThomas Huth bcd_put_digit(&ret, (sgnb == 1) ? 0x3 : 0x7, 1); 2470fcf5ef2aSThomas Huth } 2471fcf5ef2aSThomas Huth 2472fcf5ef2aSThomas Huth cr = bcd_cmp_zero(b); 2473fcf5ef2aSThomas Huth 2474fcf5ef2aSThomas Huth if (ox_flag) { 2475efa73196SNikunj A Dadhania cr |= CRF_SO; 2476fcf5ef2aSThomas Huth } 2477fcf5ef2aSThomas Huth 2478fcf5ef2aSThomas Huth if (unlikely(invalid)) { 2479efa73196SNikunj A Dadhania cr = CRF_SO; 2480fcf5ef2aSThomas Huth } 2481fcf5ef2aSThomas Huth 2482fcf5ef2aSThomas Huth *r = ret; 2483fcf5ef2aSThomas Huth 2484fcf5ef2aSThomas Huth return cr; 2485fcf5ef2aSThomas Huth } 2486fcf5ef2aSThomas Huth 2487a3d67f3eSLuis Pires /** 2488a3d67f3eSLuis Pires * Compare 2 128-bit unsigned integers, passed in as unsigned 64-bit pairs 2489a3d67f3eSLuis Pires * 2490a3d67f3eSLuis Pires * Returns: 2491a3d67f3eSLuis Pires * > 0 if ahi|alo > bhi|blo, 2492a3d67f3eSLuis Pires * 0 if ahi|alo == bhi|blo, 2493a3d67f3eSLuis Pires * < 0 if ahi|alo < bhi|blo 2494a3d67f3eSLuis Pires */ 2495a3d67f3eSLuis Pires static inline int ucmp128(uint64_t alo, uint64_t ahi, 2496a3d67f3eSLuis Pires uint64_t blo, uint64_t bhi) 2497a3d67f3eSLuis Pires { 2498a3d67f3eSLuis Pires return (ahi == bhi) ? 2499a3d67f3eSLuis Pires (alo > blo ? 1 : (alo == blo ? 0 : -1)) : 2500a3d67f3eSLuis Pires (ahi > bhi ? 1 : -1); 2501a3d67f3eSLuis Pires } 2502a3d67f3eSLuis Pires 2503a406c058SJose Ricardo Ziviani uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2504a406c058SJose Ricardo Ziviani { 2505a406c058SJose Ricardo Ziviani int i; 2506a3d67f3eSLuis Pires int cr; 2507a406c058SJose Ricardo Ziviani uint64_t lo_value; 2508a406c058SJose Ricardo Ziviani uint64_t hi_value; 2509*40f3e79aSLuis Pires uint64_t rem; 2510a406c058SJose Ricardo Ziviani ppc_avr_t ret = { .u64 = { 0, 0 } }; 2511a406c058SJose Ricardo Ziviani 25123c385a93SMark Cave-Ayland if (b->VsrSD(0) < 0) { 25133c385a93SMark Cave-Ayland lo_value = -b->VsrSD(1); 25143c385a93SMark Cave-Ayland hi_value = ~b->VsrD(0) + !lo_value; 2515a406c058SJose Ricardo Ziviani bcd_put_digit(&ret, 0xD, 0); 2516a3d67f3eSLuis Pires 2517a3d67f3eSLuis Pires cr = CRF_LT; 2518a406c058SJose Ricardo Ziviani } else { 25193c385a93SMark Cave-Ayland lo_value = b->VsrD(1); 25203c385a93SMark Cave-Ayland hi_value = b->VsrD(0); 2521a406c058SJose Ricardo Ziviani bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0); 2522a3d67f3eSLuis Pires 2523a3d67f3eSLuis Pires if (hi_value == 0 && lo_value == 0) { 2524a3d67f3eSLuis Pires cr = CRF_EQ; 2525a3d67f3eSLuis Pires } else { 2526a3d67f3eSLuis Pires cr = CRF_GT; 2527a3d67f3eSLuis Pires } 2528a406c058SJose Ricardo Ziviani } 2529a406c058SJose Ricardo Ziviani 2530a3d67f3eSLuis Pires /* 2531a3d67f3eSLuis Pires * Check src limits: abs(src) <= 10^31 - 1 2532a3d67f3eSLuis Pires * 2533a3d67f3eSLuis Pires * 10^31 - 1 = 0x0000007e37be2022 c0914b267fffffff 2534a3d67f3eSLuis Pires */ 2535a3d67f3eSLuis Pires if (ucmp128(lo_value, hi_value, 2536a3d67f3eSLuis Pires 0xc0914b267fffffffULL, 0x7e37be2022ULL) > 0) { 2537a3d67f3eSLuis Pires cr |= CRF_SO; 2538a3d67f3eSLuis Pires 2539a3d67f3eSLuis Pires /* 2540a3d67f3eSLuis Pires * According to the ISA, if src wouldn't fit in the destination 2541a3d67f3eSLuis Pires * register, the result is undefined. 2542a3d67f3eSLuis Pires * In that case, we leave r unchanged. 2543a3d67f3eSLuis Pires */ 2544a3d67f3eSLuis Pires } else { 2545*40f3e79aSLuis Pires rem = divu128(&lo_value, &hi_value, 1000000000000000ULL); 2546a406c058SJose Ricardo Ziviani 2547*40f3e79aSLuis Pires for (i = 1; i < 16; rem /= 10, i++) { 2548*40f3e79aSLuis Pires bcd_put_digit(&ret, rem % 10, i); 2549a406c058SJose Ricardo Ziviani } 2550a406c058SJose Ricardo Ziviani 2551a406c058SJose Ricardo Ziviani for (; i < 32; lo_value /= 10, i++) { 2552a406c058SJose Ricardo Ziviani bcd_put_digit(&ret, lo_value % 10, i); 2553a406c058SJose Ricardo Ziviani } 2554a406c058SJose Ricardo Ziviani 2555a406c058SJose Ricardo Ziviani *r = ret; 2556a3d67f3eSLuis Pires } 2557a406c058SJose Ricardo Ziviani 2558a406c058SJose Ricardo Ziviani return cr; 2559a406c058SJose Ricardo Ziviani } 2560a406c058SJose Ricardo Ziviani 2561c85bc7ddSJose Ricardo Ziviani uint32_t helper_bcdctsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2562c85bc7ddSJose Ricardo Ziviani { 2563c85bc7ddSJose Ricardo Ziviani uint8_t i; 2564c85bc7ddSJose Ricardo Ziviani int cr; 2565c85bc7ddSJose Ricardo Ziviani uint64_t carry; 2566c85bc7ddSJose Ricardo Ziviani uint64_t unused; 2567c85bc7ddSJose Ricardo Ziviani uint64_t lo_value; 2568c85bc7ddSJose Ricardo Ziviani uint64_t hi_value = 0; 2569c85bc7ddSJose Ricardo Ziviani int sgnb = bcd_get_sgn(b); 2570c85bc7ddSJose Ricardo Ziviani int invalid = (sgnb == 0); 2571c85bc7ddSJose Ricardo Ziviani 2572c85bc7ddSJose Ricardo Ziviani lo_value = bcd_get_digit(b, 31, &invalid); 2573c85bc7ddSJose Ricardo Ziviani for (i = 30; i > 0; i--) { 2574c85bc7ddSJose Ricardo Ziviani mulu64(&lo_value, &carry, lo_value, 10ULL); 2575c85bc7ddSJose Ricardo Ziviani mulu64(&hi_value, &unused, hi_value, 10ULL); 2576c85bc7ddSJose Ricardo Ziviani lo_value += bcd_get_digit(b, i, &invalid); 2577c85bc7ddSJose Ricardo Ziviani hi_value += carry; 2578c85bc7ddSJose Ricardo Ziviani 2579c85bc7ddSJose Ricardo Ziviani if (unlikely(invalid)) { 2580c85bc7ddSJose Ricardo Ziviani break; 2581c85bc7ddSJose Ricardo Ziviani } 2582c85bc7ddSJose Ricardo Ziviani } 2583c85bc7ddSJose Ricardo Ziviani 2584c85bc7ddSJose Ricardo Ziviani if (sgnb == -1) { 25853c385a93SMark Cave-Ayland r->VsrSD(1) = -lo_value; 25863c385a93SMark Cave-Ayland r->VsrSD(0) = ~hi_value + !r->VsrSD(1); 2587c85bc7ddSJose Ricardo Ziviani } else { 25883c385a93SMark Cave-Ayland r->VsrSD(1) = lo_value; 25893c385a93SMark Cave-Ayland r->VsrSD(0) = hi_value; 2590c85bc7ddSJose Ricardo Ziviani } 2591c85bc7ddSJose Ricardo Ziviani 2592c85bc7ddSJose Ricardo Ziviani cr = bcd_cmp_zero(b); 2593c85bc7ddSJose Ricardo Ziviani 2594c85bc7ddSJose Ricardo Ziviani if (unlikely(invalid)) { 2595c85bc7ddSJose Ricardo Ziviani cr = CRF_SO; 2596c85bc7ddSJose Ricardo Ziviani } 2597c85bc7ddSJose Ricardo Ziviani 2598c85bc7ddSJose Ricardo Ziviani return cr; 2599c85bc7ddSJose Ricardo Ziviani } 2600c85bc7ddSJose Ricardo Ziviani 2601c3025c3bSJose Ricardo Ziviani uint32_t helper_bcdcpsgn(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 2602c3025c3bSJose Ricardo Ziviani { 2603c3025c3bSJose Ricardo Ziviani int i; 2604c3025c3bSJose Ricardo Ziviani int invalid = 0; 2605c3025c3bSJose Ricardo Ziviani 2606c3025c3bSJose Ricardo Ziviani if (bcd_get_sgn(a) == 0 || bcd_get_sgn(b) == 0) { 2607c3025c3bSJose Ricardo Ziviani return CRF_SO; 2608c3025c3bSJose Ricardo Ziviani } 2609c3025c3bSJose Ricardo Ziviani 2610c3025c3bSJose Ricardo Ziviani *r = *a; 2611428115c3SMark Cave-Ayland bcd_put_digit(r, b->VsrB(BCD_DIG_BYTE(0)) & 0xF, 0); 2612c3025c3bSJose Ricardo Ziviani 2613c3025c3bSJose Ricardo Ziviani for (i = 1; i < 32; i++) { 2614c3025c3bSJose Ricardo Ziviani bcd_get_digit(a, i, &invalid); 2615c3025c3bSJose Ricardo Ziviani bcd_get_digit(b, i, &invalid); 2616c3025c3bSJose Ricardo Ziviani if (unlikely(invalid)) { 2617c3025c3bSJose Ricardo Ziviani return CRF_SO; 2618c3025c3bSJose Ricardo Ziviani } 2619c3025c3bSJose Ricardo Ziviani } 2620c3025c3bSJose Ricardo Ziviani 2621c3025c3bSJose Ricardo Ziviani return bcd_cmp_zero(r); 2622c3025c3bSJose Ricardo Ziviani } 2623c3025c3bSJose Ricardo Ziviani 2624466a3f9cSJose Ricardo Ziviani uint32_t helper_bcdsetsgn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps) 2625466a3f9cSJose Ricardo Ziviani { 2626466a3f9cSJose Ricardo Ziviani int sgnb = bcd_get_sgn(b); 2627466a3f9cSJose Ricardo Ziviani 2628466a3f9cSJose Ricardo Ziviani *r = *b; 2629466a3f9cSJose Ricardo Ziviani bcd_put_digit(r, bcd_preferred_sgn(sgnb, ps), 0); 2630466a3f9cSJose Ricardo Ziviani 2631071663dfSJose Ricardo Ziviani if (bcd_is_valid(b) == false) { 2632466a3f9cSJose Ricardo Ziviani return CRF_SO; 2633466a3f9cSJose Ricardo Ziviani } 2634466a3f9cSJose Ricardo Ziviani 2635466a3f9cSJose Ricardo Ziviani return bcd_cmp_zero(r); 2636466a3f9cSJose Ricardo Ziviani } 2637466a3f9cSJose Ricardo Ziviani 2638e04797f7SJose Ricardo Ziviani uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 2639e04797f7SJose Ricardo Ziviani { 2640e04797f7SJose Ricardo Ziviani int cr; 2641428115c3SMark Cave-Ayland int i = a->VsrSB(7); 2642e04797f7SJose Ricardo Ziviani bool ox_flag = false; 2643e04797f7SJose Ricardo Ziviani int sgnb = bcd_get_sgn(b); 2644e04797f7SJose Ricardo Ziviani ppc_avr_t ret = *b; 26453c385a93SMark Cave-Ayland ret.VsrD(1) &= ~0xf; 2646e04797f7SJose Ricardo Ziviani 2647e04797f7SJose Ricardo Ziviani if (bcd_is_valid(b) == false) { 2648e04797f7SJose Ricardo Ziviani return CRF_SO; 2649e04797f7SJose Ricardo Ziviani } 2650e04797f7SJose Ricardo Ziviani 2651e04797f7SJose Ricardo Ziviani if (unlikely(i > 31)) { 2652e04797f7SJose Ricardo Ziviani i = 31; 2653e04797f7SJose Ricardo Ziviani } else if (unlikely(i < -31)) { 2654e04797f7SJose Ricardo Ziviani i = -31; 2655e04797f7SJose Ricardo Ziviani } 2656e04797f7SJose Ricardo Ziviani 2657e04797f7SJose Ricardo Ziviani if (i > 0) { 26583c385a93SMark Cave-Ayland ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag); 2659e04797f7SJose Ricardo Ziviani } else { 26603c385a93SMark Cave-Ayland urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4); 2661e04797f7SJose Ricardo Ziviani } 2662e04797f7SJose Ricardo Ziviani bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0); 2663e04797f7SJose Ricardo Ziviani 2664e04797f7SJose Ricardo Ziviani *r = ret; 2665e04797f7SJose Ricardo Ziviani 2666e04797f7SJose Ricardo Ziviani cr = bcd_cmp_zero(r); 2667e04797f7SJose Ricardo Ziviani if (ox_flag) { 2668e04797f7SJose Ricardo Ziviani cr |= CRF_SO; 2669e04797f7SJose Ricardo Ziviani } 2670e04797f7SJose Ricardo Ziviani 2671e04797f7SJose Ricardo Ziviani return cr; 2672e04797f7SJose Ricardo Ziviani } 2673e04797f7SJose Ricardo Ziviani 2674a49a95e9SJose Ricardo Ziviani uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 2675a49a95e9SJose Ricardo Ziviani { 2676a49a95e9SJose Ricardo Ziviani int cr; 2677a49a95e9SJose Ricardo Ziviani int i; 2678a49a95e9SJose Ricardo Ziviani int invalid = 0; 2679a49a95e9SJose Ricardo Ziviani bool ox_flag = false; 2680a49a95e9SJose Ricardo Ziviani ppc_avr_t ret = *b; 2681a49a95e9SJose Ricardo Ziviani 2682a49a95e9SJose Ricardo Ziviani for (i = 0; i < 32; i++) { 2683a49a95e9SJose Ricardo Ziviani bcd_get_digit(b, i, &invalid); 2684a49a95e9SJose Ricardo Ziviani 2685a49a95e9SJose Ricardo Ziviani if (unlikely(invalid)) { 2686a49a95e9SJose Ricardo Ziviani return CRF_SO; 2687a49a95e9SJose Ricardo Ziviani } 2688a49a95e9SJose Ricardo Ziviani } 2689a49a95e9SJose Ricardo Ziviani 2690428115c3SMark Cave-Ayland i = a->VsrSB(7); 2691a49a95e9SJose Ricardo Ziviani if (i >= 32) { 2692a49a95e9SJose Ricardo Ziviani ox_flag = true; 26933c385a93SMark Cave-Ayland ret.VsrD(1) = ret.VsrD(0) = 0; 2694a49a95e9SJose Ricardo Ziviani } else if (i <= -32) { 26953c385a93SMark Cave-Ayland ret.VsrD(1) = ret.VsrD(0) = 0; 2696a49a95e9SJose Ricardo Ziviani } else if (i > 0) { 26973c385a93SMark Cave-Ayland ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag); 2698a49a95e9SJose Ricardo Ziviani } else { 26993c385a93SMark Cave-Ayland urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4); 2700a49a95e9SJose Ricardo Ziviani } 2701a49a95e9SJose Ricardo Ziviani *r = ret; 2702a49a95e9SJose Ricardo Ziviani 2703a49a95e9SJose Ricardo Ziviani cr = bcd_cmp_zero(r); 2704a49a95e9SJose Ricardo Ziviani if (ox_flag) { 2705a49a95e9SJose Ricardo Ziviani cr |= CRF_SO; 2706a49a95e9SJose Ricardo Ziviani } 2707a49a95e9SJose Ricardo Ziviani 2708a49a95e9SJose Ricardo Ziviani return cr; 2709a49a95e9SJose Ricardo Ziviani } 2710a49a95e9SJose Ricardo Ziviani 2711a54238adSJose Ricardo Ziviani uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 2712a54238adSJose Ricardo Ziviani { 2713a54238adSJose Ricardo Ziviani int cr; 2714a54238adSJose Ricardo Ziviani int unused = 0; 2715a54238adSJose Ricardo Ziviani int invalid = 0; 2716a54238adSJose Ricardo Ziviani bool ox_flag = false; 2717a54238adSJose Ricardo Ziviani int sgnb = bcd_get_sgn(b); 2718a54238adSJose Ricardo Ziviani ppc_avr_t ret = *b; 27193c385a93SMark Cave-Ayland ret.VsrD(1) &= ~0xf; 2720a54238adSJose Ricardo Ziviani 2721428115c3SMark Cave-Ayland int i = a->VsrSB(7); 2722428115c3SMark Cave-Ayland ppc_avr_t bcd_one; 2723428115c3SMark Cave-Ayland 2724428115c3SMark Cave-Ayland bcd_one.VsrD(0) = 0; 2725428115c3SMark Cave-Ayland bcd_one.VsrD(1) = 0x10; 2726a54238adSJose Ricardo Ziviani 2727a54238adSJose Ricardo Ziviani if (bcd_is_valid(b) == false) { 2728a54238adSJose Ricardo Ziviani return CRF_SO; 2729a54238adSJose Ricardo Ziviani } 2730a54238adSJose Ricardo Ziviani 2731a54238adSJose Ricardo Ziviani if (unlikely(i > 31)) { 2732a54238adSJose Ricardo Ziviani i = 31; 2733a54238adSJose Ricardo Ziviani } else if (unlikely(i < -31)) { 2734a54238adSJose Ricardo Ziviani i = -31; 2735a54238adSJose Ricardo Ziviani } 2736a54238adSJose Ricardo Ziviani 2737a54238adSJose Ricardo Ziviani if (i > 0) { 27383c385a93SMark Cave-Ayland ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag); 2739a54238adSJose Ricardo Ziviani } else { 27403c385a93SMark Cave-Ayland urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4); 2741a54238adSJose Ricardo Ziviani 2742a54238adSJose Ricardo Ziviani if (bcd_get_digit(&ret, 0, &invalid) >= 5) { 2743a54238adSJose Ricardo Ziviani bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused); 2744a54238adSJose Ricardo Ziviani } 2745a54238adSJose Ricardo Ziviani } 2746a54238adSJose Ricardo Ziviani bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0); 2747a54238adSJose Ricardo Ziviani 2748a54238adSJose Ricardo Ziviani cr = bcd_cmp_zero(&ret); 2749a54238adSJose Ricardo Ziviani if (ox_flag) { 2750a54238adSJose Ricardo Ziviani cr |= CRF_SO; 2751a54238adSJose Ricardo Ziviani } 2752a54238adSJose Ricardo Ziviani *r = ret; 2753a54238adSJose Ricardo Ziviani 2754a54238adSJose Ricardo Ziviani return cr; 2755a54238adSJose Ricardo Ziviani } 2756a54238adSJose Ricardo Ziviani 275731bc4d11SJose Ricardo Ziviani uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 275831bc4d11SJose Ricardo Ziviani { 275931bc4d11SJose Ricardo Ziviani uint64_t mask; 276031bc4d11SJose Ricardo Ziviani uint32_t ox_flag = 0; 2761428115c3SMark Cave-Ayland int i = a->VsrSH(3) + 1; 276231bc4d11SJose Ricardo Ziviani ppc_avr_t ret = *b; 276331bc4d11SJose Ricardo Ziviani 276431bc4d11SJose Ricardo Ziviani if (bcd_is_valid(b) == false) { 276531bc4d11SJose Ricardo Ziviani return CRF_SO; 276631bc4d11SJose Ricardo Ziviani } 276731bc4d11SJose Ricardo Ziviani 276831bc4d11SJose Ricardo Ziviani if (i > 16 && i < 32) { 276931bc4d11SJose Ricardo Ziviani mask = (uint64_t)-1 >> (128 - i * 4); 27703c385a93SMark Cave-Ayland if (ret.VsrD(0) & ~mask) { 277131bc4d11SJose Ricardo Ziviani ox_flag = CRF_SO; 277231bc4d11SJose Ricardo Ziviani } 277331bc4d11SJose Ricardo Ziviani 27743c385a93SMark Cave-Ayland ret.VsrD(0) &= mask; 277531bc4d11SJose Ricardo Ziviani } else if (i >= 0 && i <= 16) { 277631bc4d11SJose Ricardo Ziviani mask = (uint64_t)-1 >> (64 - i * 4); 27773c385a93SMark Cave-Ayland if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) { 277831bc4d11SJose Ricardo Ziviani ox_flag = CRF_SO; 277931bc4d11SJose Ricardo Ziviani } 278031bc4d11SJose Ricardo Ziviani 27813c385a93SMark Cave-Ayland ret.VsrD(1) &= mask; 27823c385a93SMark Cave-Ayland ret.VsrD(0) = 0; 278331bc4d11SJose Ricardo Ziviani } 278431bc4d11SJose Ricardo Ziviani bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0); 278531bc4d11SJose Ricardo Ziviani *r = ret; 278631bc4d11SJose Ricardo Ziviani 278731bc4d11SJose Ricardo Ziviani return bcd_cmp_zero(&ret) | ox_flag; 278831bc4d11SJose Ricardo Ziviani } 278931bc4d11SJose Ricardo Ziviani 27905c32e2e4SJose Ricardo Ziviani uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) 27915c32e2e4SJose Ricardo Ziviani { 27925c32e2e4SJose Ricardo Ziviani int i; 27935c32e2e4SJose Ricardo Ziviani uint64_t mask; 27945c32e2e4SJose Ricardo Ziviani uint32_t ox_flag = 0; 27955c32e2e4SJose Ricardo Ziviani int invalid = 0; 27965c32e2e4SJose Ricardo Ziviani ppc_avr_t ret = *b; 27975c32e2e4SJose Ricardo Ziviani 27985c32e2e4SJose Ricardo Ziviani for (i = 0; i < 32; i++) { 27995c32e2e4SJose Ricardo Ziviani bcd_get_digit(b, i, &invalid); 28005c32e2e4SJose Ricardo Ziviani 28015c32e2e4SJose Ricardo Ziviani if (unlikely(invalid)) { 28025c32e2e4SJose Ricardo Ziviani return CRF_SO; 28035c32e2e4SJose Ricardo Ziviani } 28045c32e2e4SJose Ricardo Ziviani } 28055c32e2e4SJose Ricardo Ziviani 2806428115c3SMark Cave-Ayland i = a->VsrSH(3); 28075c32e2e4SJose Ricardo Ziviani if (i > 16 && i < 33) { 28085c32e2e4SJose Ricardo Ziviani mask = (uint64_t)-1 >> (128 - i * 4); 28093c385a93SMark Cave-Ayland if (ret.VsrD(0) & ~mask) { 28105c32e2e4SJose Ricardo Ziviani ox_flag = CRF_SO; 28115c32e2e4SJose Ricardo Ziviani } 28125c32e2e4SJose Ricardo Ziviani 28133c385a93SMark Cave-Ayland ret.VsrD(0) &= mask; 28145c32e2e4SJose Ricardo Ziviani } else if (i > 0 && i <= 16) { 28155c32e2e4SJose Ricardo Ziviani mask = (uint64_t)-1 >> (64 - i * 4); 28163c385a93SMark Cave-Ayland if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) { 28175c32e2e4SJose Ricardo Ziviani ox_flag = CRF_SO; 28185c32e2e4SJose Ricardo Ziviani } 28195c32e2e4SJose Ricardo Ziviani 28203c385a93SMark Cave-Ayland ret.VsrD(1) &= mask; 28213c385a93SMark Cave-Ayland ret.VsrD(0) = 0; 28225c32e2e4SJose Ricardo Ziviani } else if (i == 0) { 28233c385a93SMark Cave-Ayland if (ret.VsrD(0) || ret.VsrD(1)) { 28245c32e2e4SJose Ricardo Ziviani ox_flag = CRF_SO; 28255c32e2e4SJose Ricardo Ziviani } 28263c385a93SMark Cave-Ayland ret.VsrD(0) = ret.VsrD(1) = 0; 28275c32e2e4SJose Ricardo Ziviani } 28285c32e2e4SJose Ricardo Ziviani 28295c32e2e4SJose Ricardo Ziviani *r = ret; 28303c385a93SMark Cave-Ayland if (r->VsrD(0) == 0 && r->VsrD(1) == 0) { 28315c32e2e4SJose Ricardo Ziviani return ox_flag | CRF_EQ; 28325c32e2e4SJose Ricardo Ziviani } 28335c32e2e4SJose Ricardo Ziviani 28345c32e2e4SJose Ricardo Ziviani return ox_flag | CRF_GT; 28355c32e2e4SJose Ricardo Ziviani } 28365c32e2e4SJose Ricardo Ziviani 2837fcf5ef2aSThomas Huth void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a) 2838fcf5ef2aSThomas Huth { 2839fcf5ef2aSThomas Huth int i; 2840fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u8) { 2841fcf5ef2aSThomas Huth r->u8[i] = AES_sbox[a->u8[i]]; 2842fcf5ef2aSThomas Huth } 2843fcf5ef2aSThomas Huth } 2844fcf5ef2aSThomas Huth 2845fcf5ef2aSThomas Huth void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 2846fcf5ef2aSThomas Huth { 2847fcf5ef2aSThomas Huth ppc_avr_t result; 2848fcf5ef2aSThomas Huth int i; 2849fcf5ef2aSThomas Huth 2850fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u32) { 28512dea57dbSMark Cave-Ayland result.VsrW(i) = b->VsrW(i) ^ 28522dea57dbSMark Cave-Ayland (AES_Te0[a->VsrB(AES_shifts[4 * i + 0])] ^ 28532dea57dbSMark Cave-Ayland AES_Te1[a->VsrB(AES_shifts[4 * i + 1])] ^ 28542dea57dbSMark Cave-Ayland AES_Te2[a->VsrB(AES_shifts[4 * i + 2])] ^ 28552dea57dbSMark Cave-Ayland AES_Te3[a->VsrB(AES_shifts[4 * i + 3])]); 2856fcf5ef2aSThomas Huth } 2857fcf5ef2aSThomas Huth *r = result; 2858fcf5ef2aSThomas Huth } 2859fcf5ef2aSThomas Huth 2860fcf5ef2aSThomas Huth void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 2861fcf5ef2aSThomas Huth { 2862fcf5ef2aSThomas Huth ppc_avr_t result; 2863fcf5ef2aSThomas Huth int i; 2864fcf5ef2aSThomas Huth 2865fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u8) { 28662dea57dbSMark Cave-Ayland result.VsrB(i) = b->VsrB(i) ^ (AES_sbox[a->VsrB(AES_shifts[i])]); 2867fcf5ef2aSThomas Huth } 2868fcf5ef2aSThomas Huth *r = result; 2869fcf5ef2aSThomas Huth } 2870fcf5ef2aSThomas Huth 2871fcf5ef2aSThomas Huth void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 2872fcf5ef2aSThomas Huth { 2873fcf5ef2aSThomas Huth /* This differs from what is written in ISA V2.07. The RTL is */ 2874fcf5ef2aSThomas Huth /* incorrect and will be fixed in V2.07B. */ 2875fcf5ef2aSThomas Huth int i; 2876fcf5ef2aSThomas Huth ppc_avr_t tmp; 2877fcf5ef2aSThomas Huth 2878fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u8) { 28792dea57dbSMark Cave-Ayland tmp.VsrB(i) = b->VsrB(i) ^ AES_isbox[a->VsrB(AES_ishifts[i])]; 2880fcf5ef2aSThomas Huth } 2881fcf5ef2aSThomas Huth 2882fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u32) { 28832dea57dbSMark Cave-Ayland r->VsrW(i) = 28842dea57dbSMark Cave-Ayland AES_imc[tmp.VsrB(4 * i + 0)][0] ^ 28852dea57dbSMark Cave-Ayland AES_imc[tmp.VsrB(4 * i + 1)][1] ^ 28862dea57dbSMark Cave-Ayland AES_imc[tmp.VsrB(4 * i + 2)][2] ^ 28872dea57dbSMark Cave-Ayland AES_imc[tmp.VsrB(4 * i + 3)][3]; 2888fcf5ef2aSThomas Huth } 2889fcf5ef2aSThomas Huth } 2890fcf5ef2aSThomas Huth 2891fcf5ef2aSThomas Huth void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) 2892fcf5ef2aSThomas Huth { 2893fcf5ef2aSThomas Huth ppc_avr_t result; 2894fcf5ef2aSThomas Huth int i; 2895fcf5ef2aSThomas Huth 2896fcf5ef2aSThomas Huth VECTOR_FOR_INORDER_I(i, u8) { 28972dea57dbSMark Cave-Ayland result.VsrB(i) = b->VsrB(i) ^ (AES_isbox[a->VsrB(AES_ishifts[i])]); 2898fcf5ef2aSThomas Huth } 2899fcf5ef2aSThomas Huth *r = result; 2900fcf5ef2aSThomas Huth } 2901fcf5ef2aSThomas Huth 2902fcf5ef2aSThomas Huth void helper_vshasigmaw(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) 2903fcf5ef2aSThomas Huth { 2904fcf5ef2aSThomas Huth int st = (st_six & 0x10) != 0; 2905fcf5ef2aSThomas Huth int six = st_six & 0xF; 2906fcf5ef2aSThomas Huth int i; 2907fcf5ef2aSThomas Huth 2908730d2ca3SMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->u32); i++) { 2909fcf5ef2aSThomas Huth if (st == 0) { 2910fcf5ef2aSThomas Huth if ((six & (0x8 >> i)) == 0) { 29110ef83bf2SMark Cave-Ayland r->VsrW(i) = ror32(a->VsrW(i), 7) ^ 29120ef83bf2SMark Cave-Ayland ror32(a->VsrW(i), 18) ^ 2913730d2ca3SMark Cave-Ayland (a->VsrW(i) >> 3); 2914fcf5ef2aSThomas Huth } else { /* six.bit[i] == 1 */ 29150ef83bf2SMark Cave-Ayland r->VsrW(i) = ror32(a->VsrW(i), 17) ^ 29160ef83bf2SMark Cave-Ayland ror32(a->VsrW(i), 19) ^ 2917730d2ca3SMark Cave-Ayland (a->VsrW(i) >> 10); 2918fcf5ef2aSThomas Huth } 2919fcf5ef2aSThomas Huth } else { /* st == 1 */ 2920fcf5ef2aSThomas Huth if ((six & (0x8 >> i)) == 0) { 29210ef83bf2SMark Cave-Ayland r->VsrW(i) = ror32(a->VsrW(i), 2) ^ 29220ef83bf2SMark Cave-Ayland ror32(a->VsrW(i), 13) ^ 29230ef83bf2SMark Cave-Ayland ror32(a->VsrW(i), 22); 2924fcf5ef2aSThomas Huth } else { /* six.bit[i] == 1 */ 29250ef83bf2SMark Cave-Ayland r->VsrW(i) = ror32(a->VsrW(i), 6) ^ 29260ef83bf2SMark Cave-Ayland ror32(a->VsrW(i), 11) ^ 29270ef83bf2SMark Cave-Ayland ror32(a->VsrW(i), 25); 2928fcf5ef2aSThomas Huth } 2929fcf5ef2aSThomas Huth } 2930fcf5ef2aSThomas Huth } 2931fcf5ef2aSThomas Huth } 2932fcf5ef2aSThomas Huth 2933fcf5ef2aSThomas Huth void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) 2934fcf5ef2aSThomas Huth { 2935fcf5ef2aSThomas Huth int st = (st_six & 0x10) != 0; 2936fcf5ef2aSThomas Huth int six = st_six & 0xF; 2937fcf5ef2aSThomas Huth int i; 2938fcf5ef2aSThomas Huth 2939730d2ca3SMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->u64); i++) { 2940fcf5ef2aSThomas Huth if (st == 0) { 2941fcf5ef2aSThomas Huth if ((six & (0x8 >> (2 * i))) == 0) { 29420ef83bf2SMark Cave-Ayland r->VsrD(i) = ror64(a->VsrD(i), 1) ^ 29430ef83bf2SMark Cave-Ayland ror64(a->VsrD(i), 8) ^ 2944730d2ca3SMark Cave-Ayland (a->VsrD(i) >> 7); 2945fcf5ef2aSThomas Huth } else { /* six.bit[2*i] == 1 */ 29460ef83bf2SMark Cave-Ayland r->VsrD(i) = ror64(a->VsrD(i), 19) ^ 29470ef83bf2SMark Cave-Ayland ror64(a->VsrD(i), 61) ^ 2948730d2ca3SMark Cave-Ayland (a->VsrD(i) >> 6); 2949fcf5ef2aSThomas Huth } 2950fcf5ef2aSThomas Huth } else { /* st == 1 */ 2951fcf5ef2aSThomas Huth if ((six & (0x8 >> (2 * i))) == 0) { 29520ef83bf2SMark Cave-Ayland r->VsrD(i) = ror64(a->VsrD(i), 28) ^ 29530ef83bf2SMark Cave-Ayland ror64(a->VsrD(i), 34) ^ 29540ef83bf2SMark Cave-Ayland ror64(a->VsrD(i), 39); 2955fcf5ef2aSThomas Huth } else { /* six.bit[2*i] == 1 */ 29560ef83bf2SMark Cave-Ayland r->VsrD(i) = ror64(a->VsrD(i), 14) ^ 29570ef83bf2SMark Cave-Ayland ror64(a->VsrD(i), 18) ^ 29580ef83bf2SMark Cave-Ayland ror64(a->VsrD(i), 41); 2959fcf5ef2aSThomas Huth } 2960fcf5ef2aSThomas Huth } 2961fcf5ef2aSThomas Huth } 2962fcf5ef2aSThomas Huth } 2963fcf5ef2aSThomas Huth 2964fcf5ef2aSThomas Huth void helper_vpermxor(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) 2965fcf5ef2aSThomas Huth { 2966fcf5ef2aSThomas Huth ppc_avr_t result; 2967fcf5ef2aSThomas Huth int i; 2968fcf5ef2aSThomas Huth 296960594feaSMark Cave-Ayland for (i = 0; i < ARRAY_SIZE(r->u8); i++) { 297060594feaSMark Cave-Ayland int indexA = c->VsrB(i) >> 4; 297160594feaSMark Cave-Ayland int indexB = c->VsrB(i) & 0xF; 297260594feaSMark Cave-Ayland 297360594feaSMark Cave-Ayland result.VsrB(i) = a->VsrB(indexA) ^ b->VsrB(indexB); 2974fcf5ef2aSThomas Huth } 2975fcf5ef2aSThomas Huth *r = result; 2976fcf5ef2aSThomas Huth } 2977fcf5ef2aSThomas Huth 2978fcf5ef2aSThomas Huth #undef VECTOR_FOR_INORDER_I 2979fcf5ef2aSThomas Huth 2980fcf5ef2aSThomas Huth /*****************************************************************************/ 2981fcf5ef2aSThomas Huth /* SPE extension helpers */ 2982fcf5ef2aSThomas Huth /* Use a table to make this quicker */ 2983fcf5ef2aSThomas Huth static const uint8_t hbrev[16] = { 2984fcf5ef2aSThomas Huth 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 2985fcf5ef2aSThomas Huth 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF, 2986fcf5ef2aSThomas Huth }; 2987fcf5ef2aSThomas Huth 2988fcf5ef2aSThomas Huth static inline uint8_t byte_reverse(uint8_t val) 2989fcf5ef2aSThomas Huth { 2990fcf5ef2aSThomas Huth return hbrev[val >> 4] | (hbrev[val & 0xF] << 4); 2991fcf5ef2aSThomas Huth } 2992fcf5ef2aSThomas Huth 2993fcf5ef2aSThomas Huth static inline uint32_t word_reverse(uint32_t val) 2994fcf5ef2aSThomas Huth { 2995fcf5ef2aSThomas Huth return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) | 2996fcf5ef2aSThomas Huth (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24); 2997fcf5ef2aSThomas Huth } 2998fcf5ef2aSThomas Huth 2999fcf5ef2aSThomas Huth #define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */ 3000fcf5ef2aSThomas Huth target_ulong helper_brinc(target_ulong arg1, target_ulong arg2) 3001fcf5ef2aSThomas Huth { 3002fcf5ef2aSThomas Huth uint32_t a, b, d, mask; 3003fcf5ef2aSThomas Huth 3004fcf5ef2aSThomas Huth mask = UINT32_MAX >> (32 - MASKBITS); 3005fcf5ef2aSThomas Huth a = arg1 & mask; 3006fcf5ef2aSThomas Huth b = arg2 & mask; 3007fcf5ef2aSThomas Huth d = word_reverse(1 + word_reverse(a | ~b)); 3008fcf5ef2aSThomas Huth return (arg1 & ~mask) | (d & b); 3009fcf5ef2aSThomas Huth } 3010fcf5ef2aSThomas Huth 3011fcf5ef2aSThomas Huth uint32_t helper_cntlsw32(uint32_t val) 3012fcf5ef2aSThomas Huth { 3013fcf5ef2aSThomas Huth if (val & 0x80000000) { 3014fcf5ef2aSThomas Huth return clz32(~val); 3015fcf5ef2aSThomas Huth } else { 3016fcf5ef2aSThomas Huth return clz32(val); 3017fcf5ef2aSThomas Huth } 3018fcf5ef2aSThomas Huth } 3019fcf5ef2aSThomas Huth 3020fcf5ef2aSThomas Huth uint32_t helper_cntlzw32(uint32_t val) 3021fcf5ef2aSThomas Huth { 3022fcf5ef2aSThomas Huth return clz32(val); 3023fcf5ef2aSThomas Huth } 3024fcf5ef2aSThomas Huth 3025fcf5ef2aSThomas Huth /* 440 specific */ 3026fcf5ef2aSThomas Huth target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high, 3027fcf5ef2aSThomas Huth target_ulong low, uint32_t update_Rc) 3028fcf5ef2aSThomas Huth { 3029fcf5ef2aSThomas Huth target_ulong mask; 3030fcf5ef2aSThomas Huth int i; 3031fcf5ef2aSThomas Huth 3032fcf5ef2aSThomas Huth i = 1; 3033fcf5ef2aSThomas Huth for (mask = 0xFF000000; mask != 0; mask = mask >> 8) { 3034fcf5ef2aSThomas Huth if ((high & mask) == 0) { 3035fcf5ef2aSThomas Huth if (update_Rc) { 3036fcf5ef2aSThomas Huth env->crf[0] = 0x4; 3037fcf5ef2aSThomas Huth } 3038fcf5ef2aSThomas Huth goto done; 3039fcf5ef2aSThomas Huth } 3040fcf5ef2aSThomas Huth i++; 3041fcf5ef2aSThomas Huth } 3042fcf5ef2aSThomas Huth for (mask = 0xFF000000; mask != 0; mask = mask >> 8) { 3043fcf5ef2aSThomas Huth if ((low & mask) == 0) { 3044fcf5ef2aSThomas Huth if (update_Rc) { 3045fcf5ef2aSThomas Huth env->crf[0] = 0x8; 3046fcf5ef2aSThomas Huth } 3047fcf5ef2aSThomas Huth goto done; 3048fcf5ef2aSThomas Huth } 3049fcf5ef2aSThomas Huth i++; 3050fcf5ef2aSThomas Huth } 3051fcf5ef2aSThomas Huth i = 8; 3052fcf5ef2aSThomas Huth if (update_Rc) { 3053fcf5ef2aSThomas Huth env->crf[0] = 0x2; 3054fcf5ef2aSThomas Huth } 3055fcf5ef2aSThomas Huth done: 3056fcf5ef2aSThomas Huth env->xer = (env->xer & ~0x7F) | i; 3057fcf5ef2aSThomas Huth if (update_Rc) { 3058fcf5ef2aSThomas Huth env->crf[0] |= xer_so; 3059fcf5ef2aSThomas Huth } 3060fcf5ef2aSThomas Huth return i; 3061fcf5ef2aSThomas Huth } 3062