gcc 3.2.2 bug workaround (RedHat 9 fix)
[qemu] / ops_template_mem.h
1 /*
2  *  i386 micro operations (included several times to generate
3  *  different operand sizes)
4  * 
5  *  Copyright (c) 2003 Fabrice Bellard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #ifdef MEM_WRITE
22
23 #if DATA_BITS == 8
24 #define MEM_SUFFIX b_mem
25 #elif DATA_BITS == 16
26 #define MEM_SUFFIX w_mem
27 #elif DATA_BITS == 32
28 #define MEM_SUFFIX l_mem
29 #endif
30
31 #else
32
33 #define MEM_SUFFIX SUFFIX
34
35 #endif
36
37 void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void)
38 {
39     int count, src;
40     count = T1 & SHIFT_MASK;
41     if (count) {
42         src = T0;
43         T0 &= DATA_MASK;
44         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
45 #ifdef MEM_WRITE
46         glue(st, SUFFIX)((uint8_t *)A0, T0);
47 #else
48         /* gcc 3.2 workaround. This is really a bug in gcc. */
49         asm volatile("" : : "r" (T0));
50 #endif
51         CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | 
52             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
53             (T0 & CC_C);
54         CC_OP = CC_OP_EFLAGS;
55     }
56     FORCE_RET();
57 }
58
59 void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void)
60 {
61     int count, src;
62     count = T1 & SHIFT_MASK;
63     if (count) {
64         src = T0;
65         T0 &= DATA_MASK;
66         T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
67 #ifdef MEM_WRITE
68         glue(st, SUFFIX)((uint8_t *)A0, T0);
69 #else
70         /* gcc 3.2 workaround. This is really a bug in gcc. */
71         asm volatile("" : : "r" (T0));
72 #endif
73         CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
74             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
75             ((T0 >> (DATA_BITS - 1)) & CC_C);
76         CC_OP = CC_OP_EFLAGS;
77     }
78     FORCE_RET();
79 }
80
81 void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void)
82 {
83     int count;
84     count = T1 & SHIFT_MASK;
85     if (count) {
86         T0 &= DATA_MASK;
87         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
88 #ifdef MEM_WRITE
89         glue(st, SUFFIX)((uint8_t *)A0, T0);
90 #endif
91     }
92     FORCE_RET();
93 }
94
95 void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void)
96 {
97     int count;
98     count = T1 & SHIFT_MASK;
99     if (count) {
100         T0 &= DATA_MASK;
101         T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
102 #ifdef MEM_WRITE
103         glue(st, SUFFIX)((uint8_t *)A0, T0);
104 #endif
105     }
106     FORCE_RET();
107 }
108
109 void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void)
110 {
111     int count, res, eflags;
112     unsigned int src;
113
114     count = T1 & 0x1f;
115 #if DATA_BITS == 16
116     count = rclw_table[count];
117 #elif DATA_BITS == 8
118     count = rclb_table[count];
119 #endif
120     if (count) {
121         eflags = cc_table[CC_OP].compute_all();
122         T0 &= DATA_MASK;
123         src = T0;
124         res = (T0 << count) | ((eflags & CC_C) << (count - 1));
125         if (count > 1)
126             res |= T0 >> (DATA_BITS + 1 - count);
127         T0 = res;
128 #ifdef MEM_WRITE
129         glue(st, SUFFIX)((uint8_t *)A0, T0);
130 #endif
131         CC_SRC = (eflags & ~(CC_C | CC_O)) |
132             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
133             ((src >> (DATA_BITS - count)) & CC_C);
134         CC_OP = CC_OP_EFLAGS;
135     }
136     FORCE_RET();
137 }
138
139 void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void)
140 {
141     int count, res, eflags;
142     unsigned int src;
143
144     count = T1 & 0x1f;
145 #if DATA_BITS == 16
146     count = rclw_table[count];
147 #elif DATA_BITS == 8
148     count = rclb_table[count];
149 #endif
150     if (count) {
151         eflags = cc_table[CC_OP].compute_all();
152         T0 &= DATA_MASK;
153         src = T0;
154         res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
155         if (count > 1)
156             res |= T0 << (DATA_BITS + 1 - count);
157         T0 = res;
158 #ifdef MEM_WRITE
159         glue(st, SUFFIX)((uint8_t *)A0, T0);
160 #endif
161         CC_SRC = (eflags & ~(CC_C | CC_O)) |
162             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
163             ((src >> (count - 1)) & CC_C);
164         CC_OP = CC_OP_EFLAGS;
165     }
166     FORCE_RET();
167 }
168
169 void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void)
170 {
171     int count, src;
172     count = T1 & 0x1f;
173     if (count) {
174         src = (DATA_TYPE)T0 << (count - 1);
175         T0 = T0 << count;
176 #ifdef MEM_WRITE
177         glue(st, SUFFIX)((uint8_t *)A0, T0);
178 #endif
179         CC_SRC = src;
180         CC_DST = T0;
181         CC_OP = CC_OP_SHLB + SHIFT;
182     }
183     FORCE_RET();
184 }
185
186 void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void)
187 {
188     int count, src;
189     count = T1 & 0x1f;
190     if (count) {
191         T0 &= DATA_MASK;
192         src = T0 >> (count - 1);
193         T0 = T0 >> count;
194 #ifdef MEM_WRITE
195         glue(st, SUFFIX)((uint8_t *)A0, T0);
196 #endif
197         CC_SRC = src;
198         CC_DST = T0;
199         CC_OP = CC_OP_SARB + SHIFT;
200     }
201     FORCE_RET();
202 }
203
204 void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void)
205 {
206     int count, src;
207     count = T1 & 0x1f;
208     if (count) {
209         src = (DATA_STYPE)T0;
210         T0 = src >> count;
211         src = src >> (count - 1);
212 #ifdef MEM_WRITE
213         glue(st, SUFFIX)((uint8_t *)A0, T0);
214 #endif
215         CC_SRC = src;
216         CC_DST = T0;
217         CC_OP = CC_OP_SARB + SHIFT;
218     }
219     FORCE_RET();
220 }
221
222 #if DATA_BITS == 16
223 /* XXX: overflow flag might be incorrect in some cases in shldw */
224 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
225 {
226     int count;
227     unsigned int res, tmp;
228     count = PARAM1;
229     T1 &= 0xffff;
230     res = T1 | (T0 << 16);
231     tmp = res >> (32 - count);
232     res <<= count;
233     if (count > 16)
234         res |= T1 << (count - 16);
235     T0 = res >> 16;
236 #ifdef MEM_WRITE
237     glue(st, SUFFIX)((uint8_t *)A0, T0);
238 #endif
239     CC_SRC = tmp;
240     CC_DST = T0;
241 }
242
243 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
244 {
245     int count;
246     unsigned int res, tmp;
247     count = ECX & 0x1f;
248     if (count) {
249         T1 &= 0xffff;
250         res = T1 | (T0 << 16);
251         tmp = res >> (32 - count);
252         res <<= count;
253         if (count > 16)
254           res |= T1 << (count - 16);
255         T0 = res >> 16;
256 #ifdef MEM_WRITE
257         glue(st, SUFFIX)((uint8_t *)A0, T0);
258 #endif
259         CC_SRC = tmp;
260         CC_DST = T0;
261         CC_OP = CC_OP_SARB + SHIFT;
262     }
263     FORCE_RET();
264 }
265
266 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
267 {
268     int count;
269     unsigned int res, tmp;
270
271     count = PARAM1;
272     res = (T0 & 0xffff) | (T1 << 16);
273     tmp = res >> (count - 1);
274     res >>= count;
275     if (count > 16)
276         res |= T1 << (32 - count);
277     T0 = res;
278 #ifdef MEM_WRITE
279     glue(st, SUFFIX)((uint8_t *)A0, T0);
280 #endif
281     CC_SRC = tmp;
282     CC_DST = T0;
283 }
284
285
286 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
287 {
288     int count;
289     unsigned int res, tmp;
290
291     count = ECX & 0x1f;
292     if (count) {
293         res = (T0 & 0xffff) | (T1 << 16);
294         tmp = res >> (count - 1);
295         res >>= count;
296         if (count > 16)
297             res |= T1 << (32 - count);
298         T0 = res;
299 #ifdef MEM_WRITE
300         glue(st, SUFFIX)((uint8_t *)A0, T0);
301 #endif
302         CC_SRC = tmp;
303         CC_DST = T0;
304         CC_OP = CC_OP_SARB + SHIFT;
305     }
306     FORCE_RET();
307 }
308 #endif
309
310 #if DATA_BITS == 32
311 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
312 {
313     int count, tmp;
314     count = PARAM1;
315     T0 &= DATA_MASK;
316     T1 &= DATA_MASK;
317     tmp = T0 << (count - 1);
318     T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
319 #ifdef MEM_WRITE
320     glue(st, SUFFIX)((uint8_t *)A0, T0);
321 #endif
322     CC_SRC = tmp;
323     CC_DST = T0;
324 }
325
326 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
327 {
328     int count, tmp;
329     count = ECX & 0x1f;
330     if (count) {
331         T0 &= DATA_MASK;
332         T1 &= DATA_MASK;
333         tmp = T0 << (count - 1);
334         T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
335 #ifdef MEM_WRITE
336         glue(st, SUFFIX)((uint8_t *)A0, T0);
337 #endif
338         CC_SRC = tmp;
339         CC_DST = T0;
340         CC_OP = CC_OP_SHLB + SHIFT;
341     }
342     FORCE_RET();
343 }
344
345 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
346 {
347     int count, tmp;
348     count = PARAM1;
349     T0 &= DATA_MASK;
350     T1 &= DATA_MASK;
351     tmp = T0 >> (count - 1);
352     T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
353 #ifdef MEM_WRITE
354     glue(st, SUFFIX)((uint8_t *)A0, T0);
355 #endif
356     CC_SRC = tmp;
357     CC_DST = T0;
358 }
359
360
361 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
362 {
363     int count, tmp;
364     count = ECX & 0x1f;
365     if (count) {
366         T0 &= DATA_MASK;
367         T1 &= DATA_MASK;
368         tmp = T0 >> (count - 1);
369         T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
370 #ifdef MEM_WRITE
371         glue(st, SUFFIX)((uint8_t *)A0, T0);
372 #endif
373         CC_SRC = tmp;
374         CC_DST = T0;
375         CC_OP = CC_OP_SARB + SHIFT;
376     }
377     FORCE_RET();
378 }
379 #endif
380
381 /* carry add/sub (we only need to set CC_OP differently) */
382
383 void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void)
384 {
385     int cf;
386     cf = cc_table[CC_OP].compute_c();
387     T0 = T0 + T1 + cf;
388 #ifdef MEM_WRITE
389     glue(st, SUFFIX)((uint8_t *)A0, T0);
390 #endif
391     CC_SRC = T1;
392     CC_DST = T0;
393     CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
394 }
395
396 void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void)
397 {
398     int cf;
399     cf = cc_table[CC_OP].compute_c();
400     T0 = T0 - T1 - cf;
401 #ifdef MEM_WRITE
402     glue(st, SUFFIX)((uint8_t *)A0, T0);
403 #endif
404     CC_SRC = T1;
405     CC_DST = T0;
406     CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
407 }
408
409 void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void)
410 {
411     unsigned int src, dst;
412
413     src = T0;
414     dst = EAX - T0;
415     if ((DATA_TYPE)dst == 0) {
416         T0 = T1;
417     } else {
418         EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
419     }
420 #ifdef MEM_WRITE
421     glue(st, SUFFIX)((uint8_t *)A0, T0);
422 #endif
423     CC_SRC = src;
424     CC_DST = dst;
425     FORCE_RET();
426 }
427
428 #undef MEM_SUFFIX
429 #undef MEM_WRITE