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" 21*cd617484SPhilippe 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 /* modulo 9 table */ 33d7582078SBlue Swirl static const uint8_t rclb_table[32] = { 34d7582078SBlue Swirl 0, 1, 2, 3, 4, 5, 6, 7, 35d7582078SBlue Swirl 8, 0, 1, 2, 3, 4, 5, 6, 36d7582078SBlue Swirl 7, 8, 0, 1, 2, 3, 4, 5, 37d7582078SBlue Swirl 6, 7, 8, 0, 1, 2, 3, 4, 38d7582078SBlue Swirl }; 39d7582078SBlue Swirl 40d7582078SBlue Swirl /* modulo 17 table */ 41d7582078SBlue Swirl static const uint8_t rclw_table[32] = { 42d7582078SBlue Swirl 0, 1, 2, 3, 4, 5, 6, 7, 43d7582078SBlue Swirl 8, 9, 10, 11, 12, 13, 14, 15, 44d7582078SBlue Swirl 16, 0, 1, 2, 3, 4, 5, 6, 45d7582078SBlue Swirl 7, 8, 9, 10, 11, 12, 13, 14, 46d7582078SBlue Swirl }; 47d7582078SBlue Swirl 48d7582078SBlue Swirl /* division, flags are undefined */ 49d7582078SBlue Swirl 507923057bSBlue Swirl void helper_divb_AL(CPUX86State *env, target_ulong t0) 51d7582078SBlue Swirl { 52d7582078SBlue Swirl unsigned int num, den, q, r; 53d7582078SBlue Swirl 544b34e3adSliguang num = (env->regs[R_EAX] & 0xffff); 55d7582078SBlue Swirl den = (t0 & 0xff); 56d7582078SBlue Swirl if (den == 0) { 57cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 58d7582078SBlue Swirl } 59d7582078SBlue Swirl q = (num / den); 60d7582078SBlue Swirl if (q > 0xff) { 61cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 62d7582078SBlue Swirl } 63d7582078SBlue Swirl q &= 0xff; 64d7582078SBlue Swirl r = (num % den) & 0xff; 654b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q; 66d7582078SBlue Swirl } 67d7582078SBlue Swirl 687923057bSBlue Swirl void helper_idivb_AL(CPUX86State *env, target_ulong t0) 69d7582078SBlue Swirl { 70d7582078SBlue Swirl int num, den, q, r; 71d7582078SBlue Swirl 724b34e3adSliguang num = (int16_t)env->regs[R_EAX]; 73d7582078SBlue Swirl den = (int8_t)t0; 74d7582078SBlue Swirl if (den == 0) { 75cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 76d7582078SBlue Swirl } 77d7582078SBlue Swirl q = (num / den); 78d7582078SBlue Swirl if (q != (int8_t)q) { 79cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 80d7582078SBlue Swirl } 81d7582078SBlue Swirl q &= 0xff; 82d7582078SBlue Swirl r = (num % den) & 0xff; 834b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q; 84d7582078SBlue Swirl } 85d7582078SBlue Swirl 867923057bSBlue Swirl void helper_divw_AX(CPUX86State *env, target_ulong t0) 87d7582078SBlue Swirl { 88d7582078SBlue Swirl unsigned int num, den, q, r; 89d7582078SBlue Swirl 9000f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16); 91d7582078SBlue Swirl den = (t0 & 0xffff); 92d7582078SBlue Swirl if (den == 0) { 93cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 94d7582078SBlue Swirl } 95d7582078SBlue Swirl q = (num / den); 96d7582078SBlue Swirl if (q > 0xffff) { 97cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 98d7582078SBlue Swirl } 99d7582078SBlue Swirl q &= 0xffff; 100d7582078SBlue Swirl r = (num % den) & 0xffff; 1014b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q; 10200f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r; 103d7582078SBlue Swirl } 104d7582078SBlue Swirl 1057923057bSBlue Swirl void helper_idivw_AX(CPUX86State *env, target_ulong t0) 106d7582078SBlue Swirl { 107d7582078SBlue Swirl int num, den, q, r; 108d7582078SBlue Swirl 10900f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16); 110d7582078SBlue Swirl den = (int16_t)t0; 111d7582078SBlue Swirl if (den == 0) { 112cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 113d7582078SBlue Swirl } 114d7582078SBlue Swirl q = (num / den); 115d7582078SBlue Swirl if (q != (int16_t)q) { 116cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 117d7582078SBlue Swirl } 118d7582078SBlue Swirl q &= 0xffff; 119d7582078SBlue Swirl r = (num % den) & 0xffff; 1204b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q; 12100f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r; 122d7582078SBlue Swirl } 123d7582078SBlue Swirl 1247923057bSBlue Swirl void helper_divl_EAX(CPUX86State *env, target_ulong t0) 125d7582078SBlue Swirl { 126d7582078SBlue Swirl unsigned int den, r; 127d7582078SBlue Swirl uint64_t num, q; 128d7582078SBlue Swirl 12900f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 130d7582078SBlue Swirl den = t0; 131d7582078SBlue Swirl if (den == 0) { 132cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 133d7582078SBlue Swirl } 134d7582078SBlue Swirl q = (num / den); 135d7582078SBlue Swirl r = (num % den); 136d7582078SBlue Swirl if (q > 0xffffffff) { 137cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 138d7582078SBlue Swirl } 1394b34e3adSliguang env->regs[R_EAX] = (uint32_t)q; 14000f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r; 141d7582078SBlue Swirl } 142d7582078SBlue Swirl 1437923057bSBlue Swirl void helper_idivl_EAX(CPUX86State *env, target_ulong t0) 144d7582078SBlue Swirl { 145d7582078SBlue Swirl int den, r; 146d7582078SBlue Swirl int64_t num, q; 147d7582078SBlue Swirl 14800f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 149d7582078SBlue Swirl den = t0; 150d7582078SBlue Swirl if (den == 0) { 151cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 152d7582078SBlue Swirl } 153d7582078SBlue Swirl q = (num / den); 154d7582078SBlue Swirl r = (num % den); 155d7582078SBlue Swirl if (q != (int32_t)q) { 156cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 157d7582078SBlue Swirl } 1584b34e3adSliguang env->regs[R_EAX] = (uint32_t)q; 15900f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r; 160d7582078SBlue Swirl } 161d7582078SBlue Swirl 162d7582078SBlue Swirl /* bcd */ 163d7582078SBlue Swirl 164d7582078SBlue Swirl /* XXX: exception */ 1657923057bSBlue Swirl void helper_aam(CPUX86State *env, int base) 166d7582078SBlue Swirl { 167d7582078SBlue Swirl int al, ah; 168d7582078SBlue Swirl 1694b34e3adSliguang al = env->regs[R_EAX] & 0xff; 170d7582078SBlue Swirl ah = al / base; 171d7582078SBlue Swirl al = al % base; 1724b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 173d7582078SBlue Swirl CC_DST = al; 174d7582078SBlue Swirl } 175d7582078SBlue Swirl 1767923057bSBlue Swirl void helper_aad(CPUX86State *env, int base) 177d7582078SBlue Swirl { 178d7582078SBlue Swirl int al, ah; 179d7582078SBlue Swirl 1804b34e3adSliguang al = env->regs[R_EAX] & 0xff; 1814b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 182d7582078SBlue Swirl al = ((ah * base) + al) & 0xff; 1834b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al; 184d7582078SBlue Swirl CC_DST = al; 185d7582078SBlue Swirl } 186d7582078SBlue Swirl 1877923057bSBlue Swirl void helper_aaa(CPUX86State *env) 188d7582078SBlue Swirl { 189d7582078SBlue Swirl int icarry; 190d7582078SBlue Swirl int al, ah, af; 191d7582078SBlue Swirl int eflags; 192d7582078SBlue Swirl 193f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 194d7582078SBlue Swirl af = eflags & CC_A; 1954b34e3adSliguang al = env->regs[R_EAX] & 0xff; 1964b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 197d7582078SBlue Swirl 198d7582078SBlue Swirl icarry = (al > 0xf9); 199d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 200d7582078SBlue Swirl al = (al + 6) & 0x0f; 201d7582078SBlue Swirl ah = (ah + 1 + icarry) & 0xff; 202d7582078SBlue Swirl eflags |= CC_C | CC_A; 203d7582078SBlue Swirl } else { 204d7582078SBlue Swirl eflags &= ~(CC_C | CC_A); 205d7582078SBlue Swirl al &= 0x0f; 206d7582078SBlue Swirl } 2074b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 208d7582078SBlue Swirl CC_SRC = eflags; 209d7582078SBlue Swirl } 210d7582078SBlue Swirl 2117923057bSBlue Swirl void helper_aas(CPUX86State *env) 212d7582078SBlue Swirl { 213d7582078SBlue Swirl int icarry; 214d7582078SBlue Swirl int al, ah, af; 215d7582078SBlue Swirl int eflags; 216d7582078SBlue Swirl 217f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 218d7582078SBlue Swirl af = eflags & CC_A; 2194b34e3adSliguang al = env->regs[R_EAX] & 0xff; 2204b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff; 221d7582078SBlue Swirl 222d7582078SBlue Swirl icarry = (al < 6); 223d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 224d7582078SBlue Swirl al = (al - 6) & 0x0f; 225d7582078SBlue Swirl ah = (ah - 1 - icarry) & 0xff; 226d7582078SBlue Swirl eflags |= CC_C | CC_A; 227d7582078SBlue Swirl } else { 228d7582078SBlue Swirl eflags &= ~(CC_C | CC_A); 229d7582078SBlue Swirl al &= 0x0f; 230d7582078SBlue Swirl } 2314b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8); 232d7582078SBlue Swirl CC_SRC = eflags; 233d7582078SBlue Swirl } 234d7582078SBlue Swirl 2357923057bSBlue Swirl void helper_daa(CPUX86State *env) 236d7582078SBlue Swirl { 237d7582078SBlue Swirl int old_al, al, af, cf; 238d7582078SBlue Swirl int eflags; 239d7582078SBlue Swirl 240f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 241d7582078SBlue Swirl cf = eflags & CC_C; 242d7582078SBlue Swirl af = eflags & CC_A; 2434b34e3adSliguang old_al = al = env->regs[R_EAX] & 0xff; 244d7582078SBlue Swirl 245d7582078SBlue Swirl eflags = 0; 246d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 247d7582078SBlue Swirl al = (al + 6) & 0xff; 248d7582078SBlue Swirl eflags |= CC_A; 249d7582078SBlue Swirl } 250d7582078SBlue Swirl if ((old_al > 0x99) || cf) { 251d7582078SBlue Swirl al = (al + 0x60) & 0xff; 252d7582078SBlue Swirl eflags |= CC_C; 253d7582078SBlue Swirl } 2544b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al; 255d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */ 256d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */ 257d7582078SBlue Swirl eflags |= parity_table[al]; /* pf */ 258d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */ 259d7582078SBlue Swirl CC_SRC = eflags; 260d7582078SBlue Swirl } 261d7582078SBlue Swirl 2627923057bSBlue Swirl void helper_das(CPUX86State *env) 263d7582078SBlue Swirl { 264d7582078SBlue Swirl int al, al1, af, cf; 265d7582078SBlue Swirl int eflags; 266d7582078SBlue Swirl 267f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 268d7582078SBlue Swirl cf = eflags & CC_C; 269d7582078SBlue Swirl af = eflags & CC_A; 2704b34e3adSliguang al = env->regs[R_EAX] & 0xff; 271d7582078SBlue Swirl 272d7582078SBlue Swirl eflags = 0; 273d7582078SBlue Swirl al1 = al; 274d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) { 275d7582078SBlue Swirl eflags |= CC_A; 276d7582078SBlue Swirl if (al < 6 || cf) { 277d7582078SBlue Swirl eflags |= CC_C; 278d7582078SBlue Swirl } 279d7582078SBlue Swirl al = (al - 6) & 0xff; 280d7582078SBlue Swirl } 281d7582078SBlue Swirl if ((al1 > 0x99) || cf) { 282d7582078SBlue Swirl al = (al - 0x60) & 0xff; 283d7582078SBlue Swirl eflags |= CC_C; 284d7582078SBlue Swirl } 2854b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al; 286d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */ 287d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */ 288d7582078SBlue Swirl eflags |= parity_table[al]; /* pf */ 289d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */ 290d7582078SBlue Swirl CC_SRC = eflags; 291d7582078SBlue Swirl } 292d7582078SBlue Swirl 293d7582078SBlue Swirl #ifdef TARGET_X86_64 294d7582078SBlue Swirl static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) 295d7582078SBlue Swirl { 296d7582078SBlue Swirl *plow += a; 297d7582078SBlue Swirl /* carry test */ 298d7582078SBlue Swirl if (*plow < a) { 299d7582078SBlue Swirl (*phigh)++; 300d7582078SBlue Swirl } 301d7582078SBlue Swirl *phigh += b; 302d7582078SBlue Swirl } 303d7582078SBlue Swirl 304d7582078SBlue Swirl static void neg128(uint64_t *plow, uint64_t *phigh) 305d7582078SBlue Swirl { 306d7582078SBlue Swirl *plow = ~*plow; 307d7582078SBlue Swirl *phigh = ~*phigh; 308d7582078SBlue Swirl add128(plow, phigh, 1, 0); 309d7582078SBlue Swirl } 310d7582078SBlue Swirl 311d7582078SBlue Swirl /* return TRUE if overflow */ 312d7582078SBlue Swirl static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b) 313d7582078SBlue Swirl { 314d7582078SBlue Swirl uint64_t q, r, a1, a0; 315d7582078SBlue Swirl int i, qb, ab; 316d7582078SBlue Swirl 317d7582078SBlue Swirl a0 = *plow; 318d7582078SBlue Swirl a1 = *phigh; 319d7582078SBlue Swirl if (a1 == 0) { 320d7582078SBlue Swirl q = a0 / b; 321d7582078SBlue Swirl r = a0 % b; 322d7582078SBlue Swirl *plow = q; 323d7582078SBlue Swirl *phigh = r; 324d7582078SBlue Swirl } else { 325d7582078SBlue Swirl if (a1 >= b) { 326d7582078SBlue Swirl return 1; 327d7582078SBlue Swirl } 328d7582078SBlue Swirl /* XXX: use a better algorithm */ 329d7582078SBlue Swirl for (i = 0; i < 64; i++) { 330d7582078SBlue Swirl ab = a1 >> 63; 331d7582078SBlue Swirl a1 = (a1 << 1) | (a0 >> 63); 332d7582078SBlue Swirl if (ab || a1 >= b) { 333d7582078SBlue Swirl a1 -= b; 334d7582078SBlue Swirl qb = 1; 335d7582078SBlue Swirl } else { 336d7582078SBlue Swirl qb = 0; 337d7582078SBlue Swirl } 338d7582078SBlue Swirl a0 = (a0 << 1) | qb; 339d7582078SBlue Swirl } 340d7582078SBlue Swirl #if defined(DEBUG_MULDIV) 341d7582078SBlue Swirl printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 342d7582078SBlue Swirl ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n", 343d7582078SBlue Swirl *phigh, *plow, b, a0, a1); 344d7582078SBlue Swirl #endif 345d7582078SBlue Swirl *plow = a0; 346d7582078SBlue Swirl *phigh = a1; 347d7582078SBlue Swirl } 348d7582078SBlue Swirl return 0; 349d7582078SBlue Swirl } 350d7582078SBlue Swirl 351d7582078SBlue Swirl /* return TRUE if overflow */ 352d7582078SBlue Swirl static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) 353d7582078SBlue Swirl { 354d7582078SBlue Swirl int sa, sb; 355d7582078SBlue Swirl 356d7582078SBlue Swirl sa = ((int64_t)*phigh < 0); 357d7582078SBlue Swirl if (sa) { 358d7582078SBlue Swirl neg128(plow, phigh); 359d7582078SBlue Swirl } 360d7582078SBlue Swirl sb = (b < 0); 361d7582078SBlue Swirl if (sb) { 362d7582078SBlue Swirl b = -b; 363d7582078SBlue Swirl } 364d7582078SBlue Swirl if (div64(plow, phigh, b) != 0) { 365d7582078SBlue Swirl return 1; 366d7582078SBlue Swirl } 367d7582078SBlue Swirl if (sa ^ sb) { 368d7582078SBlue Swirl if (*plow > (1ULL << 63)) { 369d7582078SBlue Swirl return 1; 370d7582078SBlue Swirl } 371d7582078SBlue Swirl *plow = -*plow; 372d7582078SBlue Swirl } else { 373d7582078SBlue Swirl if (*plow >= (1ULL << 63)) { 374d7582078SBlue Swirl return 1; 375d7582078SBlue Swirl } 376d7582078SBlue Swirl } 377d7582078SBlue Swirl if (sa) { 378d7582078SBlue Swirl *phigh = -*phigh; 379d7582078SBlue Swirl } 380d7582078SBlue Swirl return 0; 381d7582078SBlue Swirl } 382d7582078SBlue Swirl 3837923057bSBlue Swirl void helper_divq_EAX(CPUX86State *env, target_ulong t0) 384d7582078SBlue Swirl { 385d7582078SBlue Swirl uint64_t r0, r1; 386d7582078SBlue Swirl 387d7582078SBlue Swirl if (t0 == 0) { 388cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 389d7582078SBlue Swirl } 3904b34e3adSliguang r0 = env->regs[R_EAX]; 39100f5e6f2Sliguang r1 = env->regs[R_EDX]; 392d7582078SBlue Swirl if (div64(&r0, &r1, t0)) { 393cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 394d7582078SBlue Swirl } 3954b34e3adSliguang env->regs[R_EAX] = r0; 39600f5e6f2Sliguang env->regs[R_EDX] = r1; 397d7582078SBlue Swirl } 398d7582078SBlue Swirl 3997923057bSBlue Swirl void helper_idivq_EAX(CPUX86State *env, target_ulong t0) 400d7582078SBlue Swirl { 401d7582078SBlue Swirl uint64_t r0, r1; 402d7582078SBlue Swirl 403d7582078SBlue Swirl if (t0 == 0) { 404cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 405d7582078SBlue Swirl } 4064b34e3adSliguang r0 = env->regs[R_EAX]; 40700f5e6f2Sliguang r1 = env->regs[R_EDX]; 408d7582078SBlue Swirl if (idiv64(&r0, &r1, t0)) { 409cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC()); 410d7582078SBlue Swirl } 4114b34e3adSliguang env->regs[R_EAX] = r0; 41200f5e6f2Sliguang env->regs[R_EDX] = r1; 413d7582078SBlue Swirl } 414d7582078SBlue Swirl #endif 415d7582078SBlue Swirl 416f1300734SRichard Henderson #if TARGET_LONG_BITS == 32 417f1300734SRichard Henderson # define ctztl ctz32 418f1300734SRichard Henderson # define clztl clz32 419f1300734SRichard Henderson #else 420f1300734SRichard Henderson # define ctztl ctz64 421f1300734SRichard Henderson # define clztl clz64 422f1300734SRichard Henderson #endif 423f1300734SRichard Henderson 4240592f74aSRichard Henderson target_ulong helper_pdep(target_ulong src, target_ulong mask) 4250592f74aSRichard Henderson { 4260592f74aSRichard Henderson target_ulong dest = 0; 4270592f74aSRichard Henderson int i, o; 4280592f74aSRichard Henderson 4290592f74aSRichard Henderson for (i = 0; mask != 0; i++) { 4300592f74aSRichard Henderson o = ctztl(mask); 4310592f74aSRichard Henderson mask &= mask - 1; 4320592f74aSRichard Henderson dest |= ((src >> i) & 1) << o; 4330592f74aSRichard Henderson } 4340592f74aSRichard Henderson return dest; 4350592f74aSRichard Henderson } 4360592f74aSRichard Henderson 4370592f74aSRichard Henderson target_ulong helper_pext(target_ulong src, target_ulong mask) 4380592f74aSRichard Henderson { 4390592f74aSRichard Henderson target_ulong dest = 0; 4400592f74aSRichard Henderson int i, o; 4410592f74aSRichard Henderson 4420592f74aSRichard Henderson for (o = 0; mask != 0; o++) { 4430592f74aSRichard Henderson i = ctztl(mask); 4440592f74aSRichard Henderson mask &= mask - 1; 4450592f74aSRichard Henderson dest |= ((src >> i) & 1) << o; 4460592f74aSRichard Henderson } 4470592f74aSRichard Henderson return dest; 4480592f74aSRichard Henderson } 4490592f74aSRichard Henderson 450d7582078SBlue Swirl #define SHIFT 0 451d7582078SBlue Swirl #include "shift_helper_template.h" 452d7582078SBlue Swirl #undef SHIFT 453d7582078SBlue Swirl 454d7582078SBlue Swirl #define SHIFT 1 455d7582078SBlue Swirl #include "shift_helper_template.h" 456d7582078SBlue Swirl #undef SHIFT 457d7582078SBlue Swirl 458d7582078SBlue Swirl #define SHIFT 2 459d7582078SBlue Swirl #include "shift_helper_template.h" 460d7582078SBlue Swirl #undef SHIFT 461d7582078SBlue Swirl 462d7582078SBlue Swirl #ifdef TARGET_X86_64 463d7582078SBlue Swirl #define SHIFT 3 464d7582078SBlue Swirl #include "shift_helper_template.h" 465d7582078SBlue Swirl #undef SHIFT 466d7582078SBlue Swirl #endif 46707929f2aSRichard Henderson 46807929f2aSRichard Henderson /* Test that BIT is enabled in CR4. If not, raise an illegal opcode 46907929f2aSRichard Henderson exception. This reduces the requirements for rare CR4 bits being 47007929f2aSRichard Henderson mapped into HFLAGS. */ 47107929f2aSRichard Henderson void helper_cr4_testbit(CPUX86State *env, uint32_t bit) 47207929f2aSRichard Henderson { 47307929f2aSRichard Henderson if (unlikely((env->cr[4] & bit) == 0)) { 47407929f2aSRichard Henderson raise_exception_ra(env, EXCP06_ILLOP, GETPC()); 47507929f2aSRichard Henderson } 47607929f2aSRichard Henderson } 477369fd5caSRichard Henderson 478369fd5caSRichard Henderson target_ulong HELPER(rdrand)(CPUX86State *env) 479369fd5caSRichard Henderson { 480369fd5caSRichard Henderson Error *err = NULL; 481369fd5caSRichard Henderson target_ulong ret; 482369fd5caSRichard Henderson 483369fd5caSRichard Henderson if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { 484369fd5caSRichard Henderson qemu_log_mask(LOG_UNIMP, "rdrand: Crypto failure: %s", 485369fd5caSRichard Henderson error_get_pretty(err)); 486369fd5caSRichard Henderson error_free(err); 487369fd5caSRichard Henderson /* Failure clears CF and all other flags, and returns 0. */ 488369fd5caSRichard Henderson env->cc_src = 0; 489369fd5caSRichard Henderson return 0; 490369fd5caSRichard Henderson } 491369fd5caSRichard Henderson 492369fd5caSRichard Henderson /* Success sets CF and clears all others. */ 493369fd5caSRichard Henderson env->cc_src = CC_C; 494369fd5caSRichard Henderson return ret; 495369fd5caSRichard Henderson } 496