1d7582078SBlue Swirl /* 2d7582078SBlue Swirl * x86 integer helpers 3d7582078SBlue Swirl * 4d7582078SBlue Swirl * Copyright (c) 2003 Fabrice Bellard 5d7582078SBlue Swirl * 6d7582078SBlue Swirl * This library is free software; you can redistribute it and/or 7d7582078SBlue Swirl * modify it under the terms of the GNU Lesser General Public 8d7582078SBlue Swirl * License as published by the Free Software Foundation; either 9d9ff33adSChetan Pant * version 2.1 of the License, or (at your option) any later version. 10d7582078SBlue Swirl * 11d7582078SBlue Swirl * This library is distributed in the hope that it will be useful, 12d7582078SBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 13d7582078SBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14d7582078SBlue Swirl * Lesser General Public License for more details. 15d7582078SBlue Swirl * 16d7582078SBlue Swirl * You should have received a copy of the GNU Lesser General Public 17d7582078SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18d7582078SBlue Swirl */ 19d7582078SBlue Swirl 20b6a0aa05SPeter Maydell #include "qemu/osdep.h" 21cd617484SPhilippe Mathieu-Daudé #include "qemu/log.h" 22d7582078SBlue Swirl #include "cpu.h" 2363c91552SPaolo Bonzini #include "exec/exec-all.h" 241de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 252ef6175aSRichard Henderson #include "exec/helper-proto.h" 26369fd5caSRichard Henderson #include "qapi/error.h" 27369fd5caSRichard Henderson #include "qemu/guest-random.h" 28ed69e831SClaudio Fontana #include "helper-tcg.h" 29d7582078SBlue Swirl 30d7582078SBlue Swirl //#define DEBUG_MULDIV 31d7582078SBlue Swirl 32d7582078SBlue Swirl /* division, flags are undefined */ 33d7582078SBlue Swirl 347923057bSBlue Swirl void helper_divb_AL(CPUX86State *env, target_ulong t0) 35d7582078SBlue Swirl { 36d7582078SBlue Swirl unsigned int num, den, q, r; 37d7582078SBlue Swirl 384b34e3adSliguang num = (env->regs[R_EAX] & 0xffff); 39d7582078SBlue Swirl den = (t0 & 0xff); 40d7582078SBlue Swirl if (den == 0) { 41cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 42d7582078SBlue Swirl } 43d7582078SBlue Swirl q = (num / den); 44d7582078SBlue Swirl if (q > 0xff) { 45cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 46d7582078SBlue Swirl } 47d7582078SBlue Swirl q &= 0xff; 48d7582078SBlue Swirl r = (num % den) & 0xff; 494b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q; 50d7582078SBlue Swirl } 51d7582078SBlue Swirl 527923057bSBlue Swirl void helper_idivb_AL(CPUX86State *env, target_ulong t0) 53d7582078SBlue Swirl { 54d7582078SBlue Swirl int num, den, q, r; 55d7582078SBlue Swirl 564b34e3adSliguang num = (int16_t)env->regs[R_EAX]; 57d7582078SBlue Swirl den = (int8_t)t0; 58d7582078SBlue Swirl if (den == 0) { 59cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 60d7582078SBlue Swirl } 61d7582078SBlue Swirl q = (num / den); 62d7582078SBlue Swirl if (q != (int8_t)q) { 63cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 64d7582078SBlue Swirl } 65d7582078SBlue Swirl q &= 0xff; 66d7582078SBlue Swirl r = (num % den) & 0xff; 674b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q; 68d7582078SBlue Swirl } 69d7582078SBlue Swirl 707923057bSBlue Swirl void helper_divw_AX(CPUX86State *env, target_ulong t0) 71d7582078SBlue Swirl { 72d7582078SBlue Swirl unsigned int num, den, q, r; 73d7582078SBlue Swirl 7400f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16); 75d7582078SBlue Swirl den = (t0 & 0xffff); 76d7582078SBlue Swirl if (den == 0) { 77cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 78d7582078SBlue Swirl } 79d7582078SBlue Swirl q = (num / den); 80d7582078SBlue Swirl if (q > 0xffff) { 81cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 82d7582078SBlue Swirl } 83d7582078SBlue Swirl q &= 0xffff; 84d7582078SBlue Swirl r = (num % den) & 0xffff; 854b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q; 8600f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r; 87d7582078SBlue Swirl } 88d7582078SBlue Swirl 897923057bSBlue Swirl void helper_idivw_AX(CPUX86State *env, target_ulong t0) 90d7582078SBlue Swirl { 91d7582078SBlue Swirl int num, den, q, r; 92d7582078SBlue Swirl 9300f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16); 94d7582078SBlue Swirl den = (int16_t)t0; 95d7582078SBlue Swirl if (den == 0) { 96cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 97d7582078SBlue Swirl } 98d7582078SBlue Swirl q = (num / den); 99d7582078SBlue Swirl if (q != (int16_t)q) { 100cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 101d7582078SBlue Swirl } 102d7582078SBlue Swirl q &= 0xffff; 103d7582078SBlue Swirl r = (num % den) & 0xffff; 1044b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q; 10500f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r; 106d7582078SBlue Swirl } 107d7582078SBlue Swirl 1087923057bSBlue Swirl void helper_divl_EAX(CPUX86State *env, target_ulong t0) 109d7582078SBlue Swirl { 110d7582078SBlue Swirl unsigned int den, r; 111d7582078SBlue Swirl uint64_t num, q; 112d7582078SBlue Swirl 11300f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 114d7582078SBlue Swirl den = t0; 115d7582078SBlue Swirl if (den == 0) { 116cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 117d7582078SBlue Swirl } 118d7582078SBlue Swirl q = (num / den); 119d7582078SBlue Swirl r = (num % den); 120d7582078SBlue Swirl if (q > 0xffffffff) { 121cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 122d7582078SBlue Swirl } 1234b34e3adSliguang env->regs[R_EAX] = (uint32_t)q; 12400f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r; 125d7582078SBlue Swirl } 126d7582078SBlue Swirl 1277923057bSBlue Swirl void helper_idivl_EAX(CPUX86State *env, target_ulong t0) 128d7582078SBlue Swirl { 129d7582078SBlue Swirl int den, r; 130d7582078SBlue Swirl int64_t num, q; 131d7582078SBlue Swirl 13200f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 133d7582078SBlue Swirl den = t0; 134d7582078SBlue Swirl if (den == 0) { 135cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 136d7582078SBlue Swirl } 137d7582078SBlue Swirl q = (num / den); 138d7582078SBlue Swirl r = (num % den); 139d7582078SBlue Swirl if (q != (int32_t)q) { 140cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 141d7582078SBlue Swirl } 1424b34e3adSliguang env->regs[R_EAX] = (uint32_t)q; 14300f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r; 144d7582078SBlue Swirl } 145d7582078SBlue Swirl 146d7582078SBlue Swirl /* bcd */ 147d7582078SBlue Swirl 148ec568919SPaolo Bonzini target_ulong helper_aam(target_ulong al, target_ulong base) 149d7582078SBlue Swirl { 150ec568919SPaolo Bonzini int ah; 151d7582078SBlue Swirl 152ec568919SPaolo Bonzini al &= 0xff; 153d7582078SBlue Swirl ah = al / base; 154d7582078SBlue Swirl al = al % base; 155ec568919SPaolo Bonzini return al | (ah << 8); 156d7582078SBlue Swirl } 157d7582078SBlue Swirl 158ec568919SPaolo Bonzini target_ulong helper_aad(target_ulong ax, target_ulong base) 159d7582078SBlue Swirl { 160d7582078SBlue Swirl int al, ah; 161d7582078SBlue Swirl 162ec568919SPaolo Bonzini al = ax & 0xff; 163ec568919SPaolo Bonzini ah = (ax >> 8) & 0xff; 164d7582078SBlue Swirl al = ((ah * base) + al) & 0xff; 165ec568919SPaolo Bonzini return al; 166d7582078SBlue Swirl } 167d7582078SBlue Swirl 1687923057bSBlue Swirl void helper_aaa(CPUX86State *env) 169d7582078SBlue Swirl { 170d7582078SBlue Swirl int icarry; 171d7582078SBlue Swirl int al, ah, af; 172d7582078SBlue Swirl int eflags; 173d7582078SBlue Swirl 1742455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env); 175d7582078SBlue Swirl af = eflags & CC_A; 1764b34e3adSliguang al = env->regs[R_EAX] & 0xff; 1774b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 178d7582078SBlue Swirl 179d7582078SBlue Swirl icarry = (al > 0xf9); 180d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 181d7582078SBlue Swirl al = (al + 6) & 0x0f; 182d7582078SBlue Swirl ah = (ah + 1 + icarry) & 0xff; 183d7582078SBlue Swirl eflags |= CC_C | CC_A; 184d7582078SBlue Swirl } else { 185d7582078SBlue Swirl eflags &= ~(CC_C | CC_A); 186d7582078SBlue Swirl al &= 0x0f; 187d7582078SBlue Swirl } 1884b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 189d7582078SBlue Swirl CC_SRC = eflags; 190*abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS; 191d7582078SBlue Swirl } 192d7582078SBlue Swirl 1937923057bSBlue Swirl void helper_aas(CPUX86State *env) 194d7582078SBlue Swirl { 195d7582078SBlue Swirl int icarry; 196d7582078SBlue Swirl int al, ah, af; 197d7582078SBlue Swirl int eflags; 198d7582078SBlue Swirl 1992455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env); 200d7582078SBlue Swirl af = eflags & CC_A; 2014b34e3adSliguang al = env->regs[R_EAX] & 0xff; 2024b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 203d7582078SBlue Swirl 204d7582078SBlue Swirl icarry = (al < 6); 205d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 206d7582078SBlue Swirl al = (al - 6) & 0x0f; 207d7582078SBlue Swirl ah = (ah - 1 - icarry) & 0xff; 208d7582078SBlue Swirl eflags |= CC_C | CC_A; 209d7582078SBlue Swirl } else { 210d7582078SBlue Swirl eflags &= ~(CC_C | CC_A); 211d7582078SBlue Swirl al &= 0x0f; 212d7582078SBlue Swirl } 2134b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 214d7582078SBlue Swirl CC_SRC = eflags; 215*abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS; 216d7582078SBlue Swirl } 217d7582078SBlue Swirl 2187923057bSBlue Swirl void helper_daa(CPUX86State *env) 219d7582078SBlue Swirl { 220d7582078SBlue Swirl int old_al, al, af, cf; 221d7582078SBlue Swirl int eflags; 222d7582078SBlue Swirl 2232455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env); 224d7582078SBlue Swirl cf = eflags & CC_C; 225d7582078SBlue Swirl af = eflags & CC_A; 2264b34e3adSliguang old_al = al = env->regs[R_EAX] & 0xff; 227d7582078SBlue Swirl 228d7582078SBlue Swirl eflags = 0; 229d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 230d7582078SBlue Swirl al = (al + 6) & 0xff; 231d7582078SBlue Swirl eflags |= CC_A; 232d7582078SBlue Swirl } 233d7582078SBlue Swirl if ((old_al > 0x99) || cf) { 234d7582078SBlue Swirl al = (al + 0x60) & 0xff; 235d7582078SBlue Swirl eflags |= CC_C; 236d7582078SBlue Swirl } 2374b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al; 238d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */ 239d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */ 240d7582078SBlue Swirl eflags |= parity_table[al]; /* pf */ 241d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */ 242d7582078SBlue Swirl CC_SRC = eflags; 243*abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS; 244d7582078SBlue Swirl } 245d7582078SBlue Swirl 2467923057bSBlue Swirl void helper_das(CPUX86State *env) 247d7582078SBlue Swirl { 248d7582078SBlue Swirl int al, al1, af, cf; 249d7582078SBlue Swirl int eflags; 250d7582078SBlue Swirl 2512455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env); 252d7582078SBlue Swirl cf = eflags & CC_C; 253d7582078SBlue Swirl af = eflags & CC_A; 2544b34e3adSliguang al = env->regs[R_EAX] & 0xff; 255d7582078SBlue Swirl 256d7582078SBlue Swirl eflags = 0; 257d7582078SBlue Swirl al1 = al; 258d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 259d7582078SBlue Swirl eflags |= CC_A; 260d7582078SBlue Swirl if (al < 6 || cf) { 261d7582078SBlue Swirl eflags |= CC_C; 262d7582078SBlue Swirl } 263d7582078SBlue Swirl al = (al - 6) & 0xff; 264d7582078SBlue Swirl } 265d7582078SBlue Swirl if ((al1 > 0x99) || cf) { 266d7582078SBlue Swirl al = (al - 0x60) & 0xff; 267d7582078SBlue Swirl eflags |= CC_C; 268d7582078SBlue Swirl } 2694b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al; 270d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */ 271d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */ 272d7582078SBlue Swirl eflags |= parity_table[al]; /* pf */ 273d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */ 274d7582078SBlue Swirl CC_SRC = eflags; 275*abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS; 276d7582078SBlue Swirl } 277d7582078SBlue Swirl 278d7582078SBlue Swirl #ifdef TARGET_X86_64 279d7582078SBlue Swirl static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) 280d7582078SBlue Swirl { 281d7582078SBlue Swirl *plow += a; 282d7582078SBlue Swirl /* carry test */ 283d7582078SBlue Swirl if (*plow < a) { 284d7582078SBlue Swirl (*phigh)++; 285d7582078SBlue Swirl } 286d7582078SBlue Swirl *phigh += b; 287d7582078SBlue Swirl } 288d7582078SBlue Swirl 289d7582078SBlue Swirl static void neg128(uint64_t *plow, uint64_t *phigh) 290d7582078SBlue Swirl { 291d7582078SBlue Swirl *plow = ~*plow; 292d7582078SBlue Swirl *phigh = ~*phigh; 293d7582078SBlue Swirl add128(plow, phigh, 1, 0); 294d7582078SBlue Swirl } 295d7582078SBlue Swirl 296d7582078SBlue Swirl /* return TRUE if overflow */ 297d7582078SBlue Swirl static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b) 298d7582078SBlue Swirl { 299d7582078SBlue Swirl uint64_t q, r, a1, a0; 300d7582078SBlue Swirl int i, qb, ab; 301d7582078SBlue Swirl 302d7582078SBlue Swirl a0 = *plow; 303d7582078SBlue Swirl a1 = *phigh; 304d7582078SBlue Swirl if (a1 == 0) { 305d7582078SBlue Swirl q = a0 / b; 306d7582078SBlue Swirl r = a0 % b; 307d7582078SBlue Swirl *plow = q; 308d7582078SBlue Swirl *phigh = r; 309d7582078SBlue Swirl } else { 310d7582078SBlue Swirl if (a1 >= b) { 311d7582078SBlue Swirl return 1; 312d7582078SBlue Swirl } 313d7582078SBlue Swirl /* XXX: use a better algorithm */ 314d7582078SBlue Swirl for (i = 0; i < 64; i++) { 315d7582078SBlue Swirl ab = a1 >> 63; 316d7582078SBlue Swirl a1 = (a1 << 1) | (a0 >> 63); 317d7582078SBlue Swirl if (ab || a1 >= b) { 318d7582078SBlue Swirl a1 -= b; 319d7582078SBlue Swirl qb = 1; 320d7582078SBlue Swirl } else { 321d7582078SBlue Swirl qb = 0; 322d7582078SBlue Swirl } 323d7582078SBlue Swirl a0 = (a0 << 1) | qb; 324d7582078SBlue Swirl } 325d7582078SBlue Swirl #if defined(DEBUG_MULDIV) 326d7582078SBlue Swirl printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 327d7582078SBlue Swirl ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n", 328d7582078SBlue Swirl *phigh, *plow, b, a0, a1); 329d7582078SBlue Swirl #endif 330d7582078SBlue Swirl *plow = a0; 331d7582078SBlue Swirl *phigh = a1; 332d7582078SBlue Swirl } 333d7582078SBlue Swirl return 0; 334d7582078SBlue Swirl } 335d7582078SBlue Swirl 336d7582078SBlue Swirl /* return TRUE if overflow */ 337d7582078SBlue Swirl static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) 338d7582078SBlue Swirl { 339d7582078SBlue Swirl int sa, sb; 340d7582078SBlue Swirl 341d7582078SBlue Swirl sa = ((int64_t)*phigh < 0); 342d7582078SBlue Swirl if (sa) { 343d7582078SBlue Swirl neg128(plow, phigh); 344d7582078SBlue Swirl } 345d7582078SBlue Swirl sb = (b < 0); 346d7582078SBlue Swirl if (sb) { 347d7582078SBlue Swirl b = -b; 348d7582078SBlue Swirl } 349d7582078SBlue Swirl if (div64(plow, phigh, b) != 0) { 350d7582078SBlue Swirl return 1; 351d7582078SBlue Swirl } 352d7582078SBlue Swirl if (sa ^ sb) { 353d7582078SBlue Swirl if (*plow > (1ULL << 63)) { 354d7582078SBlue Swirl return 1; 355d7582078SBlue Swirl } 356d7582078SBlue Swirl *plow = -*plow; 357d7582078SBlue Swirl } else { 358d7582078SBlue Swirl if (*plow >= (1ULL << 63)) { 359d7582078SBlue Swirl return 1; 360d7582078SBlue Swirl } 361d7582078SBlue Swirl } 362d7582078SBlue Swirl if (sa) { 363d7582078SBlue Swirl *phigh = -*phigh; 364d7582078SBlue Swirl } 365d7582078SBlue Swirl return 0; 366d7582078SBlue Swirl } 367d7582078SBlue Swirl 3687923057bSBlue Swirl void helper_divq_EAX(CPUX86State *env, target_ulong t0) 369d7582078SBlue Swirl { 370d7582078SBlue Swirl uint64_t r0, r1; 371d7582078SBlue Swirl 372d7582078SBlue Swirl if (t0 == 0) { 373cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 374d7582078SBlue Swirl } 3754b34e3adSliguang r0 = env->regs[R_EAX]; 37600f5e6f2Sliguang r1 = env->regs[R_EDX]; 377d7582078SBlue Swirl if (div64(&r0, &r1, t0)) { 378cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 379d7582078SBlue Swirl } 3804b34e3adSliguang env->regs[R_EAX] = r0; 38100f5e6f2Sliguang env->regs[R_EDX] = r1; 382d7582078SBlue Swirl } 383d7582078SBlue Swirl 3847923057bSBlue Swirl void helper_idivq_EAX(CPUX86State *env, target_ulong t0) 385d7582078SBlue Swirl { 386d7582078SBlue Swirl uint64_t r0, r1; 387d7582078SBlue Swirl 388d7582078SBlue Swirl if (t0 == 0) { 389cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 390d7582078SBlue Swirl } 3914b34e3adSliguang r0 = env->regs[R_EAX]; 39200f5e6f2Sliguang r1 = env->regs[R_EDX]; 393d7582078SBlue Swirl if (idiv64(&r0, &r1, t0)) { 394cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 395d7582078SBlue Swirl } 3964b34e3adSliguang env->regs[R_EAX] = r0; 39700f5e6f2Sliguang env->regs[R_EDX] = r1; 398d7582078SBlue Swirl } 399d7582078SBlue Swirl #endif 400d7582078SBlue Swirl 401f1300734SRichard Henderson #if TARGET_LONG_BITS == 32 402f1300734SRichard Henderson # define ctztl ctz32 403f1300734SRichard Henderson # define clztl clz32 404f1300734SRichard Henderson #else 405f1300734SRichard Henderson # define ctztl ctz64 406f1300734SRichard Henderson # define clztl clz64 407f1300734SRichard Henderson #endif 408f1300734SRichard Henderson 4090592f74aSRichard Henderson target_ulong helper_pdep(target_ulong src, target_ulong mask) 4100592f74aSRichard Henderson { 4110592f74aSRichard Henderson target_ulong dest = 0; 4120592f74aSRichard Henderson int i, o; 4130592f74aSRichard Henderson 4140592f74aSRichard Henderson for (i = 0; mask != 0; i++) { 4150592f74aSRichard Henderson o = ctztl(mask); 4160592f74aSRichard Henderson mask &= mask - 1; 4170592f74aSRichard Henderson dest |= ((src >> i) & 1) << o; 4180592f74aSRichard Henderson } 4190592f74aSRichard Henderson return dest; 4200592f74aSRichard Henderson } 4210592f74aSRichard Henderson 4220592f74aSRichard Henderson target_ulong helper_pext(target_ulong src, target_ulong mask) 4230592f74aSRichard Henderson { 4240592f74aSRichard Henderson target_ulong dest = 0; 4250592f74aSRichard Henderson int i, o; 4260592f74aSRichard Henderson 4270592f74aSRichard Henderson for (o = 0; mask != 0; o++) { 4280592f74aSRichard Henderson i = ctztl(mask); 4290592f74aSRichard Henderson mask &= mask - 1; 4300592f74aSRichard Henderson dest |= ((src >> i) & 1) << o; 4310592f74aSRichard Henderson } 4320592f74aSRichard Henderson return dest; 4330592f74aSRichard Henderson } 4340592f74aSRichard Henderson 43507929f2aSRichard Henderson /* Test that BIT is enabled in CR4. If not, raise an illegal opcode 43607929f2aSRichard Henderson exception. This reduces the requirements for rare CR4 bits being 43707929f2aSRichard Henderson mapped into HFLAGS. */ 43807929f2aSRichard Henderson void helper_cr4_testbit(CPUX86State *env, uint32_t bit) 43907929f2aSRichard Henderson { 44007929f2aSRichard Henderson if (unlikely((env->cr[4] & bit) == 0)) { 44107929f2aSRichard Henderson raise_exception_ra(env, EXCP06_ILLOP, GETPC()); 44207929f2aSRichard Henderson } 44307929f2aSRichard Henderson } 444369fd5caSRichard Henderson 445369fd5caSRichard Henderson target_ulong HELPER(rdrand)(CPUX86State *env) 446369fd5caSRichard Henderson { 447369fd5caSRichard Henderson Error *err = NULL; 448369fd5caSRichard Henderson target_ulong ret; 449369fd5caSRichard Henderson 450369fd5caSRichard Henderson if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { 451369fd5caSRichard Henderson qemu_log_mask(LOG_UNIMP, "rdrand: Crypto failure: %s", 452369fd5caSRichard Henderson error_get_pretty(err)); 453369fd5caSRichard Henderson error_free(err); 454369fd5caSRichard Henderson /* Failure clears CF and all other flags, and returns 0. */ 455369fd5caSRichard Henderson env->cc_src = 0; 456*abdcc5c8SPaolo Bonzini ret = 0; 457*abdcc5c8SPaolo Bonzini } else { 458369fd5caSRichard Henderson /* Success sets CF and clears all others. */ 459369fd5caSRichard Henderson env->cc_src = CC_C; 460*abdcc5c8SPaolo Bonzini } 461*abdcc5c8SPaolo Bonzini env->cc_op = CC_OP_EFLAGS; 462369fd5caSRichard Henderson return ret; 463369fd5caSRichard Henderson } 464