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"
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"
27ed69e831SClaudio Fontana #include "helper-tcg.h"
28d7582078SBlue Swirl
29d7582078SBlue Swirl //#define DEBUG_MULDIV
30d7582078SBlue Swirl
31d7582078SBlue Swirl /* division, flags are undefined */
32d7582078SBlue Swirl
helper_divb_AL(CPUX86State * env,target_ulong t0)337923057bSBlue Swirl void helper_divb_AL(CPUX86State *env, target_ulong t0)
34d7582078SBlue Swirl {
35d7582078SBlue Swirl unsigned int num, den, q, r;
36d7582078SBlue Swirl
374b34e3adSliguang num = (env->regs[R_EAX] & 0xffff);
38d7582078SBlue Swirl den = (t0 & 0xff);
39d7582078SBlue Swirl if (den == 0) {
40cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
41d7582078SBlue Swirl }
42d7582078SBlue Swirl q = (num / den);
43d7582078SBlue Swirl if (q > 0xff) {
44cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
45d7582078SBlue Swirl }
46d7582078SBlue Swirl q &= 0xff;
47d7582078SBlue Swirl r = (num % den) & 0xff;
484b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q;
49d7582078SBlue Swirl }
50d7582078SBlue Swirl
helper_idivb_AL(CPUX86State * env,target_ulong t0)517923057bSBlue Swirl void helper_idivb_AL(CPUX86State *env, target_ulong t0)
52d7582078SBlue Swirl {
53d7582078SBlue Swirl int num, den, q, r;
54d7582078SBlue Swirl
554b34e3adSliguang num = (int16_t)env->regs[R_EAX];
56d7582078SBlue Swirl den = (int8_t)t0;
57d7582078SBlue Swirl if (den == 0) {
58cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
59d7582078SBlue Swirl }
60d7582078SBlue Swirl q = (num / den);
61d7582078SBlue Swirl if (q != (int8_t)q) {
62cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
63d7582078SBlue Swirl }
64d7582078SBlue Swirl q &= 0xff;
65d7582078SBlue Swirl r = (num % den) & 0xff;
664b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | (r << 8) | q;
67d7582078SBlue Swirl }
68d7582078SBlue Swirl
helper_divw_AX(CPUX86State * env,target_ulong t0)697923057bSBlue Swirl void helper_divw_AX(CPUX86State *env, target_ulong t0)
70d7582078SBlue Swirl {
71d7582078SBlue Swirl unsigned int num, den, q, r;
72d7582078SBlue Swirl
7300f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16);
74d7582078SBlue Swirl den = (t0 & 0xffff);
75d7582078SBlue Swirl if (den == 0) {
76cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
77d7582078SBlue Swirl }
78d7582078SBlue Swirl q = (num / den);
79d7582078SBlue Swirl if (q > 0xffff) {
80cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
81d7582078SBlue Swirl }
82d7582078SBlue Swirl q &= 0xffff;
83d7582078SBlue Swirl r = (num % den) & 0xffff;
844b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q;
8500f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r;
86d7582078SBlue Swirl }
87d7582078SBlue Swirl
helper_idivw_AX(CPUX86State * env,target_ulong t0)887923057bSBlue Swirl void helper_idivw_AX(CPUX86State *env, target_ulong t0)
89d7582078SBlue Swirl {
90d7582078SBlue Swirl int num, den, q, r;
91d7582078SBlue Swirl
9200f5e6f2Sliguang num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16);
93d7582078SBlue Swirl den = (int16_t)t0;
94d7582078SBlue Swirl if (den == 0) {
95cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
96d7582078SBlue Swirl }
97d7582078SBlue Swirl q = (num / den);
98d7582078SBlue Swirl if (q != (int16_t)q) {
99cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
100d7582078SBlue Swirl }
101d7582078SBlue Swirl q &= 0xffff;
102d7582078SBlue Swirl r = (num % den) & 0xffff;
1034b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | q;
10400f5e6f2Sliguang env->regs[R_EDX] = (env->regs[R_EDX] & ~0xffff) | r;
105d7582078SBlue Swirl }
106d7582078SBlue Swirl
helper_divl_EAX(CPUX86State * env,target_ulong t0)1077923057bSBlue Swirl void helper_divl_EAX(CPUX86State *env, target_ulong t0)
108d7582078SBlue Swirl {
109d7582078SBlue Swirl unsigned int den, r;
110d7582078SBlue Swirl uint64_t num, q;
111d7582078SBlue Swirl
11200f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
113d7582078SBlue Swirl den = t0;
114d7582078SBlue Swirl if (den == 0) {
115cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
116d7582078SBlue Swirl }
117d7582078SBlue Swirl q = (num / den);
118d7582078SBlue Swirl r = (num % den);
119d7582078SBlue Swirl if (q > 0xffffffff) {
120cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
121d7582078SBlue Swirl }
1224b34e3adSliguang env->regs[R_EAX] = (uint32_t)q;
12300f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r;
124d7582078SBlue Swirl }
125d7582078SBlue Swirl
helper_idivl_EAX(CPUX86State * env,target_ulong t0)1267923057bSBlue Swirl void helper_idivl_EAX(CPUX86State *env, target_ulong t0)
127d7582078SBlue Swirl {
128d7582078SBlue Swirl int den, r;
129d7582078SBlue Swirl int64_t num, q;
130d7582078SBlue Swirl
13100f5e6f2Sliguang num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
132d7582078SBlue Swirl den = t0;
133d7582078SBlue Swirl if (den == 0) {
134cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
135d7582078SBlue Swirl }
136d7582078SBlue Swirl q = (num / den);
137d7582078SBlue Swirl r = (num % den);
138d7582078SBlue Swirl if (q != (int32_t)q) {
139cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
140d7582078SBlue Swirl }
1414b34e3adSliguang env->regs[R_EAX] = (uint32_t)q;
14200f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)r;
143d7582078SBlue Swirl }
144d7582078SBlue Swirl
145d7582078SBlue Swirl /* bcd */
146d7582078SBlue Swirl
helper_aam(target_ulong al,target_ulong base)147ec568919SPaolo Bonzini target_ulong helper_aam(target_ulong al, target_ulong base)
148d7582078SBlue Swirl {
149ec568919SPaolo Bonzini int ah;
150d7582078SBlue Swirl
151ec568919SPaolo Bonzini al &= 0xff;
152d7582078SBlue Swirl ah = al / base;
153d7582078SBlue Swirl al = al % base;
154ec568919SPaolo Bonzini return al | (ah << 8);
155d7582078SBlue Swirl }
156d7582078SBlue Swirl
helper_aad(target_ulong ax,target_ulong base)157ec568919SPaolo Bonzini target_ulong helper_aad(target_ulong ax, target_ulong base)
158d7582078SBlue Swirl {
159d7582078SBlue Swirl int al, ah;
160d7582078SBlue Swirl
161ec568919SPaolo Bonzini al = ax & 0xff;
162ec568919SPaolo Bonzini ah = (ax >> 8) & 0xff;
163d7582078SBlue Swirl al = ((ah * base) + al) & 0xff;
164ec568919SPaolo Bonzini return al;
165d7582078SBlue Swirl }
166d7582078SBlue Swirl
helper_aaa(CPUX86State * env)1677923057bSBlue Swirl void helper_aaa(CPUX86State *env)
168d7582078SBlue Swirl {
169d7582078SBlue Swirl int icarry;
170d7582078SBlue Swirl int al, ah, af;
171d7582078SBlue Swirl int eflags;
172d7582078SBlue Swirl
1732455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env);
174d7582078SBlue Swirl af = eflags & CC_A;
1754b34e3adSliguang al = env->regs[R_EAX] & 0xff;
1764b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff;
177d7582078SBlue Swirl
178d7582078SBlue Swirl icarry = (al > 0xf9);
179d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) {
180d7582078SBlue Swirl al = (al + 6) & 0x0f;
181d7582078SBlue Swirl ah = (ah + 1 + icarry) & 0xff;
182d7582078SBlue Swirl eflags |= CC_C | CC_A;
183d7582078SBlue Swirl } else {
184d7582078SBlue Swirl eflags &= ~(CC_C | CC_A);
185d7582078SBlue Swirl al &= 0x0f;
186d7582078SBlue Swirl }
1874b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8);
188d7582078SBlue Swirl CC_SRC = eflags;
189abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS;
190d7582078SBlue Swirl }
191d7582078SBlue Swirl
helper_aas(CPUX86State * env)1927923057bSBlue Swirl void helper_aas(CPUX86State *env)
193d7582078SBlue Swirl {
194d7582078SBlue Swirl int icarry;
195d7582078SBlue Swirl int al, ah, af;
196d7582078SBlue Swirl int eflags;
197d7582078SBlue Swirl
1982455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env);
199d7582078SBlue Swirl af = eflags & CC_A;
2004b34e3adSliguang al = env->regs[R_EAX] & 0xff;
2014b34e3adSliguang ah = (env->regs[R_EAX] >> 8) & 0xff;
202d7582078SBlue Swirl
203d7582078SBlue Swirl icarry = (al < 6);
204d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) {
205d7582078SBlue Swirl al = (al - 6) & 0x0f;
206d7582078SBlue Swirl ah = (ah - 1 - icarry) & 0xff;
207d7582078SBlue Swirl eflags |= CC_C | CC_A;
208d7582078SBlue Swirl } else {
209d7582078SBlue Swirl eflags &= ~(CC_C | CC_A);
210d7582078SBlue Swirl al &= 0x0f;
211d7582078SBlue Swirl }
2124b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xffff) | al | (ah << 8);
213d7582078SBlue Swirl CC_SRC = eflags;
214abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS;
215d7582078SBlue Swirl }
216d7582078SBlue Swirl
helper_daa(CPUX86State * env)2177923057bSBlue Swirl void helper_daa(CPUX86State *env)
218d7582078SBlue Swirl {
219d7582078SBlue Swirl int old_al, al, af, cf;
220d7582078SBlue Swirl int eflags;
221d7582078SBlue Swirl
2222455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env);
223d7582078SBlue Swirl cf = eflags & CC_C;
224d7582078SBlue Swirl af = eflags & CC_A;
2254b34e3adSliguang old_al = al = env->regs[R_EAX] & 0xff;
226d7582078SBlue Swirl
227d7582078SBlue Swirl eflags = 0;
228d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) {
229d7582078SBlue Swirl al = (al + 6) & 0xff;
230d7582078SBlue Swirl eflags |= CC_A;
231d7582078SBlue Swirl }
232d7582078SBlue Swirl if ((old_al > 0x99) || cf) {
233d7582078SBlue Swirl al = (al + 0x60) & 0xff;
234d7582078SBlue Swirl eflags |= CC_C;
235d7582078SBlue Swirl }
2364b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al;
237d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */
238d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */
239*24899cdcSPaolo Bonzini eflags |= compute_pf(al);
240d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */
241d7582078SBlue Swirl CC_SRC = eflags;
242abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS;
243d7582078SBlue Swirl }
244d7582078SBlue Swirl
helper_das(CPUX86State * env)2457923057bSBlue Swirl void helper_das(CPUX86State *env)
246d7582078SBlue Swirl {
247d7582078SBlue Swirl int al, al1, af, cf;
248d7582078SBlue Swirl int eflags;
249d7582078SBlue Swirl
2502455e9cfSPaolo Bonzini eflags = cpu_cc_compute_all(env);
251d7582078SBlue Swirl cf = eflags & CC_C;
252d7582078SBlue Swirl af = eflags & CC_A;
2534b34e3adSliguang al = env->regs[R_EAX] & 0xff;
254d7582078SBlue Swirl
255d7582078SBlue Swirl eflags = 0;
256d7582078SBlue Swirl al1 = al;
257d7582078SBlue Swirl if (((al & 0x0f) > 9) || af) {
258d7582078SBlue Swirl eflags |= CC_A;
259d7582078SBlue Swirl if (al < 6 || cf) {
260d7582078SBlue Swirl eflags |= CC_C;
261d7582078SBlue Swirl }
262d7582078SBlue Swirl al = (al - 6) & 0xff;
263d7582078SBlue Swirl }
264d7582078SBlue Swirl if ((al1 > 0x99) || cf) {
265d7582078SBlue Swirl al = (al - 0x60) & 0xff;
266d7582078SBlue Swirl eflags |= CC_C;
267d7582078SBlue Swirl }
2684b34e3adSliguang env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | al;
269d7582078SBlue Swirl /* well, speed is not an issue here, so we compute the flags by hand */
270d7582078SBlue Swirl eflags |= (al == 0) << 6; /* zf */
271*24899cdcSPaolo Bonzini eflags |= compute_pf(al);
272d7582078SBlue Swirl eflags |= (al & 0x80); /* sf */
273d7582078SBlue Swirl CC_SRC = eflags;
274abdcc5c8SPaolo Bonzini CC_OP = CC_OP_EFLAGS;
275d7582078SBlue Swirl }
276d7582078SBlue Swirl
277d7582078SBlue Swirl #ifdef TARGET_X86_64
add128(uint64_t * plow,uint64_t * phigh,uint64_t a,uint64_t b)278d7582078SBlue Swirl static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
279d7582078SBlue Swirl {
280d7582078SBlue Swirl *plow += a;
281d7582078SBlue Swirl /* carry test */
282d7582078SBlue Swirl if (*plow < a) {
283d7582078SBlue Swirl (*phigh)++;
284d7582078SBlue Swirl }
285d7582078SBlue Swirl *phigh += b;
286d7582078SBlue Swirl }
287d7582078SBlue Swirl
neg128(uint64_t * plow,uint64_t * phigh)288d7582078SBlue Swirl static void neg128(uint64_t *plow, uint64_t *phigh)
289d7582078SBlue Swirl {
290d7582078SBlue Swirl *plow = ~*plow;
291d7582078SBlue Swirl *phigh = ~*phigh;
292d7582078SBlue Swirl add128(plow, phigh, 1, 0);
293d7582078SBlue Swirl }
294d7582078SBlue Swirl
295d7582078SBlue Swirl /* return TRUE if overflow */
div64(uint64_t * plow,uint64_t * phigh,uint64_t b)296d7582078SBlue Swirl static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
297d7582078SBlue Swirl {
298d7582078SBlue Swirl uint64_t q, r, a1, a0;
299d7582078SBlue Swirl int i, qb, ab;
300d7582078SBlue Swirl
301d7582078SBlue Swirl a0 = *plow;
302d7582078SBlue Swirl a1 = *phigh;
303d7582078SBlue Swirl if (a1 == 0) {
304d7582078SBlue Swirl q = a0 / b;
305d7582078SBlue Swirl r = a0 % b;
306d7582078SBlue Swirl *plow = q;
307d7582078SBlue Swirl *phigh = r;
308d7582078SBlue Swirl } else {
309d7582078SBlue Swirl if (a1 >= b) {
310d7582078SBlue Swirl return 1;
311d7582078SBlue Swirl }
312d7582078SBlue Swirl /* XXX: use a better algorithm */
313d7582078SBlue Swirl for (i = 0; i < 64; i++) {
314d7582078SBlue Swirl ab = a1 >> 63;
315d7582078SBlue Swirl a1 = (a1 << 1) | (a0 >> 63);
316d7582078SBlue Swirl if (ab || a1 >= b) {
317d7582078SBlue Swirl a1 -= b;
318d7582078SBlue Swirl qb = 1;
319d7582078SBlue Swirl } else {
320d7582078SBlue Swirl qb = 0;
321d7582078SBlue Swirl }
322d7582078SBlue Swirl a0 = (a0 << 1) | qb;
323d7582078SBlue Swirl }
324d7582078SBlue Swirl #if defined(DEBUG_MULDIV)
325d7582078SBlue Swirl printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64
326d7582078SBlue Swirl ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
327d7582078SBlue Swirl *phigh, *plow, b, a0, a1);
328d7582078SBlue Swirl #endif
329d7582078SBlue Swirl *plow = a0;
330d7582078SBlue Swirl *phigh = a1;
331d7582078SBlue Swirl }
332d7582078SBlue Swirl return 0;
333d7582078SBlue Swirl }
334d7582078SBlue Swirl
335d7582078SBlue Swirl /* return TRUE if overflow */
idiv64(uint64_t * plow,uint64_t * phigh,int64_t b)336d7582078SBlue Swirl static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
337d7582078SBlue Swirl {
338d7582078SBlue Swirl int sa, sb;
339d7582078SBlue Swirl
340d7582078SBlue Swirl sa = ((int64_t)*phigh < 0);
341d7582078SBlue Swirl if (sa) {
342d7582078SBlue Swirl neg128(plow, phigh);
343d7582078SBlue Swirl }
344d7582078SBlue Swirl sb = (b < 0);
345d7582078SBlue Swirl if (sb) {
346d7582078SBlue Swirl b = -b;
347d7582078SBlue Swirl }
348d7582078SBlue Swirl if (div64(plow, phigh, b) != 0) {
349d7582078SBlue Swirl return 1;
350d7582078SBlue Swirl }
351d7582078SBlue Swirl if (sa ^ sb) {
352d7582078SBlue Swirl if (*plow > (1ULL << 63)) {
353d7582078SBlue Swirl return 1;
354d7582078SBlue Swirl }
355d7582078SBlue Swirl *plow = -*plow;
356d7582078SBlue Swirl } else {
357d7582078SBlue Swirl if (*plow >= (1ULL << 63)) {
358d7582078SBlue Swirl return 1;
359d7582078SBlue Swirl }
360d7582078SBlue Swirl }
361d7582078SBlue Swirl if (sa) {
362d7582078SBlue Swirl *phigh = -*phigh;
363d7582078SBlue Swirl }
364d7582078SBlue Swirl return 0;
365d7582078SBlue Swirl }
366d7582078SBlue Swirl
helper_divq_EAX(CPUX86State * env,target_ulong t0)3677923057bSBlue Swirl void helper_divq_EAX(CPUX86State *env, target_ulong t0)
368d7582078SBlue Swirl {
369d7582078SBlue Swirl uint64_t r0, r1;
370d7582078SBlue Swirl
371d7582078SBlue Swirl if (t0 == 0) {
372cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
373d7582078SBlue Swirl }
3744b34e3adSliguang r0 = env->regs[R_EAX];
37500f5e6f2Sliguang r1 = env->regs[R_EDX];
376d7582078SBlue Swirl if (div64(&r0, &r1, t0)) {
377cc33c5d6SPavel Dovgalyuk raise_exception_ra(env, EXCP00_DIVZ, GETPC());
378d7582078SBlue Swirl }
3794b34e3adSliguang env->regs[R_EAX] = r0;
38000f5e6f2Sliguang env->regs[R_EDX] = r1;
381d7582078SBlue Swirl }
382d7582078SBlue Swirl
helper_idivq_EAX(CPUX86State * env,target_ulong t0)3837923057bSBlue Swirl void helper_idivq_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 (idiv64(&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 #endif
399d7582078SBlue Swirl
400f1300734SRichard Henderson #if TARGET_LONG_BITS == 32
401f1300734SRichard Henderson # define ctztl ctz32
402f1300734SRichard Henderson # define clztl clz32
403f1300734SRichard Henderson #else
404f1300734SRichard Henderson # define ctztl ctz64
405f1300734SRichard Henderson # define clztl clz64
406f1300734SRichard Henderson #endif
407f1300734SRichard Henderson
helper_pdep(target_ulong src,target_ulong mask)4080592f74aSRichard Henderson target_ulong helper_pdep(target_ulong src, target_ulong mask)
4090592f74aSRichard Henderson {
4100592f74aSRichard Henderson target_ulong dest = 0;
4110592f74aSRichard Henderson int i, o;
4120592f74aSRichard Henderson
4130592f74aSRichard Henderson for (i = 0; mask != 0; i++) {
4140592f74aSRichard Henderson o = ctztl(mask);
4150592f74aSRichard Henderson mask &= mask - 1;
4160592f74aSRichard Henderson dest |= ((src >> i) & 1) << o;
4170592f74aSRichard Henderson }
4180592f74aSRichard Henderson return dest;
4190592f74aSRichard Henderson }
4200592f74aSRichard Henderson
helper_pext(target_ulong src,target_ulong mask)4210592f74aSRichard Henderson target_ulong helper_pext(target_ulong src, target_ulong mask)
4220592f74aSRichard Henderson {
4230592f74aSRichard Henderson target_ulong dest = 0;
4240592f74aSRichard Henderson int i, o;
4250592f74aSRichard Henderson
4260592f74aSRichard Henderson for (o = 0; mask != 0; o++) {
4270592f74aSRichard Henderson i = ctztl(mask);
4280592f74aSRichard Henderson mask &= mask - 1;
4290592f74aSRichard Henderson dest |= ((src >> i) & 1) << o;
4300592f74aSRichard Henderson }
4310592f74aSRichard Henderson return dest;
4320592f74aSRichard Henderson }
4330592f74aSRichard Henderson
43407929f2aSRichard Henderson /* Test that BIT is enabled in CR4. If not, raise an illegal opcode
43507929f2aSRichard Henderson exception. This reduces the requirements for rare CR4 bits being
43607929f2aSRichard Henderson mapped into HFLAGS. */
helper_cr4_testbit(CPUX86State * env,uint32_t bit)43707929f2aSRichard Henderson void helper_cr4_testbit(CPUX86State *env, uint32_t bit)
43807929f2aSRichard Henderson {
43907929f2aSRichard Henderson if (unlikely((env->cr[4] & bit) == 0)) {
44007929f2aSRichard Henderson raise_exception_ra(env, EXCP06_ILLOP, GETPC());
44107929f2aSRichard Henderson }
44207929f2aSRichard Henderson }
443369fd5caSRichard Henderson
HELPER(rdrand)444369fd5caSRichard Henderson target_ulong HELPER(rdrand)(CPUX86State *env)
445369fd5caSRichard Henderson {
446369fd5caSRichard Henderson Error *err = NULL;
447369fd5caSRichard Henderson target_ulong ret;
448369fd5caSRichard Henderson
449369fd5caSRichard Henderson if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
450369fd5caSRichard Henderson qemu_log_mask(LOG_UNIMP, "rdrand: Crypto failure: %s",
451369fd5caSRichard Henderson error_get_pretty(err));
452369fd5caSRichard Henderson error_free(err);
453369fd5caSRichard Henderson /* Failure clears CF and all other flags, and returns 0. */
454369fd5caSRichard Henderson env->cc_src = 0;
455abdcc5c8SPaolo Bonzini ret = 0;
456abdcc5c8SPaolo Bonzini } else {
457369fd5caSRichard Henderson /* Success sets CF and clears all others. */
458369fd5caSRichard Henderson env->cc_src = CC_C;
459abdcc5c8SPaolo Bonzini }
460abdcc5c8SPaolo Bonzini env->cc_op = CC_OP_EFLAGS;
461369fd5caSRichard Henderson return ret;
462369fd5caSRichard Henderson }
463