xref: /qemu/target/i386/tcg/int_helper.c (revision cd6174843b0896c9e57176159b38ecba45bade0e)
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