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