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