]>
git.proxmox.com Git - qemu.git/blob - ops_template.h
745c27d7e5426aea4ca918596f86ba44a8ffef78
2 #define DATA_BITS (1 << (3 + SHIFT))
3 #define SHIFT_MASK (DATA_BITS - 1)
4 #define SIGN_MASK (1 << (DATA_BITS - 1))
8 #define DATA_TYPE uint8_t
9 #define DATA_STYPE int8_t
10 #define DATA_MASK 0xff
13 #define DATA_TYPE uint16_t
14 #define DATA_STYPE int16_t
15 #define DATA_MASK 0xffff
18 #define DATA_TYPE uint32_t
19 #define DATA_STYPE int32_t
20 #define DATA_MASK 0xffffffff
22 #error unhandled operand size
25 /* dynamic flags computation */
27 static int glue(compute_all_add
, SUFFIX
)(void)
29 int cf
, pf
, af
, zf
, sf
, of
;
32 src2
= CC_DST
- CC_SRC
;
33 cf
= (DATA_TYPE
)CC_DST
< (DATA_TYPE
)src1
;
34 pf
= parity_table
[(uint8_t)CC_DST
];
35 af
= (CC_DST
^ src1
^ src2
) & 0x10;
36 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
37 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
38 of
= lshift((src1
^ src2
^ -1) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
39 return cf
| pf
| af
| zf
| sf
| of
;
42 static int glue(compute_c_add
, SUFFIX
)(void)
46 cf
= (DATA_TYPE
)CC_DST
< (DATA_TYPE
)src1
;
50 static int glue(compute_all_adc
, SUFFIX
)(void)
52 int cf
, pf
, af
, zf
, sf
, of
;
55 src2
= CC_DST
- CC_SRC
- 1;
56 cf
= (DATA_TYPE
)CC_DST
<= (DATA_TYPE
)src1
;
57 pf
= parity_table
[(uint8_t)CC_DST
];
58 af
= (CC_DST
^ src1
^ src2
) & 0x10;
59 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
60 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
61 of
= lshift((src1
^ src2
^ -1) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
62 return cf
| pf
| af
| zf
| sf
| of
;
65 static int glue(compute_c_adc
, SUFFIX
)(void)
69 cf
= (DATA_TYPE
)CC_DST
<= (DATA_TYPE
)src1
;
73 static int glue(compute_all_sub
, SUFFIX
)(void)
75 int cf
, pf
, af
, zf
, sf
, of
;
78 src2
= CC_SRC
- CC_DST
;
79 cf
= (DATA_TYPE
)src1
< (DATA_TYPE
)src2
;
80 pf
= parity_table
[(uint8_t)CC_DST
];
81 af
= (CC_DST
^ src1
^ src2
) & 0x10;
82 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
83 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
84 of
= lshift((src1
^ src2
) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
85 return cf
| pf
| af
| zf
| sf
| of
;
88 static int glue(compute_c_sub
, SUFFIX
)(void)
92 src2
= CC_SRC
- CC_DST
;
93 cf
= (DATA_TYPE
)src1
< (DATA_TYPE
)src2
;
97 static int glue(compute_all_sbb
, SUFFIX
)(void)
99 int cf
, pf
, af
, zf
, sf
, of
;
102 src2
= CC_SRC
- CC_DST
- 1;
103 cf
= (DATA_TYPE
)src1
<= (DATA_TYPE
)src2
;
104 pf
= parity_table
[(uint8_t)CC_DST
];
105 af
= (CC_DST
^ src1
^ src2
) & 0x10;
106 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
107 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
108 of
= lshift((src1
^ src2
) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
109 return cf
| pf
| af
| zf
| sf
| of
;
112 static int glue(compute_c_sbb
, SUFFIX
)(void)
116 src2
= CC_SRC
- CC_DST
- 1;
117 cf
= (DATA_TYPE
)src1
<= (DATA_TYPE
)src2
;
121 static int glue(compute_all_logic
, SUFFIX
)(void)
123 int cf
, pf
, af
, zf
, sf
, of
;
125 pf
= parity_table
[(uint8_t)CC_DST
];
127 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
128 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
130 return cf
| pf
| af
| zf
| sf
| of
;
133 static int glue(compute_c_logic
, SUFFIX
)(void)
138 static int glue(compute_all_inc
, SUFFIX
)(void)
140 int cf
, pf
, af
, zf
, sf
, of
;
145 pf
= parity_table
[(uint8_t)CC_DST
];
146 af
= (CC_DST
^ src1
^ src2
) & 0x10;
147 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
148 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
149 of
= ((CC_DST
& DATA_MASK
) == SIGN_MASK
) << 11;
150 return cf
| pf
| af
| zf
| sf
| of
;
154 static int glue(compute_c_inc
, SUFFIX
)(void)
160 static int glue(compute_all_dec
, SUFFIX
)(void)
162 int cf
, pf
, af
, zf
, sf
, of
;
167 pf
= parity_table
[(uint8_t)CC_DST
];
168 af
= (CC_DST
^ src1
^ src2
) & 0x10;
169 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
170 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
171 of
= ((CC_DST
& DATA_MASK
) == ((uint32_t)SIGN_MASK
- 1)) << 11;
172 return cf
| pf
| af
| zf
| sf
| of
;
175 static int glue(compute_all_shl
, SUFFIX
)(void)
177 int cf
, pf
, af
, zf
, sf
, of
;
178 cf
= (CC_SRC
>> (DATA_BITS
- 1)) & CC_C
;
179 pf
= parity_table
[(uint8_t)CC_DST
];
180 af
= 0; /* undefined */
181 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
182 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
183 /* of is defined if shift count == 1 */
184 of
= lshift(CC_SRC
^ CC_DST
, 12 - DATA_BITS
) & CC_O
;
185 return cf
| pf
| af
| zf
| sf
| of
;
189 static int glue(compute_c_shl
, SUFFIX
)(void)
195 static int glue(compute_all_sar
, SUFFIX
)(void)
197 int cf
, pf
, af
, zf
, sf
, of
;
199 pf
= parity_table
[(uint8_t)CC_DST
];
200 af
= 0; /* undefined */
201 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
202 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
203 /* of is defined if shift count == 1 */
204 of
= lshift(CC_SRC
^ CC_DST
, 12 - DATA_BITS
) & CC_O
;
205 return cf
| pf
| af
| zf
| sf
| of
;
208 /* various optimized jumps cases */
210 void OPPROTO
glue(op_jb_sub
, SUFFIX
)(void)
214 src2
= CC_SRC
- CC_DST
;
216 if ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
)
223 void OPPROTO
glue(op_jz_sub
, SUFFIX
)(void)
225 if ((DATA_TYPE
)CC_DST
== 0)
232 void OPPROTO
glue(op_jbe_sub
, SUFFIX
)(void)
236 src2
= CC_SRC
- CC_DST
;
238 if ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
)
245 void OPPROTO
glue(op_js_sub
, SUFFIX
)(void)
247 if (CC_DST
& SIGN_MASK
)
254 void OPPROTO
glue(op_jl_sub
, SUFFIX
)(void)
258 src2
= CC_SRC
- CC_DST
;
260 if ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
)
267 void OPPROTO
glue(op_jle_sub
, SUFFIX
)(void)
271 src2
= CC_SRC
- CC_DST
;
273 if ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
)
280 /* various optimized set cases */
282 void OPPROTO
glue(op_setb_T0_sub
, SUFFIX
)(void)
286 src2
= CC_SRC
- CC_DST
;
288 T0
= ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
);
291 void OPPROTO
glue(op_setz_T0_sub
, SUFFIX
)(void)
293 T0
= ((DATA_TYPE
)CC_DST
== 0);
296 void OPPROTO
glue(op_setbe_T0_sub
, SUFFIX
)(void)
300 src2
= CC_SRC
- CC_DST
;
302 T0
= ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
);
305 void OPPROTO
glue(op_sets_T0_sub
, SUFFIX
)(void)
307 T0
= lshift(CC_DST
, -(DATA_BITS
- 1)) & 1;
310 void OPPROTO
glue(op_setl_T0_sub
, SUFFIX
)(void)
314 src2
= CC_SRC
- CC_DST
;
316 T0
= ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
);
319 void OPPROTO
glue(op_setle_T0_sub
, SUFFIX
)(void)
323 src2
= CC_SRC
- CC_DST
;
325 T0
= ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
);
330 void OPPROTO
glue(glue(op_rol
, SUFFIX
), _T0_T1_cc
)(void)
333 count
= T1
& SHIFT_MASK
;
335 CC_SRC
= cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
);
338 T0
= (T0
<< count
) | (T0
>> (DATA_BITS
- count
));
339 CC_SRC
|= (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
341 CC_OP
= CC_OP_EFLAGS
;
346 void OPPROTO
glue(glue(op_ror
, SUFFIX
), _T0_T1_cc
)(void)
349 count
= T1
& SHIFT_MASK
;
351 CC_SRC
= cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
);
354 T0
= (T0
>> count
) | (T0
<< (DATA_BITS
- count
));
355 CC_SRC
|= (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
356 ((T0
>> (DATA_BITS
- 1)) & CC_C
);
357 CC_OP
= CC_OP_EFLAGS
;
362 void OPPROTO
glue(glue(op_rcl
, SUFFIX
), _T0_T1_cc
)(void)
364 int count
, res
, eflags
;
369 count
= rclw_table
[count
];
371 count
= rclb_table
[count
];
374 eflags
= cc_table
[CC_OP
].compute_all();
377 res
= (T0
<< count
) | ((eflags
& CC_C
) << (count
- 1));
379 res
|= T0
>> (DATA_BITS
+ 1 - count
);
381 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
382 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
383 ((src
>> (DATA_BITS
- count
)) & CC_C
);
384 CC_OP
= CC_OP_EFLAGS
;
389 void OPPROTO
glue(glue(op_rcr
, SUFFIX
), _T0_T1_cc
)(void)
391 int count
, res
, eflags
;
396 count
= rclw_table
[count
];
398 count
= rclb_table
[count
];
401 eflags
= cc_table
[CC_OP
].compute_all();
404 res
= (T0
>> count
) | ((eflags
& CC_C
) << (DATA_BITS
- count
));
406 res
|= T0
<< (DATA_BITS
+ 1 - count
);
408 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
409 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
410 ((src
>> (count
- 1)) & CC_C
);
411 CC_OP
= CC_OP_EFLAGS
;
416 void OPPROTO
glue(glue(op_shl
, SUFFIX
), _T0_T1_cc
)(void)
421 CC_SRC
= (DATA_TYPE
)T0
<< (count
- 1);
424 CC_OP
= CC_OP_SHLB
+ SHIFT
;
429 void OPPROTO
glue(glue(op_shr
, SUFFIX
), _T0_T1_cc
)(void)
435 CC_SRC
= T0
>> (count
- 1);
438 CC_OP
= CC_OP_SARB
+ SHIFT
;
443 void OPPROTO
glue(glue(op_sar
, SUFFIX
), _T0_T1_cc
)(void)
448 src
= (DATA_STYPE
)T0
;
449 CC_SRC
= src
>> (count
- 1);
452 CC_OP
= CC_OP_SARB
+ SHIFT
;
458 /* XXX: overflow flag might be incorrect in some cases in shldw */
459 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_im_cc
)(void)
465 res
= T1
| (T0
<< 16);
466 CC_SRC
= res
>> (32 - count
);
469 res
|= T1
<< (count
- 16);
474 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_ECX_cc
)(void)
481 res
= T1
| (T0
<< 16);
482 CC_SRC
= res
>> (32 - count
);
485 res
|= T1
<< (count
- 16);
488 CC_OP
= CC_OP_SARB
+ SHIFT
;
492 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_im_cc
)(void)
498 res
= (T0
& 0xffff) | (T1
<< 16);
499 CC_SRC
= res
>> (count
- 1);
502 res
|= T1
<< (32 - count
);
508 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_ECX_cc
)(void)
515 res
= (T0
& 0xffff) | (T1
<< 16);
516 CC_SRC
= res
>> (count
- 1);
519 res
|= T1
<< (32 - count
);
522 CC_OP
= CC_OP_SARB
+ SHIFT
;
528 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_im_cc
)(void)
534 CC_SRC
= T0
<< (count
- 1);
535 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
539 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_ECX_cc
)(void)
546 CC_SRC
= T0
<< (count
- 1);
547 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
549 CC_OP
= CC_OP_SHLB
+ SHIFT
;
553 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_im_cc
)(void)
559 CC_SRC
= T0
>> (count
- 1);
560 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
565 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_ECX_cc
)(void)
572 CC_SRC
= T0
>> (count
- 1);
573 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
575 CC_OP
= CC_OP_SARB
+ SHIFT
;
580 /* carry add/sub (we only need to set CC_OP differently) */
582 void OPPROTO
glue(glue(op_adc
, SUFFIX
), _T0_T1_cc
)(void)
585 cf
= cc_table
[CC_OP
].compute_c();
589 CC_OP
= CC_OP_ADDB
+ SHIFT
+ cf
* 3;
592 void OPPROTO
glue(glue(op_sbb
, SUFFIX
), _T0_T1_cc
)(void)
595 cf
= cc_table
[CC_OP
].compute_c();
599 CC_OP
= CC_OP_SUBB
+ SHIFT
+ cf
* 3;
605 void OPPROTO
glue(glue(op_bt
, SUFFIX
), _T0_T1_cc
)(void)
608 count
= T1
& SHIFT_MASK
;
609 CC_SRC
= T0
>> count
;
612 void OPPROTO
glue(glue(op_bts
, SUFFIX
), _T0_T1_cc
)(void)
615 count
= T1
& SHIFT_MASK
;
616 CC_SRC
= T0
>> count
;
620 void OPPROTO
glue(glue(op_btr
, SUFFIX
), _T0_T1_cc
)(void)
623 count
= T1
& SHIFT_MASK
;
624 CC_SRC
= T0
>> count
;
628 void OPPROTO
glue(glue(op_btc
, SUFFIX
), _T0_T1_cc
)(void)
631 count
= T1
& SHIFT_MASK
;
632 CC_SRC
= T0
>> count
;
636 void OPPROTO
glue(glue(op_bsf
, SUFFIX
), _T0_cc
)(void)
639 res
= T0
& DATA_MASK
;
642 while ((res
& 1) == 0) {
647 CC_DST
= 1; /* ZF = 1 */
649 CC_DST
= 0; /* ZF = 1 */
654 void OPPROTO
glue(glue(op_bsr
, SUFFIX
), _T0_cc
)(void)
657 res
= T0
& DATA_MASK
;
659 count
= DATA_BITS
- 1;
660 while ((res
& SIGN_MASK
) == 0) {
665 CC_DST
= 1; /* ZF = 1 */
667 CC_DST
= 0; /* ZF = 1 */
674 /* string operations */
675 /* XXX: maybe use lower level instructions to ease exception handling */
677 void OPPROTO
glue(op_movs
, SUFFIX
)(void)
680 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
681 glue(st
, SUFFIX
)((void *)EDI
, v
);
682 ESI
+= (DF
<< SHIFT
);
683 EDI
+= (DF
<< SHIFT
);
686 void OPPROTO
glue(op_rep_movs
, SUFFIX
)(void)
691 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
692 glue(st
, SUFFIX
)((void *)EDI
, v
);
699 void OPPROTO
glue(op_stos
, SUFFIX
)(void)
701 glue(st
, SUFFIX
)((void *)EDI
, EAX
);
702 EDI
+= (DF
<< SHIFT
);
705 void OPPROTO
glue(op_rep_stos
, SUFFIX
)(void)
710 glue(st
, SUFFIX
)((void *)EDI
, EAX
);
716 void OPPROTO
glue(op_lods
, SUFFIX
)(void)
719 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
721 EAX
= (EAX
& ~0xff) | v
;
723 EAX
= (EAX
& ~0xffff) | v
;
727 ESI
+= (DF
<< SHIFT
);
730 /* don't know if it is used */
731 void OPPROTO
glue(op_rep_lods
, SUFFIX
)(void)
736 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
738 EAX
= (EAX
& ~0xff) | v
;
740 EAX
= (EAX
& ~0xffff) | v
;
749 void OPPROTO
glue(op_scas
, SUFFIX
)(void)
753 v
= glue(ldu
, SUFFIX
)((void *)EDI
);
754 EDI
+= (DF
<< SHIFT
);
759 void OPPROTO
glue(op_repz_scas
, SUFFIX
)(void)
764 /* NOTE: the flags are not modified if ECX == 0 */
765 v1
= EAX
& DATA_MASK
;
768 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
776 CC_OP
= CC_OP_SUBB
+ SHIFT
;
780 void OPPROTO
glue(op_repnz_scas
, SUFFIX
)(void)
785 /* NOTE: the flags are not modified if ECX == 0 */
786 v1
= EAX
& DATA_MASK
;
789 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
797 CC_OP
= CC_OP_SUBB
+ SHIFT
;
801 void OPPROTO
glue(op_cmps
, SUFFIX
)(void)
804 v1
= glue(ldu
, SUFFIX
)((void *)ESI
);
805 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
806 ESI
+= (DF
<< SHIFT
);
807 EDI
+= (DF
<< SHIFT
);
812 void OPPROTO
glue(op_repz_cmps
, SUFFIX
)(void)
818 v1
= glue(ldu
, SUFFIX
)((void *)ESI
);
819 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
828 CC_OP
= CC_OP_SUBB
+ SHIFT
;
832 void OPPROTO
glue(op_repnz_cmps
, SUFFIX
)(void)
838 v1
= glue(ldu
, SUFFIX
)((void *)ESI
);
839 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
848 CC_OP
= CC_OP_SUBB
+ SHIFT
;
854 void OPPROTO
glue(op_outs
, SUFFIX
)(void)
858 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
859 glue(cpu_x86_out
, SUFFIX
)(dx
, v
);
860 ESI
+= (DF
<< SHIFT
);
863 void OPPROTO
glue(op_rep_outs
, SUFFIX
)(void)
869 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
870 glue(cpu_x86_out
, SUFFIX
)(dx
, v
);
876 void OPPROTO
glue(op_ins
, SUFFIX
)(void)
880 v
= glue(cpu_x86_in
, SUFFIX
)(dx
);
881 glue(st
, SUFFIX
)((void *)EDI
, v
);
882 EDI
+= (DF
<< SHIFT
);
885 void OPPROTO
glue(op_rep_ins
, SUFFIX
)(void)
891 v
= glue(cpu_x86_in
, SUFFIX
)(dx
);
892 glue(st
, SUFFIX
)((void *)EDI
, v
);
893 EDI
+= (DF
<< SHIFT
);
898 void OPPROTO
glue(glue(op_out
, SUFFIX
), _T0_T1
)(void)
900 glue(cpu_x86_out
, SUFFIX
)(T0
& 0xffff, T1
& DATA_MASK
);
903 void OPPROTO
glue(glue(op_in
, SUFFIX
), _T0_T1
)(void)
905 T1
= glue(cpu_x86_in
, SUFFIX
)(T0
& 0xffff);