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