0.6.2-alt1
[qemu] / qemu-snapshot-2004-11-28_23 / target-i386 / 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 MEM_WRITE == 0
24
25 #if DATA_BITS == 8
26 #define MEM_SUFFIX b_raw
27 #elif DATA_BITS == 16
28 #define MEM_SUFFIX w_raw
29 #elif DATA_BITS == 32
30 #define MEM_SUFFIX l_raw
31 #endif
32
33 #elif MEM_WRITE == 1
34
35 #if DATA_BITS == 8
36 #define MEM_SUFFIX b_kernel
37 #elif DATA_BITS == 16
38 #define MEM_SUFFIX w_kernel
39 #elif DATA_BITS == 32
40 #define MEM_SUFFIX l_kernel
41 #endif
42
43 #elif MEM_WRITE == 2
44
45 #if DATA_BITS == 8
46 #define MEM_SUFFIX b_user
47 #elif DATA_BITS == 16
48 #define MEM_SUFFIX w_user
49 #elif DATA_BITS == 32
50 #define MEM_SUFFIX l_user
51 #endif
52
53 #else
54
55 #error invalid MEM_WRITE
56
57 #endif
58
59 #else
60
61 #define MEM_SUFFIX SUFFIX
62
63 #endif
64
65 void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void)
66 {
67     int count, src;
68     count = T1 & SHIFT_MASK;
69     if (count) {
70         src = T0;
71         T0 &= DATA_MASK;
72         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
73 #ifdef MEM_WRITE
74         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
75 #else
76         /* gcc 3.2 workaround. This is really a bug in gcc. */
77         asm volatile("" : : "r" (T0));
78 #endif
79         CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | 
80             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
81             (T0 & CC_C);
82         CC_OP = CC_OP_EFLAGS;
83     }
84     FORCE_RET();
85 }
86
87 void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void)
88 {
89     int count, src;
90     count = T1 & SHIFT_MASK;
91     if (count) {
92         src = T0;
93         T0 &= DATA_MASK;
94         T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
95 #ifdef MEM_WRITE
96         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
97 #else
98         /* gcc 3.2 workaround. This is really a bug in gcc. */
99         asm volatile("" : : "r" (T0));
100 #endif
101         CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
102             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
103             ((T0 >> (DATA_BITS - 1)) & CC_C);
104         CC_OP = CC_OP_EFLAGS;
105     }
106     FORCE_RET();
107 }
108
109 void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void)
110 {
111     int count;
112     count = T1 & SHIFT_MASK;
113     if (count) {
114         T0 &= DATA_MASK;
115         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
116 #ifdef MEM_WRITE
117         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
118 #endif
119     }
120     FORCE_RET();
121 }
122
123 void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void)
124 {
125     int count;
126     count = T1 & SHIFT_MASK;
127     if (count) {
128         T0 &= DATA_MASK;
129         T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
130 #ifdef MEM_WRITE
131         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
132 #endif
133     }
134     FORCE_RET();
135 }
136
137 void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void)
138 {
139     int count, res, eflags;
140     unsigned int src;
141
142     count = T1 & 0x1f;
143 #if DATA_BITS == 16
144     count = rclw_table[count];
145 #elif DATA_BITS == 8
146     count = rclb_table[count];
147 #endif
148     if (count) {
149         eflags = cc_table[CC_OP].compute_all();
150         T0 &= DATA_MASK;
151         src = T0;
152         res = (T0 << count) | ((eflags & CC_C) << (count - 1));
153         if (count > 1)
154             res |= T0 >> (DATA_BITS + 1 - count);
155         T0 = res;
156 #ifdef MEM_WRITE
157         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
158 #endif
159         CC_SRC = (eflags & ~(CC_C | CC_O)) |
160             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
161             ((src >> (DATA_BITS - count)) & CC_C);
162         CC_OP = CC_OP_EFLAGS;
163     }
164     FORCE_RET();
165 }
166
167 void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void)
168 {
169     int count, res, eflags;
170     unsigned int src;
171
172     count = T1 & 0x1f;
173 #if DATA_BITS == 16
174     count = rclw_table[count];
175 #elif DATA_BITS == 8
176     count = rclb_table[count];
177 #endif
178     if (count) {
179         eflags = cc_table[CC_OP].compute_all();
180         T0 &= DATA_MASK;
181         src = T0;
182         res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
183         if (count > 1)
184             res |= T0 << (DATA_BITS + 1 - count);
185         T0 = res;
186 #ifdef MEM_WRITE
187         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
188 #endif
189         CC_SRC = (eflags & ~(CC_C | CC_O)) |
190             (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
191             ((src >> (count - 1)) & CC_C);
192         CC_OP = CC_OP_EFLAGS;
193     }
194     FORCE_RET();
195 }
196
197 void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void)
198 {
199     int count, src;
200     count = T1 & 0x1f;
201     if (count) {
202         src = (DATA_TYPE)T0 << (count - 1);
203         T0 = T0 << count;
204 #ifdef MEM_WRITE
205         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
206 #endif
207         CC_SRC = src;
208         CC_DST = T0;
209         CC_OP = CC_OP_SHLB + SHIFT;
210     }
211     FORCE_RET();
212 }
213
214 void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void)
215 {
216     int count, src;
217     count = T1 & 0x1f;
218     if (count) {
219         T0 &= DATA_MASK;
220         src = T0 >> (count - 1);
221         T0 = T0 >> count;
222 #ifdef MEM_WRITE
223         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
224 #endif
225         CC_SRC = src;
226         CC_DST = T0;
227         CC_OP = CC_OP_SARB + SHIFT;
228     }
229     FORCE_RET();
230 }
231
232 void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void)
233 {
234     int count, src;
235     count = T1 & 0x1f;
236     if (count) {
237         src = (DATA_STYPE)T0;
238         T0 = src >> count;
239         src = src >> (count - 1);
240 #ifdef MEM_WRITE
241         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
242 #endif
243         CC_SRC = src;
244         CC_DST = T0;
245         CC_OP = CC_OP_SARB + SHIFT;
246     }
247     FORCE_RET();
248 }
249
250 #if DATA_BITS == 16
251 /* XXX: overflow flag might be incorrect in some cases in shldw */
252 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
253 {
254     int count;
255     unsigned int res, tmp;
256     count = PARAM1;
257     T1 &= 0xffff;
258     res = T1 | (T0 << 16);
259     tmp = res >> (32 - count);
260     res <<= count;
261     if (count > 16)
262         res |= T1 << (count - 16);
263     T0 = res >> 16;
264 #ifdef MEM_WRITE
265     glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
266 #endif
267     CC_SRC = tmp;
268     CC_DST = T0;
269 }
270
271 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
272 {
273     int count;
274     unsigned int res, tmp;
275     count = ECX & 0x1f;
276     if (count) {
277         T1 &= 0xffff;
278         res = T1 | (T0 << 16);
279         tmp = res >> (32 - count);
280         res <<= count;
281         if (count > 16)
282           res |= T1 << (count - 16);
283         T0 = res >> 16;
284 #ifdef MEM_WRITE
285         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
286 #endif
287         CC_SRC = tmp;
288         CC_DST = T0;
289         CC_OP = CC_OP_SARB + SHIFT;
290     }
291     FORCE_RET();
292 }
293
294 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
295 {
296     int count;
297     unsigned int res, tmp;
298
299     count = PARAM1;
300     res = (T0 & 0xffff) | (T1 << 16);
301     tmp = res >> (count - 1);
302     res >>= count;
303     if (count > 16)
304         res |= T1 << (32 - count);
305     T0 = res;
306 #ifdef MEM_WRITE
307     glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
308 #endif
309     CC_SRC = tmp;
310     CC_DST = T0;
311 }
312
313
314 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
315 {
316     int count;
317     unsigned int res, tmp;
318
319     count = ECX & 0x1f;
320     if (count) {
321         res = (T0 & 0xffff) | (T1 << 16);
322         tmp = res >> (count - 1);
323         res >>= count;
324         if (count > 16)
325             res |= T1 << (32 - count);
326         T0 = res;
327 #ifdef MEM_WRITE
328         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
329 #endif
330         CC_SRC = tmp;
331         CC_DST = T0;
332         CC_OP = CC_OP_SARB + SHIFT;
333     }
334     FORCE_RET();
335 }
336 #endif
337
338 #if DATA_BITS == 32
339 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
340 {
341     int count, tmp;
342     count = PARAM1;
343     T0 &= DATA_MASK;
344     T1 &= DATA_MASK;
345     tmp = T0 << (count - 1);
346     T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
347 #ifdef MEM_WRITE
348     glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
349 #endif
350     CC_SRC = tmp;
351     CC_DST = T0;
352 }
353
354 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
355 {
356     int count, tmp;
357     count = ECX & 0x1f;
358     if (count) {
359         T0 &= DATA_MASK;
360         T1 &= DATA_MASK;
361         tmp = T0 << (count - 1);
362         T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
363 #ifdef MEM_WRITE
364         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
365 #endif
366         CC_SRC = tmp;
367         CC_DST = T0;
368         CC_OP = CC_OP_SHLB + SHIFT;
369     }
370     FORCE_RET();
371 }
372
373 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
374 {
375     int count, tmp;
376     count = PARAM1;
377     T0 &= DATA_MASK;
378     T1 &= DATA_MASK;
379     tmp = T0 >> (count - 1);
380     T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
381 #ifdef MEM_WRITE
382     glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
383 #endif
384     CC_SRC = tmp;
385     CC_DST = T0;
386 }
387
388
389 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
390 {
391     int count, tmp;
392     count = ECX & 0x1f;
393     if (count) {
394         T0 &= DATA_MASK;
395         T1 &= DATA_MASK;
396         tmp = T0 >> (count - 1);
397         T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
398 #ifdef MEM_WRITE
399         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
400 #endif
401         CC_SRC = tmp;
402         CC_DST = T0;
403         CC_OP = CC_OP_SARB + SHIFT;
404     }
405     FORCE_RET();
406 }
407 #endif
408
409 /* carry add/sub (we only need to set CC_OP differently) */
410
411 void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void)
412 {
413     int cf;
414     cf = cc_table[CC_OP].compute_c();
415     T0 = T0 + T1 + cf;
416 #ifdef MEM_WRITE
417     glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
418 #endif
419     CC_SRC = T1;
420     CC_DST = T0;
421     CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
422 }
423
424 void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void)
425 {
426     int cf;
427     cf = cc_table[CC_OP].compute_c();
428     T0 = T0 - T1 - cf;
429 #ifdef MEM_WRITE
430     glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
431 #endif
432     CC_SRC = T1;
433     CC_DST = T0;
434     CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
435 }
436
437 void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void)
438 {
439     unsigned int src, dst;
440
441     src = T0;
442     dst = EAX - T0;
443     if ((DATA_TYPE)dst == 0) {
444         T0 = T1;
445 #ifdef MEM_WRITE
446         glue(st, MEM_SUFFIX)((uint8_t *)A0, T0);
447 #endif
448     } else {
449         EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
450     }
451     CC_SRC = src;
452     CC_DST = dst;
453     FORCE_RET();
454 }
455
456 #undef MEM_SUFFIX
457 #undef MEM_WRITE