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" 21d7582078SBlue Swirl #include "cpu.h" 2263c91552SPaolo Bonzini #include "exec/exec-all.h" 231de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 242ef6175aSRichard Henderson #include "exec/helper-proto.h" 25369fd5caSRichard Henderson #include "qapi/error.h" 26369fd5caSRichard Henderson #include "qemu/guest-random.h" 27*ed69e831SClaudio Fontana #include "helper-tcg.h" 28d7582078SBlue Swirl 29d7582078SBlue Swirl //#define DEBUG_MULDIV 30d7582078SBlue Swirl 31d7582078SBlue Swirl /* modulo 9 table */ 32d7582078SBlue Swirl static const uint8_t rclb_table[32] = { 33d7582078SBlue Swirl 0, 1, 2, 3, 4, 5, 6, 7, 34d7582078SBlue Swirl 8, 0, 1, 2, 3, 4, 5, 6, 35d7582078SBlue Swirl 7, 8, 0, 1, 2, 3, 4, 5, 36d7582078SBlue Swirl 6, 7, 8, 0, 1, 2, 3, 4, 37d7582078SBlue Swirl }; 38d7582078SBlue Swirl 39d7582078SBlue Swirl /* modulo 17 table */ 40d7582078SBlue Swirl static const uint8_t rclw_table[32] = { 41d7582078SBlue Swirl 0, 1, 2, 3, 4, 5, 6, 7, 42d7582078SBlue Swirl 8, 9, 10, 11, 12, 13, 14, 15, 43d7582078SBlue Swirl 16, 0, 1, 2, 3, 4, 5, 6, 44d7582078SBlue Swirl 7, 8, 9, 10, 11, 12, 13, 14, 45d7582078SBlue Swirl }; 46d7582078SBlue Swirl 47d7582078SBlue Swirl /* division, flags are undefined */ 48d7582078SBlue Swirl 497923057bSBlue Swirl void helper_divb_AL(CPUX86State *env, target_ulong t0) 50d7582078SBlue Swirl { 51d7582078SBlue Swirl unsigned int num, den, q, r; 52d7582078SBlue Swirl 534b34e3adSliguang num = (env->regs[R_EAX] & 0xffff); 54d7582078SBlue Swirl den = (t0 & 0xff); 55d7582078SBlue Swirl if (den == 0) { 56cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 57d7582078SBlue Swirl } 58d7582078SBlue Swirl q = (num / den); 59d7582078SBlue Swirl if (q > 0xff) { 60cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 61d7582078SBlue Swirl } 62d7582078SBlue Swirl q &= 0xff; 63d7582078SBlue Swirl r = (num % den) & 0xff; 644b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q; 65d7582078SBlue Swirl } 66d7582078SBlue Swirl 677923057bSBlue Swirl void helper_idivb_AL(CPUX86State *env, target_ulong t0) 68d7582078SBlue Swirl { 69d7582078SBlue Swirl int num, den, q, r; 70d7582078SBlue Swirl 714b34e3adSliguang num = (int16_t)env->regs[R_EAX]; 72d7582078SBlue Swirl den = (int8_t)t0; 73d7582078SBlue Swirl if (den == 0) { 74cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 75d7582078SBlue Swirl } 76d7582078SBlue Swirl q = (num / den); 77d7582078SBlue Swirl if (q != (int8_t)q) { 78cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 79d7582078SBlue Swirl } 80d7582078SBlue Swirl q &= 0xff; 81d7582078SBlue Swirl r = (num % den) & 0xff; 824b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q; 83d7582078SBlue Swirl } 84d7582078SBlue Swirl 857923057bSBlue Swirl void helper_divw_AX(CPUX86State *env, target_ulong t0) 86d7582078SBlue Swirl { 87d7582078SBlue Swirl unsigned int num, den, q, r; 88d7582078SBlue Swirl 8900f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16); 90d7582078SBlue Swirl den = (t0 & 0xffff); 91d7582078SBlue Swirl if (den == 0) { 92cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 93d7582078SBlue Swirl } 94d7582078SBlue Swirl q = (num / den); 95d7582078SBlue Swirl if (q > 0xffff) { 96cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 97d7582078SBlue Swirl } 98d7582078SBlue Swirl q &= 0xffff; 99d7582078SBlue Swirl r = (num % den) & 0xffff; 1004b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q; 10100f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r; 102d7582078SBlue Swirl } 103d7582078SBlue Swirl 1047923057bSBlue Swirl void helper_idivw_AX(CPUX86State *env, target_ulong t0) 105d7582078SBlue Swirl { 106d7582078SBlue Swirl int num, den, q, r; 107d7582078SBlue Swirl 10800f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16); 109d7582078SBlue Swirl den = (int16_t)t0; 110d7582078SBlue Swirl if (den == 0) { 111cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 112d7582078SBlue Swirl } 113d7582078SBlue Swirl q = (num / den); 114d7582078SBlue Swirl if (q != (int16_t)q) { 115cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 116d7582078SBlue Swirl } 117d7582078SBlue Swirl q &= 0xffff; 118d7582078SBlue Swirl r = (num % den) & 0xffff; 1194b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q; 12000f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r; 121d7582078SBlue Swirl } 122d7582078SBlue Swirl 1237923057bSBlue Swirl void helper_divl_EAX(CPUX86State *env, target_ulong t0) 124d7582078SBlue Swirl { 125d7582078SBlue Swirl unsigned int den, r; 126d7582078SBlue Swirl uint64_t num, q; 127d7582078SBlue Swirl 12800f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 129d7582078SBlue Swirl den = t0; 130d7582078SBlue Swirl if (den == 0) { 131cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 132d7582078SBlue Swirl } 133d7582078SBlue Swirl q = (num / den); 134d7582078SBlue Swirl r = (num % den); 135d7582078SBlue Swirl if (q > 0xffffffff) { 136cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 137d7582078SBlue Swirl } 1384b34e3adSliguang env->regs[R_EAX] = (uint32_t)q; 13900f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r; 140d7582078SBlue Swirl } 141d7582078SBlue Swirl 1427923057bSBlue Swirl void helper_idivl_EAX(CPUX86State *env, target_ulong t0) 143d7582078SBlue Swirl { 144d7582078SBlue Swirl int den, r; 145d7582078SBlue Swirl int64_t num, q; 146d7582078SBlue Swirl 14700f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 148d7582078SBlue Swirl den = t0; 149d7582078SBlue Swirl if (den == 0) { 150cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 151d7582078SBlue Swirl } 152d7582078SBlue Swirl q = (num / den); 153d7582078SBlue Swirl r = (num % den); 154d7582078SBlue Swirl if (q != (int32_t)q) { 155cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 156d7582078SBlue Swirl } 1574b34e3adSliguang env->regs[R_EAX] = (uint32_t)q; 15800f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r; 159d7582078SBlue Swirl } 160d7582078SBlue Swirl 161d7582078SBlue Swirl /* bcd */ 162d7582078SBlue Swirl 163d7582078SBlue Swirl /* XXX: exception */ 1647923057bSBlue Swirl void helper_aam(CPUX86State *env, int base) 165d7582078SBlue Swirl { 166d7582078SBlue Swirl int al, ah; 167d7582078SBlue Swirl 1684b34e3adSliguang al = env->regs[R_EAX] & 0xff; 169d7582078SBlue Swirl ah = al / base; 170d7582078SBlue Swirl al = al % base; 1714b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 172d7582078SBlue Swirl CC_DST = al; 173d7582078SBlue Swirl } 174d7582078SBlue Swirl 1757923057bSBlue Swirl void helper_aad(CPUX86State *env, int base) 176d7582078SBlue Swirl { 177d7582078SBlue Swirl int al, ah; 178d7582078SBlue Swirl 1794b34e3adSliguang al = env->regs[R_EAX] & 0xff; 1804b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 181d7582078SBlue Swirl al = ((ah * base) + al) & 0xff; 1824b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al; 183d7582078SBlue Swirl CC_DST = al; 184d7582078SBlue Swirl } 185d7582078SBlue Swirl 1867923057bSBlue Swirl void helper_aaa(CPUX86State *env) 187d7582078SBlue Swirl { 188d7582078SBlue Swirl int icarry; 189d7582078SBlue Swirl int al, ah, af; 190d7582078SBlue Swirl int eflags; 191d7582078SBlue Swirl 192f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 193d7582078SBlue Swirl af = eflags & CC_A; 1944b34e3adSliguang al = env->regs[R_EAX] & 0xff; 1954b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 196d7582078SBlue Swirl 197d7582078SBlue Swirl icarry = (al > 0xf9); 198d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 199d7582078SBlue Swirl al = (al + 6) & 0x0f; 200d7582078SBlue Swirl ah = (ah + 1 + icarry) & 0xff; 201d7582078SBlue Swirl eflags |= CC_C | CC_A; 202d7582078SBlue Swirl } else { 203d7582078SBlue Swirl eflags &= ~(CC_C | CC_A); 204d7582078SBlue Swirl al &= 0x0f; 205d7582078SBlue Swirl } 2064b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 207d7582078SBlue Swirl CC_SRC = eflags; 208d7582078SBlue Swirl } 209d7582078SBlue Swirl 2107923057bSBlue Swirl void helper_aas(CPUX86State *env) 211d7582078SBlue Swirl { 212d7582078SBlue Swirl int icarry; 213d7582078SBlue Swirl int al, ah, af; 214d7582078SBlue Swirl int eflags; 215d7582078SBlue Swirl 216f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 217d7582078SBlue Swirl af = eflags & CC_A; 2184b34e3adSliguang al = env->regs[R_EAX] & 0xff; 2194b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 220d7582078SBlue Swirl 221d7582078SBlue Swirl icarry = (al < 6); 222d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 223d7582078SBlue Swirl al = (al - 6) & 0x0f; 224d7582078SBlue Swirl ah = (ah - 1 - icarry) & 0xff; 225d7582078SBlue Swirl eflags |= CC_C | CC_A; 226d7582078SBlue Swirl } else { 227d7582078SBlue Swirl eflags &= ~(CC_C | CC_A); 228d7582078SBlue Swirl al &= 0x0f; 229d7582078SBlue Swirl } 2304b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 231d7582078SBlue Swirl CC_SRC = eflags; 232d7582078SBlue Swirl } 233d7582078SBlue Swirl 2347923057bSBlue Swirl void helper_daa(CPUX86State *env) 235d7582078SBlue Swirl { 236d7582078SBlue Swirl int old_al, al, af, cf; 237d7582078SBlue Swirl int eflags; 238d7582078SBlue Swirl 239f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 240d7582078SBlue Swirl cf = eflags & CC_C; 241d7582078SBlue Swirl af = eflags & CC_A; 2424b34e3adSliguang old_al = al = env->regs[R_EAX] & 0xff; 243d7582078SBlue Swirl 244d7582078SBlue Swirl eflags = 0; 245d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 246d7582078SBlue Swirl al = (al + 6) & 0xff; 247d7582078SBlue Swirl eflags |= CC_A; 248d7582078SBlue Swirl } 249d7582078SBlue Swirl if ((old_al > 0x99) || cf) { 250d7582078SBlue Swirl al = (al + 0x60) & 0xff; 251d7582078SBlue Swirl eflags |= CC_C; 252d7582078SBlue Swirl } 2534b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al; 254d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */ 255d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */ 256d7582078SBlue Swirl eflags |= parity_table[al]; /* pf */ 257d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */ 258d7582078SBlue Swirl CC_SRC = eflags; 259d7582078SBlue Swirl } 260d7582078SBlue Swirl 2617923057bSBlue Swirl void helper_das(CPUX86State *env) 262d7582078SBlue Swirl { 263d7582078SBlue Swirl int al, al1, af, cf; 264d7582078SBlue Swirl int eflags; 265d7582078SBlue Swirl 266f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 267d7582078SBlue Swirl cf = eflags & CC_C; 268d7582078SBlue Swirl af = eflags & CC_A; 2694b34e3adSliguang al = env->regs[R_EAX] & 0xff; 270d7582078SBlue Swirl 271d7582078SBlue Swirl eflags = 0; 272d7582078SBlue Swirl al1 = al; 273d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 274d7582078SBlue Swirl eflags |= CC_A; 275d7582078SBlue Swirl if (al < 6 || cf) { 276d7582078SBlue Swirl eflags |= CC_C; 277d7582078SBlue Swirl } 278d7582078SBlue Swirl al = (al - 6) & 0xff; 279d7582078SBlue Swirl } 280d7582078SBlue Swirl if ((al1 > 0x99) || cf) { 281d7582078SBlue Swirl al = (al - 0x60) & 0xff; 282d7582078SBlue Swirl eflags |= CC_C; 283d7582078SBlue Swirl } 2844b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al; 285d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */ 286d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */ 287d7582078SBlue Swirl eflags |= parity_table[al]; /* pf */ 288d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */ 289d7582078SBlue Swirl CC_SRC = eflags; 290d7582078SBlue Swirl } 291d7582078SBlue Swirl 292d7582078SBlue Swirl #ifdef TARGET_X86_64 293d7582078SBlue Swirl static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) 294d7582078SBlue Swirl { 295d7582078SBlue Swirl *plow += a; 296d7582078SBlue Swirl /* carry test */ 297d7582078SBlue Swirl if (*plow < a) { 298d7582078SBlue Swirl (*phigh)++; 299d7582078SBlue Swirl } 300d7582078SBlue Swirl *phigh += b; 301d7582078SBlue Swirl } 302d7582078SBlue Swirl 303d7582078SBlue Swirl static void neg128(uint64_t *plow, uint64_t *phigh) 304d7582078SBlue Swirl { 305d7582078SBlue Swirl *plow = ~*plow; 306d7582078SBlue Swirl *phigh = ~*phigh; 307d7582078SBlue Swirl add128(plow, phigh, 1, 0); 308d7582078SBlue Swirl } 309d7582078SBlue Swirl 310d7582078SBlue Swirl /* return TRUE if overflow */ 311d7582078SBlue Swirl static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b) 312d7582078SBlue Swirl { 313d7582078SBlue Swirl uint64_t q, r, a1, a0; 314d7582078SBlue Swirl int i, qb, ab; 315d7582078SBlue Swirl 316d7582078SBlue Swirl a0 = *plow; 317d7582078SBlue Swirl a1 = *phigh; 318d7582078SBlue Swirl if (a1 == 0) { 319d7582078SBlue Swirl q = a0 / b; 320d7582078SBlue Swirl r = a0 % b; 321d7582078SBlue Swirl *plow = q; 322d7582078SBlue Swirl *phigh = r; 323d7582078SBlue Swirl } else { 324d7582078SBlue Swirl if (a1 >= b) { 325d7582078SBlue Swirl return 1; 326d7582078SBlue Swirl } 327d7582078SBlue Swirl /* XXX: use a better algorithm */ 328d7582078SBlue Swirl for (i = 0; i < 64; i++) { 329d7582078SBlue Swirl ab = a1 >> 63; 330d7582078SBlue Swirl a1 = (a1 << 1) | (a0 >> 63); 331d7582078SBlue Swirl if (ab || a1 >= b) { 332d7582078SBlue Swirl a1 -= b; 333d7582078SBlue Swirl qb = 1; 334d7582078SBlue Swirl } else { 335d7582078SBlue Swirl qb = 0; 336d7582078SBlue Swirl } 337d7582078SBlue Swirl a0 = (a0 << 1) | qb; 338d7582078SBlue Swirl } 339d7582078SBlue Swirl #if defined(DEBUG_MULDIV) 340d7582078SBlue Swirl printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 341d7582078SBlue Swirl ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n", 342d7582078SBlue Swirl *phigh, *plow, b, a0, a1); 343d7582078SBlue Swirl #endif 344d7582078SBlue Swirl *plow = a0; 345d7582078SBlue Swirl *phigh = a1; 346d7582078SBlue Swirl } 347d7582078SBlue Swirl return 0; 348d7582078SBlue Swirl } 349d7582078SBlue Swirl 350d7582078SBlue Swirl /* return TRUE if overflow */ 351d7582078SBlue Swirl static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) 352d7582078SBlue Swirl { 353d7582078SBlue Swirl int sa, sb; 354d7582078SBlue Swirl 355d7582078SBlue Swirl sa = ((int64_t)*phigh < 0); 356d7582078SBlue Swirl if (sa) { 357d7582078SBlue Swirl neg128(plow, phigh); 358d7582078SBlue Swirl } 359d7582078SBlue Swirl sb = (b < 0); 360d7582078SBlue Swirl if (sb) { 361d7582078SBlue Swirl b = -b; 362d7582078SBlue Swirl } 363d7582078SBlue Swirl if (div64(plow, phigh, b) != 0) { 364d7582078SBlue Swirl return 1; 365d7582078SBlue Swirl } 366d7582078SBlue Swirl if (sa ^ sb) { 367d7582078SBlue Swirl if (*plow > (1ULL << 63)) { 368d7582078SBlue Swirl return 1; 369d7582078SBlue Swirl } 370d7582078SBlue Swirl *plow = -*plow; 371d7582078SBlue Swirl } else { 372d7582078SBlue Swirl if (*plow >= (1ULL << 63)) { 373d7582078SBlue Swirl return 1; 374d7582078SBlue Swirl } 375d7582078SBlue Swirl } 376d7582078SBlue Swirl if (sa) { 377d7582078SBlue Swirl *phigh = -*phigh; 378d7582078SBlue Swirl } 379d7582078SBlue Swirl return 0; 380d7582078SBlue Swirl } 381d7582078SBlue Swirl 3827923057bSBlue Swirl void helper_divq_EAX(CPUX86State *env, target_ulong t0) 383d7582078SBlue Swirl { 384d7582078SBlue Swirl uint64_t r0, r1; 385d7582078SBlue Swirl 386d7582078SBlue Swirl if (t0 == 0) { 387cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 388d7582078SBlue Swirl } 3894b34e3adSliguang r0 = env->regs[R_EAX]; 39000f5e6f2Sliguang r1 = env->regs[R_EDX]; 391d7582078SBlue Swirl if (div64(&r0, &r1, t0)) { 392cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 393d7582078SBlue Swirl } 3944b34e3adSliguang env->regs[R_EAX] = r0; 39500f5e6f2Sliguang env->regs[R_EDX] = r1; 396d7582078SBlue Swirl } 397d7582078SBlue Swirl 3987923057bSBlue Swirl void helper_idivq_EAX(CPUX86State *env, target_ulong t0) 399d7582078SBlue Swirl { 400d7582078SBlue Swirl uint64_t r0, r1; 401d7582078SBlue Swirl 402d7582078SBlue Swirl if (t0 == 0) { 403cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 404d7582078SBlue Swirl } 4054b34e3adSliguang r0 = env->regs[R_EAX]; 40600f5e6f2Sliguang r1 = env->regs[R_EDX]; 407d7582078SBlue Swirl if (idiv64(&r0, &r1, t0)) { 408cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 409d7582078SBlue Swirl } 4104b34e3adSliguang env->regs[R_EAX] = r0; 41100f5e6f2Sliguang env->regs[R_EDX] = r1; 412d7582078SBlue Swirl } 413d7582078SBlue Swirl #endif 414d7582078SBlue Swirl 415f1300734SRichard Henderson #if TARGET_LONG_BITS == 32 416f1300734SRichard Henderson # define ctztl ctz32 417f1300734SRichard Henderson # define clztl clz32 418f1300734SRichard Henderson #else 419f1300734SRichard Henderson # define ctztl ctz64 420f1300734SRichard Henderson # define clztl clz64 421f1300734SRichard Henderson #endif 422f1300734SRichard Henderson 4230592f74aSRichard Henderson target_ulong helper_pdep(target_ulong src, target_ulong mask) 4240592f74aSRichard Henderson { 4250592f74aSRichard Henderson target_ulong dest = 0; 4260592f74aSRichard Henderson int i, o; 4270592f74aSRichard Henderson 4280592f74aSRichard Henderson for (i = 0; mask != 0; i++) { 4290592f74aSRichard Henderson o = ctztl(mask); 4300592f74aSRichard Henderson mask &= mask - 1; 4310592f74aSRichard Henderson dest |= ((src >> i) & 1) << o; 4320592f74aSRichard Henderson } 4330592f74aSRichard Henderson return dest; 4340592f74aSRichard Henderson } 4350592f74aSRichard Henderson 4360592f74aSRichard Henderson target_ulong helper_pext(target_ulong src, target_ulong mask) 4370592f74aSRichard Henderson { 4380592f74aSRichard Henderson target_ulong dest = 0; 4390592f74aSRichard Henderson int i, o; 4400592f74aSRichard Henderson 4410592f74aSRichard Henderson for (o = 0; mask != 0; o++) { 4420592f74aSRichard Henderson i = ctztl(mask); 4430592f74aSRichard Henderson mask &= mask - 1; 4440592f74aSRichard Henderson dest |= ((src >> i) & 1) << o; 4450592f74aSRichard Henderson } 4460592f74aSRichard Henderson return dest; 4470592f74aSRichard Henderson } 4480592f74aSRichard Henderson 449d7582078SBlue Swirl #define SHIFT 0 450d7582078SBlue Swirl #include "shift_helper_template.h" 451d7582078SBlue Swirl #undef SHIFT 452d7582078SBlue Swirl 453d7582078SBlue Swirl #define SHIFT 1 454d7582078SBlue Swirl #include "shift_helper_template.h" 455d7582078SBlue Swirl #undef SHIFT 456d7582078SBlue Swirl 457d7582078SBlue Swirl #define SHIFT 2 458d7582078SBlue Swirl #include "shift_helper_template.h" 459d7582078SBlue Swirl #undef SHIFT 460d7582078SBlue Swirl 461d7582078SBlue Swirl #ifdef TARGET_X86_64 462d7582078SBlue Swirl #define SHIFT 3 463d7582078SBlue Swirl #include "shift_helper_template.h" 464d7582078SBlue Swirl #undef SHIFT 465d7582078SBlue Swirl #endif 46607929f2aSRichard Henderson 46707929f2aSRichard Henderson /* Test that BIT is enabled in CR4. If not, raise an illegal opcode 46807929f2aSRichard Henderson exception. This reduces the requirements for rare CR4 bits being 46907929f2aSRichard Henderson mapped into HFLAGS. */ 47007929f2aSRichard Henderson void helper_cr4_testbit(CPUX86State *env, uint32_t bit) 47107929f2aSRichard Henderson { 47207929f2aSRichard Henderson if (unlikely((env->cr[4] & bit) == 0)) { 47307929f2aSRichard Henderson raise_exception_ra(env, EXCP06_ILLOP, GETPC()); 47407929f2aSRichard Henderson } 47507929f2aSRichard Henderson } 476369fd5caSRichard Henderson 477369fd5caSRichard Henderson target_ulong HELPER(rdrand)(CPUX86State *env) 478369fd5caSRichard Henderson { 479369fd5caSRichard Henderson Error *err = NULL; 480369fd5caSRichard Henderson target_ulong ret; 481369fd5caSRichard Henderson 482369fd5caSRichard Henderson if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { 483369fd5caSRichard Henderson qemu_log_mask(LOG_UNIMP, "rdrand: Crypto failure: %s", 484369fd5caSRichard Henderson error_get_pretty(err)); 485369fd5caSRichard Henderson error_free(err); 486369fd5caSRichard Henderson /* Failure clears CF and all other flags, and returns 0. */ 487369fd5caSRichard Henderson env->cc_src = 0; 488369fd5caSRichard Henderson return 0; 489369fd5caSRichard Henderson } 490369fd5caSRichard Henderson 491369fd5caSRichard Henderson /* Success sets CF and clears all others. */ 492369fd5caSRichard Henderson env->cc_src = CC_C; 493369fd5caSRichard Henderson return ret; 494369fd5caSRichard Henderson } 495