VirtualBox

source: vbox/trunk/src/recompiler/target-i386/helper_template.h@ 54266

Last change on this file since 54266 was 36175, checked in by vboxsync, 14 years ago

rem: Synced up to v0.11.1 (35bfc7324e2e6946c4113ada5db30553a1a7c40b) from git://git.savannah.nongnu.org/qemu.git.

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1/*
2 * i386 helpers
3 *
4 * Copyright (c) 2008 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
22 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
23 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
24 * a choice of LGPL license versions is made available with the language indicating
25 * that LGPLv2 or any later version may be used, or where a choice of which version
26 * of the LGPL is applied is otherwise unspecified.
27 */
28
29#define DATA_BITS (1 << (3 + SHIFT))
30#define SHIFT_MASK (DATA_BITS - 1)
31#define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1))
32#if DATA_BITS <= 32
33#define SHIFT1_MASK 0x1f
34#else
35#define SHIFT1_MASK 0x3f
36#endif
37
38#if DATA_BITS == 8
39#define SUFFIX b
40#define DATA_TYPE uint8_t
41#define DATA_STYPE int8_t
42#define DATA_MASK 0xff
43#elif DATA_BITS == 16
44#define SUFFIX w
45#define DATA_TYPE uint16_t
46#define DATA_STYPE int16_t
47#define DATA_MASK 0xffff
48#elif DATA_BITS == 32
49#define SUFFIX l
50#define DATA_TYPE uint32_t
51#define DATA_STYPE int32_t
52#define DATA_MASK 0xffffffff
53#elif DATA_BITS == 64
54#define SUFFIX q
55#define DATA_TYPE uint64_t
56#define DATA_STYPE int64_t
57#define DATA_MASK 0xffffffffffffffffULL
58#else
59#error unhandled operand size
60#endif
61
62/* dynamic flags computation */
63
64static int glue(compute_all_add, SUFFIX)(void)
65{
66 int cf, pf, af, zf, sf, of;
67 target_long src1, src2;
68 src1 = CC_SRC;
69 src2 = CC_DST - CC_SRC;
70 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
71 pf = parity_table[(uint8_t)CC_DST];
72 af = (CC_DST ^ src1 ^ src2) & 0x10;
73 zf = ((DATA_TYPE)CC_DST == 0) << 6;
74 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
75 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
76 return cf | pf | af | zf | sf | of;
77}
78
79static int glue(compute_c_add, SUFFIX)(void)
80{
81 int cf;
82 target_long src1;
83 src1 = CC_SRC;
84 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
85 return cf;
86}
87
88static int glue(compute_all_adc, SUFFIX)(void)
89{
90 int cf, pf, af, zf, sf, of;
91 target_long src1, src2;
92 src1 = CC_SRC;
93 src2 = CC_DST - CC_SRC - 1;
94 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
95 pf = parity_table[(uint8_t)CC_DST];
96 af = (CC_DST ^ src1 ^ src2) & 0x10;
97 zf = ((DATA_TYPE)CC_DST == 0) << 6;
98 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
99 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
100 return cf | pf | af | zf | sf | of;
101}
102
103static int glue(compute_c_adc, SUFFIX)(void)
104{
105 int cf;
106 target_long src1;
107 src1 = CC_SRC;
108 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
109 return cf;
110}
111
112static int glue(compute_all_sub, SUFFIX)(void)
113{
114 int cf, pf, af, zf, sf, of;
115 target_long src1, src2;
116 src1 = CC_DST + CC_SRC;
117 src2 = CC_SRC;
118 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
119 pf = parity_table[(uint8_t)CC_DST];
120 af = (CC_DST ^ src1 ^ src2) & 0x10;
121 zf = ((DATA_TYPE)CC_DST == 0) << 6;
122 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
123 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
124 return cf | pf | af | zf | sf | of;
125}
126
127static int glue(compute_c_sub, SUFFIX)(void)
128{
129 int cf;
130 target_long src1, src2;
131 src1 = CC_DST + CC_SRC;
132 src2 = CC_SRC;
133 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
134 return cf;
135}
136
137static int glue(compute_all_sbb, SUFFIX)(void)
138{
139 int cf, pf, af, zf, sf, of;
140 target_long src1, src2;
141 src1 = CC_DST + CC_SRC + 1;
142 src2 = CC_SRC;
143 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
144 pf = parity_table[(uint8_t)CC_DST];
145 af = (CC_DST ^ src1 ^ src2) & 0x10;
146 zf = ((DATA_TYPE)CC_DST == 0) << 6;
147 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
148 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
149 return cf | pf | af | zf | sf | of;
150}
151
152static int glue(compute_c_sbb, SUFFIX)(void)
153{
154 int cf;
155 target_long src1, src2;
156 src1 = CC_DST + CC_SRC + 1;
157 src2 = CC_SRC;
158 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
159 return cf;
160}
161
162static int glue(compute_all_logic, SUFFIX)(void)
163{
164 int cf, pf, af, zf, sf, of;
165 cf = 0;
166 pf = parity_table[(uint8_t)CC_DST];
167 af = 0;
168 zf = ((DATA_TYPE)CC_DST == 0) << 6;
169 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
170 of = 0;
171 return cf | pf | af | zf | sf | of;
172}
173
174static int glue(compute_c_logic, SUFFIX)(void)
175{
176 return 0;
177}
178
179static int glue(compute_all_inc, SUFFIX)(void)
180{
181 int cf, pf, af, zf, sf, of;
182 target_long src1, src2;
183 src1 = CC_DST - 1;
184 src2 = 1;
185 cf = CC_SRC;
186 pf = parity_table[(uint8_t)CC_DST];
187 af = (CC_DST ^ src1 ^ src2) & 0x10;
188 zf = ((DATA_TYPE)CC_DST == 0) << 6;
189 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
190 of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
191 return cf | pf | af | zf | sf | of;
192}
193
194#if DATA_BITS == 32
195static int glue(compute_c_inc, SUFFIX)(void)
196{
197 return CC_SRC;
198}
199#endif
200
201static int glue(compute_all_dec, SUFFIX)(void)
202{
203 int cf, pf, af, zf, sf, of;
204 target_long src1, src2;
205 src1 = CC_DST + 1;
206 src2 = 1;
207 cf = CC_SRC;
208 pf = parity_table[(uint8_t)CC_DST];
209 af = (CC_DST ^ src1 ^ src2) & 0x10;
210 zf = ((DATA_TYPE)CC_DST == 0) << 6;
211 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
212 of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11;
213 return cf | pf | af | zf | sf | of;
214}
215
216static int glue(compute_all_shl, SUFFIX)(void)
217{
218 int cf, pf, af, zf, sf, of;
219 cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
220 pf = parity_table[(uint8_t)CC_DST];
221 af = 0; /* undefined */
222 zf = ((DATA_TYPE)CC_DST == 0) << 6;
223 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
224 /* of is defined if shift count == 1 */
225 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
226 return cf | pf | af | zf | sf | of;
227}
228
229static int glue(compute_c_shl, SUFFIX)(void)
230{
231 return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
232}
233
234#if DATA_BITS == 32
235static int glue(compute_c_sar, SUFFIX)(void)
236{
237 return CC_SRC & 1;
238}
239#endif
240
241static int glue(compute_all_sar, SUFFIX)(void)
242{
243 int cf, pf, af, zf, sf, of;
244 cf = CC_SRC & 1;
245 pf = parity_table[(uint8_t)CC_DST];
246 af = 0; /* undefined */
247 zf = ((DATA_TYPE)CC_DST == 0) << 6;
248 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
249 /* of is defined if shift count == 1 */
250 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
251 return cf | pf | af | zf | sf | of;
252}
253
254#if DATA_BITS == 32
255static int glue(compute_c_mul, SUFFIX)(void)
256{
257 int cf;
258 cf = (CC_SRC != 0);
259 return cf;
260}
261#endif
262
263/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
264 CF are modified and it is slower to do that. */
265static int glue(compute_all_mul, SUFFIX)(void)
266{
267 int cf, pf, af, zf, sf, of;
268 cf = (CC_SRC != 0);
269 pf = parity_table[(uint8_t)CC_DST];
270 af = 0; /* undefined */
271 zf = ((DATA_TYPE)CC_DST == 0) << 6;
272 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
273 of = cf << 11;
274 return cf | pf | af | zf | sf | of;
275}
276
277/* shifts */
278
279target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1)
280{
281 int count, eflags;
282 target_ulong src;
283 target_long res;
284
285 count = t1 & SHIFT1_MASK;
286#if DATA_BITS == 16
287 count = rclw_table[count];
288#elif DATA_BITS == 8
289 count = rclb_table[count];
290#endif
291 if (count) {
292 eflags = helper_cc_compute_all(CC_OP);
293 t0 &= DATA_MASK;
294 src = t0;
295 res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1));
296 if (count > 1)
297 res |= t0 >> (DATA_BITS + 1 - count);
298 t0 = res;
299 env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
300 (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
301 ((src >> (DATA_BITS - count)) & CC_C);
302 } else {
303 env->cc_tmp = -1;
304 }
305 return t0;
306}
307
308target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1)
309{
310 int count, eflags;
311 target_ulong src;
312 target_long res;
313
314 count = t1 & SHIFT1_MASK;
315#if DATA_BITS == 16
316 count = rclw_table[count];
317#elif DATA_BITS == 8
318 count = rclb_table[count];
319#endif
320 if (count) {
321 eflags = helper_cc_compute_all(CC_OP);
322 t0 &= DATA_MASK;
323 src = t0;
324 res = (t0 >> count) | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count));
325 if (count > 1)
326 res |= t0 << (DATA_BITS + 1 - count);
327 t0 = res;
328 env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
329 (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
330 ((src >> (count - 1)) & CC_C);
331 } else {
332 env->cc_tmp = -1;
333 }
334 return t0;
335}
336
337#undef DATA_BITS
338#undef SHIFT_MASK
339#undef SHIFT1_MASK
340#undef SIGN_MASK
341#undef DATA_TYPE
342#undef DATA_STYPE
343#undef DATA_MASK
344#undef SUFFIX
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette