root / target-i386 / int_helper.c @ 4d5b97da
History | View | Annotate | Download (10.4 kB)
1 | d7582078 | Blue Swirl | /*
|
---|---|---|---|
2 | d7582078 | Blue Swirl | * x86 integer helpers
|
3 | d7582078 | Blue Swirl | *
|
4 | d7582078 | Blue Swirl | * Copyright (c) 2003 Fabrice Bellard
|
5 | d7582078 | Blue Swirl | *
|
6 | d7582078 | Blue Swirl | * This library is free software; you can redistribute it and/or
|
7 | d7582078 | Blue Swirl | * modify it under the terms of the GNU Lesser General Public
|
8 | d7582078 | Blue Swirl | * License as published by the Free Software Foundation; either
|
9 | d7582078 | Blue Swirl | * version 2 of the License, or (at your option) any later version.
|
10 | d7582078 | Blue Swirl | *
|
11 | d7582078 | Blue Swirl | * This library is distributed in the hope that it will be useful,
|
12 | d7582078 | Blue Swirl | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | d7582078 | Blue Swirl | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | d7582078 | Blue Swirl | * Lesser General Public License for more details.
|
15 | d7582078 | Blue Swirl | *
|
16 | d7582078 | Blue Swirl | * You should have received a copy of the GNU Lesser General Public
|
17 | d7582078 | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | d7582078 | Blue Swirl | */
|
19 | d7582078 | Blue Swirl | |
20 | d7582078 | Blue Swirl | #include "cpu.h" |
21 | d7582078 | Blue Swirl | #include "host-utils.h" |
22 | d7582078 | Blue Swirl | #include "helper.h" |
23 | d7582078 | Blue Swirl | |
24 | d7582078 | Blue Swirl | //#define DEBUG_MULDIV
|
25 | d7582078 | Blue Swirl | |
26 | d7582078 | Blue Swirl | /* modulo 9 table */
|
27 | d7582078 | Blue Swirl | static const uint8_t rclb_table[32] = { |
28 | d7582078 | Blue Swirl | 0, 1, 2, 3, 4, 5, 6, 7, |
29 | d7582078 | Blue Swirl | 8, 0, 1, 2, 3, 4, 5, 6, |
30 | d7582078 | Blue Swirl | 7, 8, 0, 1, 2, 3, 4, 5, |
31 | d7582078 | Blue Swirl | 6, 7, 8, 0, 1, 2, 3, 4, |
32 | d7582078 | Blue Swirl | }; |
33 | d7582078 | Blue Swirl | |
34 | d7582078 | Blue Swirl | /* modulo 17 table */
|
35 | d7582078 | Blue Swirl | static const uint8_t rclw_table[32] = { |
36 | d7582078 | Blue Swirl | 0, 1, 2, 3, 4, 5, 6, 7, |
37 | d7582078 | Blue Swirl | 8, 9, 10, 11, 12, 13, 14, 15, |
38 | d7582078 | Blue Swirl | 16, 0, 1, 2, 3, 4, 5, 6, |
39 | d7582078 | Blue Swirl | 7, 8, 9, 10, 11, 12, 13, 14, |
40 | d7582078 | Blue Swirl | }; |
41 | d7582078 | Blue Swirl | |
42 | d7582078 | Blue Swirl | /* division, flags are undefined */
|
43 | d7582078 | Blue Swirl | |
44 | 7923057b | Blue Swirl | void helper_divb_AL(CPUX86State *env, target_ulong t0)
|
45 | d7582078 | Blue Swirl | { |
46 | d7582078 | Blue Swirl | unsigned int num, den, q, r; |
47 | d7582078 | Blue Swirl | |
48 | d7582078 | Blue Swirl | num = (EAX & 0xffff);
|
49 | d7582078 | Blue Swirl | den = (t0 & 0xff);
|
50 | d7582078 | Blue Swirl | if (den == 0) { |
51 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
52 | d7582078 | Blue Swirl | } |
53 | d7582078 | Blue Swirl | q = (num / den); |
54 | d7582078 | Blue Swirl | if (q > 0xff) { |
55 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
56 | d7582078 | Blue Swirl | } |
57 | d7582078 | Blue Swirl | q &= 0xff;
|
58 | d7582078 | Blue Swirl | r = (num % den) & 0xff;
|
59 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | (r << 8) | q; |
60 | d7582078 | Blue Swirl | } |
61 | d7582078 | Blue Swirl | |
62 | 7923057b | Blue Swirl | void helper_idivb_AL(CPUX86State *env, target_ulong t0)
|
63 | d7582078 | Blue Swirl | { |
64 | d7582078 | Blue Swirl | int num, den, q, r;
|
65 | d7582078 | Blue Swirl | |
66 | d7582078 | Blue Swirl | num = (int16_t)EAX; |
67 | d7582078 | Blue Swirl | den = (int8_t)t0; |
68 | d7582078 | Blue Swirl | if (den == 0) { |
69 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
70 | d7582078 | Blue Swirl | } |
71 | d7582078 | Blue Swirl | q = (num / den); |
72 | d7582078 | Blue Swirl | if (q != (int8_t)q) {
|
73 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
74 | d7582078 | Blue Swirl | } |
75 | d7582078 | Blue Swirl | q &= 0xff;
|
76 | d7582078 | Blue Swirl | r = (num % den) & 0xff;
|
77 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | (r << 8) | q; |
78 | d7582078 | Blue Swirl | } |
79 | d7582078 | Blue Swirl | |
80 | 7923057b | Blue Swirl | void helper_divw_AX(CPUX86State *env, target_ulong t0)
|
81 | d7582078 | Blue Swirl | { |
82 | d7582078 | Blue Swirl | unsigned int num, den, q, r; |
83 | d7582078 | Blue Swirl | |
84 | d7582078 | Blue Swirl | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
85 | d7582078 | Blue Swirl | den = (t0 & 0xffff);
|
86 | d7582078 | Blue Swirl | if (den == 0) { |
87 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
88 | d7582078 | Blue Swirl | } |
89 | d7582078 | Blue Swirl | q = (num / den); |
90 | d7582078 | Blue Swirl | if (q > 0xffff) { |
91 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
92 | d7582078 | Blue Swirl | } |
93 | d7582078 | Blue Swirl | q &= 0xffff;
|
94 | d7582078 | Blue Swirl | r = (num % den) & 0xffff;
|
95 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | q;
|
96 | d7582078 | Blue Swirl | EDX = (EDX & ~0xffff) | r;
|
97 | d7582078 | Blue Swirl | } |
98 | d7582078 | Blue Swirl | |
99 | 7923057b | Blue Swirl | void helper_idivw_AX(CPUX86State *env, target_ulong t0)
|
100 | d7582078 | Blue Swirl | { |
101 | d7582078 | Blue Swirl | int num, den, q, r;
|
102 | d7582078 | Blue Swirl | |
103 | d7582078 | Blue Swirl | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
104 | d7582078 | Blue Swirl | den = (int16_t)t0; |
105 | d7582078 | Blue Swirl | if (den == 0) { |
106 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
107 | d7582078 | Blue Swirl | } |
108 | d7582078 | Blue Swirl | q = (num / den); |
109 | d7582078 | Blue Swirl | if (q != (int16_t)q) {
|
110 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
111 | d7582078 | Blue Swirl | } |
112 | d7582078 | Blue Swirl | q &= 0xffff;
|
113 | d7582078 | Blue Swirl | r = (num % den) & 0xffff;
|
114 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | q;
|
115 | d7582078 | Blue Swirl | EDX = (EDX & ~0xffff) | r;
|
116 | d7582078 | Blue Swirl | } |
117 | d7582078 | Blue Swirl | |
118 | 7923057b | Blue Swirl | void helper_divl_EAX(CPUX86State *env, target_ulong t0)
|
119 | d7582078 | Blue Swirl | { |
120 | d7582078 | Blue Swirl | unsigned int den, r; |
121 | d7582078 | Blue Swirl | uint64_t num, q; |
122 | d7582078 | Blue Swirl | |
123 | d7582078 | Blue Swirl | num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
|
124 | d7582078 | Blue Swirl | den = t0; |
125 | d7582078 | Blue Swirl | if (den == 0) { |
126 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
127 | d7582078 | Blue Swirl | } |
128 | d7582078 | Blue Swirl | q = (num / den); |
129 | d7582078 | Blue Swirl | r = (num % den); |
130 | d7582078 | Blue Swirl | if (q > 0xffffffff) { |
131 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
132 | d7582078 | Blue Swirl | } |
133 | d7582078 | Blue Swirl | EAX = (uint32_t)q; |
134 | d7582078 | Blue Swirl | EDX = (uint32_t)r; |
135 | d7582078 | Blue Swirl | } |
136 | d7582078 | Blue Swirl | |
137 | 7923057b | Blue Swirl | void helper_idivl_EAX(CPUX86State *env, target_ulong t0)
|
138 | d7582078 | Blue Swirl | { |
139 | d7582078 | Blue Swirl | int den, r;
|
140 | d7582078 | Blue Swirl | int64_t num, q; |
141 | d7582078 | Blue Swirl | |
142 | d7582078 | Blue Swirl | num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
|
143 | d7582078 | Blue Swirl | den = t0; |
144 | d7582078 | Blue Swirl | if (den == 0) { |
145 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
146 | d7582078 | Blue Swirl | } |
147 | d7582078 | Blue Swirl | q = (num / den); |
148 | d7582078 | Blue Swirl | r = (num % den); |
149 | d7582078 | Blue Swirl | if (q != (int32_t)q) {
|
150 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
151 | d7582078 | Blue Swirl | } |
152 | d7582078 | Blue Swirl | EAX = (uint32_t)q; |
153 | d7582078 | Blue Swirl | EDX = (uint32_t)r; |
154 | d7582078 | Blue Swirl | } |
155 | d7582078 | Blue Swirl | |
156 | d7582078 | Blue Swirl | /* bcd */
|
157 | d7582078 | Blue Swirl | |
158 | d7582078 | Blue Swirl | /* XXX: exception */
|
159 | 7923057b | Blue Swirl | void helper_aam(CPUX86State *env, int base) |
160 | d7582078 | Blue Swirl | { |
161 | d7582078 | Blue Swirl | int al, ah;
|
162 | d7582078 | Blue Swirl | |
163 | d7582078 | Blue Swirl | al = EAX & 0xff;
|
164 | d7582078 | Blue Swirl | ah = al / base; |
165 | d7582078 | Blue Swirl | al = al % base; |
166 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | al | (ah << 8); |
167 | d7582078 | Blue Swirl | CC_DST = al; |
168 | d7582078 | Blue Swirl | } |
169 | d7582078 | Blue Swirl | |
170 | 7923057b | Blue Swirl | void helper_aad(CPUX86State *env, int base) |
171 | d7582078 | Blue Swirl | { |
172 | d7582078 | Blue Swirl | int al, ah;
|
173 | d7582078 | Blue Swirl | |
174 | d7582078 | Blue Swirl | al = EAX & 0xff;
|
175 | d7582078 | Blue Swirl | ah = (EAX >> 8) & 0xff; |
176 | d7582078 | Blue Swirl | al = ((ah * base) + al) & 0xff;
|
177 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | al;
|
178 | d7582078 | Blue Swirl | CC_DST = al; |
179 | d7582078 | Blue Swirl | } |
180 | d7582078 | Blue Swirl | |
181 | 7923057b | Blue Swirl | void helper_aaa(CPUX86State *env)
|
182 | d7582078 | Blue Swirl | { |
183 | d7582078 | Blue Swirl | int icarry;
|
184 | d7582078 | Blue Swirl | int al, ah, af;
|
185 | d7582078 | Blue Swirl | int eflags;
|
186 | d7582078 | Blue Swirl | |
187 | f0967a1a | Blue Swirl | eflags = cpu_cc_compute_all(env, CC_OP); |
188 | d7582078 | Blue Swirl | af = eflags & CC_A; |
189 | d7582078 | Blue Swirl | al = EAX & 0xff;
|
190 | d7582078 | Blue Swirl | ah = (EAX >> 8) & 0xff; |
191 | d7582078 | Blue Swirl | |
192 | d7582078 | Blue Swirl | icarry = (al > 0xf9);
|
193 | d7582078 | Blue Swirl | if (((al & 0x0f) > 9) || af) { |
194 | d7582078 | Blue Swirl | al = (al + 6) & 0x0f; |
195 | d7582078 | Blue Swirl | ah = (ah + 1 + icarry) & 0xff; |
196 | d7582078 | Blue Swirl | eflags |= CC_C | CC_A; |
197 | d7582078 | Blue Swirl | } else {
|
198 | d7582078 | Blue Swirl | eflags &= ~(CC_C | CC_A); |
199 | d7582078 | Blue Swirl | al &= 0x0f;
|
200 | d7582078 | Blue Swirl | } |
201 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | al | (ah << 8); |
202 | d7582078 | Blue Swirl | CC_SRC = eflags; |
203 | d7582078 | Blue Swirl | } |
204 | d7582078 | Blue Swirl | |
205 | 7923057b | Blue Swirl | void helper_aas(CPUX86State *env)
|
206 | d7582078 | Blue Swirl | { |
207 | d7582078 | Blue Swirl | int icarry;
|
208 | d7582078 | Blue Swirl | int al, ah, af;
|
209 | d7582078 | Blue Swirl | int eflags;
|
210 | d7582078 | Blue Swirl | |
211 | f0967a1a | Blue Swirl | eflags = cpu_cc_compute_all(env, CC_OP); |
212 | d7582078 | Blue Swirl | af = eflags & CC_A; |
213 | d7582078 | Blue Swirl | al = EAX & 0xff;
|
214 | d7582078 | Blue Swirl | ah = (EAX >> 8) & 0xff; |
215 | d7582078 | Blue Swirl | |
216 | d7582078 | Blue Swirl | icarry = (al < 6);
|
217 | d7582078 | Blue Swirl | if (((al & 0x0f) > 9) || af) { |
218 | d7582078 | Blue Swirl | al = (al - 6) & 0x0f; |
219 | d7582078 | Blue Swirl | ah = (ah - 1 - icarry) & 0xff; |
220 | d7582078 | Blue Swirl | eflags |= CC_C | CC_A; |
221 | d7582078 | Blue Swirl | } else {
|
222 | d7582078 | Blue Swirl | eflags &= ~(CC_C | CC_A); |
223 | d7582078 | Blue Swirl | al &= 0x0f;
|
224 | d7582078 | Blue Swirl | } |
225 | d7582078 | Blue Swirl | EAX = (EAX & ~0xffff) | al | (ah << 8); |
226 | d7582078 | Blue Swirl | CC_SRC = eflags; |
227 | d7582078 | Blue Swirl | } |
228 | d7582078 | Blue Swirl | |
229 | 7923057b | Blue Swirl | void helper_daa(CPUX86State *env)
|
230 | d7582078 | Blue Swirl | { |
231 | d7582078 | Blue Swirl | int old_al, al, af, cf;
|
232 | d7582078 | Blue Swirl | int eflags;
|
233 | d7582078 | Blue Swirl | |
234 | f0967a1a | Blue Swirl | eflags = cpu_cc_compute_all(env, CC_OP); |
235 | d7582078 | Blue Swirl | cf = eflags & CC_C; |
236 | d7582078 | Blue Swirl | af = eflags & CC_A; |
237 | d7582078 | Blue Swirl | old_al = al = EAX & 0xff;
|
238 | d7582078 | Blue Swirl | |
239 | d7582078 | Blue Swirl | eflags = 0;
|
240 | d7582078 | Blue Swirl | if (((al & 0x0f) > 9) || af) { |
241 | d7582078 | Blue Swirl | al = (al + 6) & 0xff; |
242 | d7582078 | Blue Swirl | eflags |= CC_A; |
243 | d7582078 | Blue Swirl | } |
244 | d7582078 | Blue Swirl | if ((old_al > 0x99) || cf) { |
245 | d7582078 | Blue Swirl | al = (al + 0x60) & 0xff; |
246 | d7582078 | Blue Swirl | eflags |= CC_C; |
247 | d7582078 | Blue Swirl | } |
248 | d7582078 | Blue Swirl | EAX = (EAX & ~0xff) | al;
|
249 | d7582078 | Blue Swirl | /* well, speed is not an issue here, so we compute the flags by hand */
|
250 | d7582078 | Blue Swirl | eflags |= (al == 0) << 6; /* zf */ |
251 | d7582078 | Blue Swirl | eflags |= parity_table[al]; /* pf */
|
252 | d7582078 | Blue Swirl | eflags |= (al & 0x80); /* sf */ |
253 | d7582078 | Blue Swirl | CC_SRC = eflags; |
254 | d7582078 | Blue Swirl | } |
255 | d7582078 | Blue Swirl | |
256 | 7923057b | Blue Swirl | void helper_das(CPUX86State *env)
|
257 | d7582078 | Blue Swirl | { |
258 | d7582078 | Blue Swirl | int al, al1, af, cf;
|
259 | d7582078 | Blue Swirl | int eflags;
|
260 | d7582078 | Blue Swirl | |
261 | f0967a1a | Blue Swirl | eflags = cpu_cc_compute_all(env, CC_OP); |
262 | d7582078 | Blue Swirl | cf = eflags & CC_C; |
263 | d7582078 | Blue Swirl | af = eflags & CC_A; |
264 | d7582078 | Blue Swirl | al = EAX & 0xff;
|
265 | d7582078 | Blue Swirl | |
266 | d7582078 | Blue Swirl | eflags = 0;
|
267 | d7582078 | Blue Swirl | al1 = al; |
268 | d7582078 | Blue Swirl | if (((al & 0x0f) > 9) || af) { |
269 | d7582078 | Blue Swirl | eflags |= CC_A; |
270 | d7582078 | Blue Swirl | if (al < 6 || cf) { |
271 | d7582078 | Blue Swirl | eflags |= CC_C; |
272 | d7582078 | Blue Swirl | } |
273 | d7582078 | Blue Swirl | al = (al - 6) & 0xff; |
274 | d7582078 | Blue Swirl | } |
275 | d7582078 | Blue Swirl | if ((al1 > 0x99) || cf) { |
276 | d7582078 | Blue Swirl | al = (al - 0x60) & 0xff; |
277 | d7582078 | Blue Swirl | eflags |= CC_C; |
278 | d7582078 | Blue Swirl | } |
279 | d7582078 | Blue Swirl | EAX = (EAX & ~0xff) | al;
|
280 | d7582078 | Blue Swirl | /* well, speed is not an issue here, so we compute the flags by hand */
|
281 | d7582078 | Blue Swirl | eflags |= (al == 0) << 6; /* zf */ |
282 | d7582078 | Blue Swirl | eflags |= parity_table[al]; /* pf */
|
283 | d7582078 | Blue Swirl | eflags |= (al & 0x80); /* sf */ |
284 | d7582078 | Blue Swirl | CC_SRC = eflags; |
285 | d7582078 | Blue Swirl | } |
286 | d7582078 | Blue Swirl | |
287 | d7582078 | Blue Swirl | #ifdef TARGET_X86_64
|
288 | d7582078 | Blue Swirl | static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) |
289 | d7582078 | Blue Swirl | { |
290 | d7582078 | Blue Swirl | *plow += a; |
291 | d7582078 | Blue Swirl | /* carry test */
|
292 | d7582078 | Blue Swirl | if (*plow < a) {
|
293 | d7582078 | Blue Swirl | (*phigh)++; |
294 | d7582078 | Blue Swirl | } |
295 | d7582078 | Blue Swirl | *phigh += b; |
296 | d7582078 | Blue Swirl | } |
297 | d7582078 | Blue Swirl | |
298 | d7582078 | Blue Swirl | static void neg128(uint64_t *plow, uint64_t *phigh) |
299 | d7582078 | Blue Swirl | { |
300 | d7582078 | Blue Swirl | *plow = ~*plow; |
301 | d7582078 | Blue Swirl | *phigh = ~*phigh; |
302 | d7582078 | Blue Swirl | add128(plow, phigh, 1, 0); |
303 | d7582078 | Blue Swirl | } |
304 | d7582078 | Blue Swirl | |
305 | d7582078 | Blue Swirl | /* return TRUE if overflow */
|
306 | d7582078 | Blue Swirl | static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b) |
307 | d7582078 | Blue Swirl | { |
308 | d7582078 | Blue Swirl | uint64_t q, r, a1, a0; |
309 | d7582078 | Blue Swirl | int i, qb, ab;
|
310 | d7582078 | Blue Swirl | |
311 | d7582078 | Blue Swirl | a0 = *plow; |
312 | d7582078 | Blue Swirl | a1 = *phigh; |
313 | d7582078 | Blue Swirl | if (a1 == 0) { |
314 | d7582078 | Blue Swirl | q = a0 / b; |
315 | d7582078 | Blue Swirl | r = a0 % b; |
316 | d7582078 | Blue Swirl | *plow = q; |
317 | d7582078 | Blue Swirl | *phigh = r; |
318 | d7582078 | Blue Swirl | } else {
|
319 | d7582078 | Blue Swirl | if (a1 >= b) {
|
320 | d7582078 | Blue Swirl | return 1; |
321 | d7582078 | Blue Swirl | } |
322 | d7582078 | Blue Swirl | /* XXX: use a better algorithm */
|
323 | d7582078 | Blue Swirl | for (i = 0; i < 64; i++) { |
324 | d7582078 | Blue Swirl | ab = a1 >> 63;
|
325 | d7582078 | Blue Swirl | a1 = (a1 << 1) | (a0 >> 63); |
326 | d7582078 | Blue Swirl | if (ab || a1 >= b) {
|
327 | d7582078 | Blue Swirl | a1 -= b; |
328 | d7582078 | Blue Swirl | qb = 1;
|
329 | d7582078 | Blue Swirl | } else {
|
330 | d7582078 | Blue Swirl | qb = 0;
|
331 | d7582078 | Blue Swirl | } |
332 | d7582078 | Blue Swirl | a0 = (a0 << 1) | qb;
|
333 | d7582078 | Blue Swirl | } |
334 | d7582078 | Blue Swirl | #if defined(DEBUG_MULDIV)
|
335 | d7582078 | Blue Swirl | printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 |
336 | d7582078 | Blue Swirl | ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n", |
337 | d7582078 | Blue Swirl | *phigh, *plow, b, a0, a1); |
338 | d7582078 | Blue Swirl | #endif
|
339 | d7582078 | Blue Swirl | *plow = a0; |
340 | d7582078 | Blue Swirl | *phigh = a1; |
341 | d7582078 | Blue Swirl | } |
342 | d7582078 | Blue Swirl | return 0; |
343 | d7582078 | Blue Swirl | } |
344 | d7582078 | Blue Swirl | |
345 | d7582078 | Blue Swirl | /* return TRUE if overflow */
|
346 | d7582078 | Blue Swirl | static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) |
347 | d7582078 | Blue Swirl | { |
348 | d7582078 | Blue Swirl | int sa, sb;
|
349 | d7582078 | Blue Swirl | |
350 | d7582078 | Blue Swirl | sa = ((int64_t)*phigh < 0);
|
351 | d7582078 | Blue Swirl | if (sa) {
|
352 | d7582078 | Blue Swirl | neg128(plow, phigh); |
353 | d7582078 | Blue Swirl | } |
354 | d7582078 | Blue Swirl | sb = (b < 0);
|
355 | d7582078 | Blue Swirl | if (sb) {
|
356 | d7582078 | Blue Swirl | b = -b; |
357 | d7582078 | Blue Swirl | } |
358 | d7582078 | Blue Swirl | if (div64(plow, phigh, b) != 0) { |
359 | d7582078 | Blue Swirl | return 1; |
360 | d7582078 | Blue Swirl | } |
361 | d7582078 | Blue Swirl | if (sa ^ sb) {
|
362 | d7582078 | Blue Swirl | if (*plow > (1ULL << 63)) { |
363 | d7582078 | Blue Swirl | return 1; |
364 | d7582078 | Blue Swirl | } |
365 | d7582078 | Blue Swirl | *plow = -*plow; |
366 | d7582078 | Blue Swirl | } else {
|
367 | d7582078 | Blue Swirl | if (*plow >= (1ULL << 63)) { |
368 | d7582078 | Blue Swirl | return 1; |
369 | d7582078 | Blue Swirl | } |
370 | d7582078 | Blue Swirl | } |
371 | d7582078 | Blue Swirl | if (sa) {
|
372 | d7582078 | Blue Swirl | *phigh = -*phigh; |
373 | d7582078 | Blue Swirl | } |
374 | d7582078 | Blue Swirl | return 0; |
375 | d7582078 | Blue Swirl | } |
376 | d7582078 | Blue Swirl | |
377 | 7923057b | Blue Swirl | void helper_mulq_EAX_T0(CPUX86State *env, target_ulong t0)
|
378 | d7582078 | Blue Swirl | { |
379 | d7582078 | Blue Swirl | uint64_t r0, r1; |
380 | d7582078 | Blue Swirl | |
381 | d7582078 | Blue Swirl | mulu64(&r0, &r1, EAX, t0); |
382 | d7582078 | Blue Swirl | EAX = r0; |
383 | d7582078 | Blue Swirl | EDX = r1; |
384 | d7582078 | Blue Swirl | CC_DST = r0; |
385 | d7582078 | Blue Swirl | CC_SRC = r1; |
386 | d7582078 | Blue Swirl | } |
387 | d7582078 | Blue Swirl | |
388 | 7923057b | Blue Swirl | void helper_imulq_EAX_T0(CPUX86State *env, target_ulong t0)
|
389 | d7582078 | Blue Swirl | { |
390 | d7582078 | Blue Swirl | uint64_t r0, r1; |
391 | d7582078 | Blue Swirl | |
392 | d7582078 | Blue Swirl | muls64(&r0, &r1, EAX, t0); |
393 | d7582078 | Blue Swirl | EAX = r0; |
394 | d7582078 | Blue Swirl | EDX = r1; |
395 | d7582078 | Blue Swirl | CC_DST = r0; |
396 | d7582078 | Blue Swirl | CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
|
397 | d7582078 | Blue Swirl | } |
398 | d7582078 | Blue Swirl | |
399 | 7923057b | Blue Swirl | target_ulong helper_imulq_T0_T1(CPUX86State *env, target_ulong t0, |
400 | 7923057b | Blue Swirl | target_ulong t1) |
401 | d7582078 | Blue Swirl | { |
402 | d7582078 | Blue Swirl | uint64_t r0, r1; |
403 | d7582078 | Blue Swirl | |
404 | d7582078 | Blue Swirl | muls64(&r0, &r1, t0, t1); |
405 | d7582078 | Blue Swirl | CC_DST = r0; |
406 | d7582078 | Blue Swirl | CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
|
407 | d7582078 | Blue Swirl | return r0;
|
408 | d7582078 | Blue Swirl | } |
409 | d7582078 | Blue Swirl | |
410 | 7923057b | Blue Swirl | void helper_divq_EAX(CPUX86State *env, target_ulong t0)
|
411 | d7582078 | Blue Swirl | { |
412 | d7582078 | Blue Swirl | uint64_t r0, r1; |
413 | d7582078 | Blue Swirl | |
414 | d7582078 | Blue Swirl | if (t0 == 0) { |
415 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
416 | d7582078 | Blue Swirl | } |
417 | d7582078 | Blue Swirl | r0 = EAX; |
418 | d7582078 | Blue Swirl | r1 = EDX; |
419 | d7582078 | Blue Swirl | if (div64(&r0, &r1, t0)) {
|
420 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
421 | d7582078 | Blue Swirl | } |
422 | d7582078 | Blue Swirl | EAX = r0; |
423 | d7582078 | Blue Swirl | EDX = r1; |
424 | d7582078 | Blue Swirl | } |
425 | d7582078 | Blue Swirl | |
426 | 7923057b | Blue Swirl | void helper_idivq_EAX(CPUX86State *env, target_ulong t0)
|
427 | d7582078 | Blue Swirl | { |
428 | d7582078 | Blue Swirl | uint64_t r0, r1; |
429 | d7582078 | Blue Swirl | |
430 | d7582078 | Blue Swirl | if (t0 == 0) { |
431 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
432 | d7582078 | Blue Swirl | } |
433 | d7582078 | Blue Swirl | r0 = EAX; |
434 | d7582078 | Blue Swirl | r1 = EDX; |
435 | d7582078 | Blue Swirl | if (idiv64(&r0, &r1, t0)) {
|
436 | d7582078 | Blue Swirl | raise_exception(env, EXCP00_DIVZ); |
437 | d7582078 | Blue Swirl | } |
438 | d7582078 | Blue Swirl | EAX = r0; |
439 | d7582078 | Blue Swirl | EDX = r1; |
440 | d7582078 | Blue Swirl | } |
441 | d7582078 | Blue Swirl | #endif
|
442 | d7582078 | Blue Swirl | |
443 | d7582078 | Blue Swirl | /* bit operations */
|
444 | d7582078 | Blue Swirl | target_ulong helper_bsf(target_ulong t0) |
445 | d7582078 | Blue Swirl | { |
446 | d7582078 | Blue Swirl | int count;
|
447 | d7582078 | Blue Swirl | target_ulong res; |
448 | d7582078 | Blue Swirl | |
449 | d7582078 | Blue Swirl | res = t0; |
450 | d7582078 | Blue Swirl | count = 0;
|
451 | d7582078 | Blue Swirl | while ((res & 1) == 0) { |
452 | d7582078 | Blue Swirl | count++; |
453 | d7582078 | Blue Swirl | res >>= 1;
|
454 | d7582078 | Blue Swirl | } |
455 | d7582078 | Blue Swirl | return count;
|
456 | d7582078 | Blue Swirl | } |
457 | d7582078 | Blue Swirl | |
458 | d7582078 | Blue Swirl | target_ulong helper_lzcnt(target_ulong t0, int wordsize)
|
459 | d7582078 | Blue Swirl | { |
460 | d7582078 | Blue Swirl | int count;
|
461 | d7582078 | Blue Swirl | target_ulong res, mask; |
462 | d7582078 | Blue Swirl | |
463 | d7582078 | Blue Swirl | if (wordsize > 0 && t0 == 0) { |
464 | d7582078 | Blue Swirl | return wordsize;
|
465 | d7582078 | Blue Swirl | } |
466 | d7582078 | Blue Swirl | res = t0; |
467 | d7582078 | Blue Swirl | count = TARGET_LONG_BITS - 1;
|
468 | d7582078 | Blue Swirl | mask = (target_ulong)1 << (TARGET_LONG_BITS - 1); |
469 | d7582078 | Blue Swirl | while ((res & mask) == 0) { |
470 | d7582078 | Blue Swirl | count--; |
471 | d7582078 | Blue Swirl | res <<= 1;
|
472 | d7582078 | Blue Swirl | } |
473 | d7582078 | Blue Swirl | if (wordsize > 0) { |
474 | d7582078 | Blue Swirl | return wordsize - 1 - count; |
475 | d7582078 | Blue Swirl | } |
476 | d7582078 | Blue Swirl | return count;
|
477 | d7582078 | Blue Swirl | } |
478 | d7582078 | Blue Swirl | |
479 | d7582078 | Blue Swirl | target_ulong helper_bsr(target_ulong t0) |
480 | d7582078 | Blue Swirl | { |
481 | d7582078 | Blue Swirl | return helper_lzcnt(t0, 0); |
482 | d7582078 | Blue Swirl | } |
483 | d7582078 | Blue Swirl | |
484 | d7582078 | Blue Swirl | #define SHIFT 0 |
485 | d7582078 | Blue Swirl | #include "shift_helper_template.h" |
486 | d7582078 | Blue Swirl | #undef SHIFT
|
487 | d7582078 | Blue Swirl | |
488 | d7582078 | Blue Swirl | #define SHIFT 1 |
489 | d7582078 | Blue Swirl | #include "shift_helper_template.h" |
490 | d7582078 | Blue Swirl | #undef SHIFT
|
491 | d7582078 | Blue Swirl | |
492 | d7582078 | Blue Swirl | #define SHIFT 2 |
493 | d7582078 | Blue Swirl | #include "shift_helper_template.h" |
494 | d7582078 | Blue Swirl | #undef SHIFT
|
495 | d7582078 | Blue Swirl | |
496 | d7582078 | Blue Swirl | #ifdef TARGET_X86_64
|
497 | d7582078 | Blue Swirl | #define SHIFT 3 |
498 | d7582078 | Blue Swirl | #include "shift_helper_template.h" |
499 | d7582078 | Blue Swirl | #undef SHIFT
|
500 | d7582078 | Blue Swirl | #endif |