0.6.2-alt1.1
[qemu] / qemu-snapshot-2004-11-28_23 / target-i386 / ops_template.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 #define DATA_BITS (1 << (3 + SHIFT))
22 #define SHIFT_MASK (DATA_BITS - 1)
23 #define SIGN_MASK (1 << (DATA_BITS - 1))
24
25 #if DATA_BITS == 8
26 #define SUFFIX b
27 #define DATA_TYPE uint8_t
28 #define DATA_STYPE int8_t
29 #define DATA_MASK 0xff
30 #elif DATA_BITS == 16
31 #define SUFFIX w
32 #define DATA_TYPE uint16_t
33 #define DATA_STYPE int16_t
34 #define DATA_MASK 0xffff
35 #elif DATA_BITS == 32
36 #define SUFFIX l
37 #define DATA_TYPE uint32_t
38 #define DATA_STYPE int32_t
39 #define DATA_MASK 0xffffffff
40 #else
41 #error unhandled operand size
42 #endif
43
44 /* dynamic flags computation */
45
46 static int glue(compute_all_add, SUFFIX)(void)
47 {
48     int cf, pf, af, zf, sf, of;
49     int src1, src2;
50     src1 = CC_SRC;
51     src2 = CC_DST - CC_SRC;
52     cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
53     pf = parity_table[(uint8_t)CC_DST];
54     af = (CC_DST ^ src1 ^ src2) & 0x10;
55     zf = ((DATA_TYPE)CC_DST == 0) << 6;
56     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
57     of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
58     return cf | pf | af | zf | sf | of;
59 }
60
61 static int glue(compute_c_add, SUFFIX)(void)
62 {
63     int src1, cf;
64     src1 = CC_SRC;
65     cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
66     return cf;
67 }
68
69 static int glue(compute_all_adc, SUFFIX)(void)
70 {
71     int cf, pf, af, zf, sf, of;
72     int src1, src2;
73     src1 = CC_SRC;
74     src2 = CC_DST - CC_SRC - 1;
75     cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
76     pf = parity_table[(uint8_t)CC_DST];
77     af = (CC_DST ^ src1 ^ src2) & 0x10;
78     zf = ((DATA_TYPE)CC_DST == 0) << 6;
79     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
80     of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
81     return cf | pf | af | zf | sf | of;
82 }
83
84 static int glue(compute_c_adc, SUFFIX)(void)
85 {
86     int src1, cf;
87     src1 = CC_SRC;
88     cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
89     return cf;
90 }
91
92 static int glue(compute_all_sub, SUFFIX)(void)
93 {
94     int cf, pf, af, zf, sf, of;
95     int src1, src2;
96     src1 = CC_DST + CC_SRC;
97     src2 = CC_SRC;
98     cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
99     pf = parity_table[(uint8_t)CC_DST];
100     af = (CC_DST ^ src1 ^ src2) & 0x10;
101     zf = ((DATA_TYPE)CC_DST == 0) << 6;
102     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
103     of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
104     return cf | pf | af | zf | sf | of;
105 }
106
107 static int glue(compute_c_sub, SUFFIX)(void)
108 {
109     int src1, src2, cf;
110     src1 = CC_DST + CC_SRC;
111     src2 = CC_SRC;
112     cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
113     return cf;
114 }
115
116 static int glue(compute_all_sbb, SUFFIX)(void)
117 {
118     int cf, pf, af, zf, sf, of;
119     int src1, src2;
120     src1 = CC_DST + CC_SRC + 1;
121     src2 = CC_SRC;
122     cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
123     pf = parity_table[(uint8_t)CC_DST];
124     af = (CC_DST ^ src1 ^ src2) & 0x10;
125     zf = ((DATA_TYPE)CC_DST == 0) << 6;
126     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
127     of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
128     return cf | pf | af | zf | sf | of;
129 }
130
131 static int glue(compute_c_sbb, SUFFIX)(void)
132 {
133     int src1, src2, cf;
134     src1 = CC_DST + CC_SRC + 1;
135     src2 = CC_SRC;
136     cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
137     return cf;
138 }
139
140 static int glue(compute_all_logic, SUFFIX)(void)
141 {
142     int cf, pf, af, zf, sf, of;
143     cf = 0;
144     pf = parity_table[(uint8_t)CC_DST];
145     af = 0;
146     zf = ((DATA_TYPE)CC_DST == 0) << 6;
147     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
148     of = 0;
149     return cf | pf | af | zf | sf | of;
150 }
151
152 static int glue(compute_c_logic, SUFFIX)(void)
153 {
154     return 0;
155 }
156
157 static int glue(compute_all_inc, SUFFIX)(void)
158 {
159     int cf, pf, af, zf, sf, of;
160     int src1, src2;
161     src1 = CC_DST - 1;
162     src2 = 1;
163     cf = CC_SRC;
164     pf = parity_table[(uint8_t)CC_DST];
165     af = (CC_DST ^ src1 ^ src2) & 0x10;
166     zf = ((DATA_TYPE)CC_DST == 0) << 6;
167     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
168     of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
169     return cf | pf | af | zf | sf | of;
170 }
171
172 #if DATA_BITS == 32
173 static int glue(compute_c_inc, SUFFIX)(void)
174 {
175     return CC_SRC;
176 }
177 #endif
178
179 static int glue(compute_all_dec, SUFFIX)(void)
180 {
181     int cf, pf, af, zf, sf, of;
182     int 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) == ((uint32_t)SIGN_MASK - 1)) << 11;
191     return cf | pf | af | zf | sf | of;
192 }
193
194 static int glue(compute_all_shl, SUFFIX)(void)
195 {
196     int cf, pf, af, zf, sf, of;
197     cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
198     pf = parity_table[(uint8_t)CC_DST];
199     af = 0; /* undefined */
200     zf = ((DATA_TYPE)CC_DST == 0) << 6;
201     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
202     /* of is defined if shift count == 1 */
203     of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
204     return cf | pf | af | zf | sf | of;
205 }
206
207 static int glue(compute_c_shl, SUFFIX)(void)
208 {
209     return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
210 }
211
212 #if DATA_BITS == 32
213 static int glue(compute_c_sar, SUFFIX)(void)
214 {
215     return CC_SRC & 1;
216 }
217 #endif
218
219 static int glue(compute_all_sar, SUFFIX)(void)
220 {
221     int cf, pf, af, zf, sf, of;
222     cf = CC_SRC & 1;
223     pf = parity_table[(uint8_t)CC_DST];
224     af = 0; /* undefined */
225     zf = ((DATA_TYPE)CC_DST == 0) << 6;
226     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
227     /* of is defined if shift count == 1 */
228     of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; 
229     return cf | pf | af | zf | sf | of;
230 }
231
232 #if DATA_BITS == 32
233 static int glue(compute_c_mul, SUFFIX)(void)
234 {
235     int cf;
236     cf = (CC_SRC != 0);
237     return cf;
238 }
239 #endif
240
241 /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
242    CF are modified and it is slower to do that. */
243 static int glue(compute_all_mul, SUFFIX)(void)
244 {
245     int cf, pf, af, zf, sf, of;
246     cf = (CC_SRC != 0);
247     pf = parity_table[(uint8_t)CC_DST];
248     af = 0; /* undefined */
249     zf = ((DATA_TYPE)CC_DST == 0) << 6;
250     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
251     of = cf << 11;
252     return cf | pf | af | zf | sf | of;
253 }
254
255 /* various optimized jumps cases */
256
257 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
258 {
259     int src1, src2;
260     src1 = CC_DST + CC_SRC;
261     src2 = CC_SRC;
262
263     if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
264         JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 0, PARAM2);
265     else
266         JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 1, PARAM3);
267     FORCE_RET();
268 }
269
270 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
271 {
272     if ((DATA_TYPE)CC_DST == 0)
273         JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 0, PARAM2);
274     else
275         JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 1, PARAM3);
276     FORCE_RET();
277 }
278
279 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
280 {
281     int src1, src2;
282     src1 = CC_DST + CC_SRC;
283     src2 = CC_SRC;
284
285     if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
286         JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 0, PARAM2);
287     else
288         JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 1, PARAM3);
289     FORCE_RET();
290 }
291
292 void OPPROTO glue(op_js_sub, SUFFIX)(void)
293 {
294     if (CC_DST & SIGN_MASK)
295         JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 0, PARAM2);
296     else
297         JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 1, PARAM3);
298     FORCE_RET();
299 }
300
301 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
302 {
303     int src1, src2;
304     src1 = CC_DST + CC_SRC;
305     src2 = CC_SRC;
306
307     if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
308         JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 0, PARAM2);
309     else
310         JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 1, PARAM3);
311     FORCE_RET();
312 }
313
314 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
315 {
316     int src1, src2;
317     src1 = CC_DST + CC_SRC;
318     src2 = CC_SRC;
319
320     if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
321         JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 0, PARAM2);
322     else
323         JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 1, PARAM3);
324     FORCE_RET();
325 }
326
327 /* oldies */
328
329 #if DATA_BITS >= 16
330
331 void OPPROTO glue(op_loopnz, SUFFIX)(void)
332 {
333     unsigned int tmp;
334     int eflags;
335     eflags = cc_table[CC_OP].compute_all();
336     tmp = (ECX - 1) & DATA_MASK;
337     ECX = (ECX & ~DATA_MASK) | tmp;
338     if (tmp != 0 && !(eflags & CC_Z))
339         EIP = PARAM1;
340     else
341         EIP = PARAM2;
342     FORCE_RET();
343 }
344
345 void OPPROTO glue(op_loopz, SUFFIX)(void)
346 {
347     unsigned int tmp;
348     int eflags;
349     eflags = cc_table[CC_OP].compute_all();
350     tmp = (ECX - 1) & DATA_MASK;
351     ECX = (ECX & ~DATA_MASK) | tmp;
352     if (tmp != 0 && (eflags & CC_Z))
353         EIP = PARAM1;
354     else
355         EIP = PARAM2;
356     FORCE_RET();
357 }
358
359 void OPPROTO glue(op_loop, SUFFIX)(void)
360 {
361     unsigned int tmp;
362     tmp = (ECX - 1) & DATA_MASK;
363     ECX = (ECX & ~DATA_MASK) | tmp;
364     if (tmp != 0)
365         EIP = PARAM1;
366     else
367         EIP = PARAM2;
368     FORCE_RET();
369 }
370
371 void OPPROTO glue(op_jecxz, SUFFIX)(void)
372 {
373     if ((DATA_TYPE)ECX == 0)
374         EIP = PARAM1;
375     else
376         EIP = PARAM2;
377     FORCE_RET();
378 }
379
380 #endif
381
382 /* various optimized set cases */
383
384 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
385 {
386     int src1, src2;
387     src1 = CC_DST + CC_SRC;
388     src2 = CC_SRC;
389
390     T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
391 }
392
393 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
394 {
395     T0 = ((DATA_TYPE)CC_DST == 0);
396 }
397
398 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
399 {
400     int src1, src2;
401     src1 = CC_DST + CC_SRC;
402     src2 = CC_SRC;
403
404     T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
405 }
406
407 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
408 {
409     T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
410 }
411
412 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
413 {
414     int src1, src2;
415     src1 = CC_DST + CC_SRC;
416     src2 = CC_SRC;
417
418     T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
419 }
420
421 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
422 {
423     int src1, src2;
424     src1 = CC_DST + CC_SRC;
425     src2 = CC_SRC;
426
427     T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
428 }
429
430 /* shifts */
431
432 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
433 {
434     int count;
435     count = T1 & 0x1f;
436     T0 = T0 << count;
437     FORCE_RET();
438 }
439
440 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
441 {
442     int count;
443     count = T1 & 0x1f;
444     T0 &= DATA_MASK;
445     T0 = T0 >> count;
446     FORCE_RET();
447 }
448
449 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
450 {
451     int count, src;
452     count = T1 & 0x1f;
453     src = (DATA_STYPE)T0;
454     T0 = src >> count;
455     FORCE_RET();
456 }
457
458 #undef MEM_WRITE
459 #include "ops_template_mem.h"
460
461 #define MEM_WRITE 0
462 #include "ops_template_mem.h"
463
464 #if !defined(CONFIG_USER_ONLY)
465 #define MEM_WRITE 1
466 #include "ops_template_mem.h"
467
468 #define MEM_WRITE 2
469 #include "ops_template_mem.h"
470 #endif
471
472 /* bit operations */
473 #if DATA_BITS >= 16
474
475 void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
476 {
477     int count;
478     count = T1 & SHIFT_MASK;
479     CC_SRC = T0 >> count;
480 }
481
482 void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
483 {
484     int count;
485     count = T1 & SHIFT_MASK;
486     T1 = T0 >> count;
487     T0 |= (1 << count);
488 }
489
490 void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
491 {
492     int count;
493     count = T1 & SHIFT_MASK;
494     T1 = T0 >> count;
495     T0 &= ~(1 << count);
496 }
497
498 void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
499 {
500     int count;
501     count = T1 & SHIFT_MASK;
502     T1 = T0 >> count;
503     T0 ^= (1 << count);
504 }
505
506 void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
507 {
508     int res, count;
509     res = T0 & DATA_MASK;
510     if (res != 0) {
511         count = 0;
512         while ((res & 1) == 0) {
513             count++;
514             res >>= 1;
515         }
516         T1 = count;
517         CC_DST = 1; /* ZF = 0 */
518     } else {
519         CC_DST = 0; /* ZF = 1 */
520     }
521     FORCE_RET();
522 }
523
524 void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
525 {
526     int res, count;
527     res = T0 & DATA_MASK;
528     if (res != 0) {
529         count = DATA_BITS - 1;
530         while ((res & SIGN_MASK) == 0) {
531             count--;
532             res <<= 1;
533         }
534         T1 = count;
535         CC_DST = 1; /* ZF = 0 */
536     } else {
537         CC_DST = 0; /* ZF = 1 */
538     }
539     FORCE_RET();
540 }
541
542 #endif
543
544 #if DATA_BITS == 32
545 void OPPROTO op_update_bt_cc(void)
546 {
547     CC_SRC = T1;
548 }
549 #endif
550
551 /* string operations */
552
553 void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
554 {
555     T0 = DF << SHIFT;
556 }
557
558 void OPPROTO glue(op_string_jz_sub, SUFFIX)(void)
559 {
560     if ((DATA_TYPE)CC_DST == 0)
561         JUMP_TB2(glue(op_string_jz_sub, SUFFIX), PARAM1, 3);
562     FORCE_RET();
563 }
564
565 void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void)
566 {
567     if ((DATA_TYPE)CC_DST != 0)
568         JUMP_TB2(glue(op_string_jnz_sub, SUFFIX), PARAM1, 3);
569     FORCE_RET();
570 }
571
572 void OPPROTO glue(glue(op_string_jz_sub, SUFFIX), _im)(void)
573 {
574     if ((DATA_TYPE)CC_DST == 0) {
575         EIP = PARAM1;
576         if (env->eflags & TF_MASK) {
577             raise_exception(EXCP01_SSTP);
578         }
579         T0 = 0;
580         EXIT_TB();
581     }
582     FORCE_RET();
583 }
584
585 void OPPROTO glue(glue(op_string_jnz_sub, SUFFIX), _im)(void)
586 {
587     if ((DATA_TYPE)CC_DST != 0) {
588         EIP = PARAM1;
589         if (env->eflags & TF_MASK) {
590             raise_exception(EXCP01_SSTP);
591         }
592         T0 = 0;
593         EXIT_TB();
594     }
595     FORCE_RET();
596 }
597
598 #if DATA_BITS >= 16
599 void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
600 {
601     if ((DATA_TYPE)ECX == 0)
602         JUMP_TB(glue(op_jz_ecx, SUFFIX), PARAM1, 1, PARAM2);
603     FORCE_RET();
604 }
605
606 void OPPROTO glue(glue(op_jz_ecx, SUFFIX), _im)(void)
607 {
608     if ((DATA_TYPE)ECX == 0) {
609         EIP = PARAM1;
610         if (env->eflags & TF_MASK) {
611             raise_exception(EXCP01_SSTP);
612         }
613         T0 = 0;
614         EXIT_TB();
615     }
616     FORCE_RET();
617 }
618 #endif
619
620 /* port I/O */
621
622 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
623 {
624     glue(cpu_out, SUFFIX)(env, T0, T1 & DATA_MASK);
625 }
626
627 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
628 {
629     T1 = glue(cpu_in, SUFFIX)(env, T0);
630 }
631
632 void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
633 {
634     T0 = glue(cpu_in, SUFFIX)(env, EDX & 0xffff);
635 }
636
637 void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
638 {
639     glue(cpu_out, SUFFIX)(env, EDX & 0xffff, T0);
640 }
641
642 void OPPROTO glue(glue(op_check_io, SUFFIX), _T0)(void)
643 {
644     glue(glue(check_io, SUFFIX), _T0)();
645 }
646
647 void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void)
648 {
649     glue(glue(check_io, SUFFIX), _DX)();
650 }
651
652 #undef DATA_BITS
653 #undef SHIFT_MASK
654 #undef SIGN_MASK
655 #undef DATA_TYPE
656 #undef DATA_STYPE
657 #undef DATA_MASK
658 #undef SUFFIX