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
)
284 void OPPROTO
glue(op_loopnz
, SUFFIX
)(void)
288 eflags
= cc_table
[CC_OP
].compute_all();
289 tmp
= (ECX
- 1) & DATA_MASK
;
290 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
291 if (tmp
!= 0 && !(eflags
& CC_Z
))
298 void OPPROTO
glue(op_loopz
, SUFFIX
)(void)
302 eflags
= cc_table
[CC_OP
].compute_all();
303 tmp
= (ECX
- 1) & DATA_MASK
;
304 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
305 if (tmp
!= 0 && (eflags
& CC_Z
))
312 void OPPROTO
glue(op_loop
, SUFFIX
)(void)
315 tmp
= (ECX
- 1) & DATA_MASK
;
316 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
324 void OPPROTO
glue(op_jecxz
, SUFFIX
)(void)
326 if ((DATA_TYPE
)ECX
== 0)
335 /* various optimized set cases */
337 void OPPROTO
glue(op_setb_T0_sub
, SUFFIX
)(void)
341 src2
= CC_SRC
- CC_DST
;
343 T0
= ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
);
346 void OPPROTO
glue(op_setz_T0_sub
, SUFFIX
)(void)
348 T0
= ((DATA_TYPE
)CC_DST
== 0);
351 void OPPROTO
glue(op_setbe_T0_sub
, SUFFIX
)(void)
355 src2
= CC_SRC
- CC_DST
;
357 T0
= ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
);
360 void OPPROTO
glue(op_sets_T0_sub
, SUFFIX
)(void)
362 T0
= lshift(CC_DST
, -(DATA_BITS
- 1)) & 1;
365 void OPPROTO
glue(op_setl_T0_sub
, SUFFIX
)(void)
369 src2
= CC_SRC
- CC_DST
;
371 T0
= ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
);
374 void OPPROTO
glue(op_setle_T0_sub
, SUFFIX
)(void)
378 src2
= CC_SRC
- CC_DST
;
380 T0
= ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
);
385 void OPPROTO
glue(glue(op_rol
, SUFFIX
), _T0_T1_cc
)(void)
389 count
= T1
& SHIFT_MASK
;
391 CC_SRC
= cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
);
394 T0
= (T0
<< count
) | (T0
>> (DATA_BITS
- count
));
395 CC_SRC
|= (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
397 CC_OP
= CC_OP_EFLAGS
;
402 void OPPROTO
glue(glue(op_ror
, SUFFIX
), _T0_T1_cc
)(void)
405 count
= T1
& SHIFT_MASK
;
407 CC_SRC
= cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
);
410 T0
= (T0
>> count
) | (T0
<< (DATA_BITS
- count
));
411 CC_SRC
|= (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
412 ((T0
>> (DATA_BITS
- 1)) & CC_C
);
413 CC_OP
= CC_OP_EFLAGS
;
418 void OPPROTO
glue(glue(op_rcl
, SUFFIX
), _T0_T1_cc
)(void)
420 int count
, res
, eflags
;
425 count
= rclw_table
[count
];
427 count
= rclb_table
[count
];
430 eflags
= cc_table
[CC_OP
].compute_all();
433 res
= (T0
<< count
) | ((eflags
& CC_C
) << (count
- 1));
435 res
|= T0
>> (DATA_BITS
+ 1 - count
);
437 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
438 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
439 ((src
>> (DATA_BITS
- count
)) & CC_C
);
440 CC_OP
= CC_OP_EFLAGS
;
445 void OPPROTO
glue(glue(op_rcr
, SUFFIX
), _T0_T1_cc
)(void)
447 int count
, res
, eflags
;
452 count
= rclw_table
[count
];
454 count
= rclb_table
[count
];
457 eflags
= cc_table
[CC_OP
].compute_all();
460 res
= (T0
>> count
) | ((eflags
& CC_C
) << (DATA_BITS
- count
));
462 res
|= T0
<< (DATA_BITS
+ 1 - count
);
464 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
465 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
466 ((src
>> (count
- 1)) & CC_C
);
467 CC_OP
= CC_OP_EFLAGS
;
472 void OPPROTO
glue(glue(op_shl
, SUFFIX
), _T0_T1_cc
)(void)
477 CC_SRC
= (DATA_TYPE
)T0
<< (count
- 1);
480 CC_OP
= CC_OP_SHLB
+ SHIFT
;
485 void OPPROTO
glue(glue(op_shr
, SUFFIX
), _T0_T1_cc
)(void)
491 CC_SRC
= T0
>> (count
- 1);
494 CC_OP
= CC_OP_SARB
+ SHIFT
;
499 void OPPROTO
glue(glue(op_sar
, SUFFIX
), _T0_T1_cc
)(void)
504 src
= (DATA_STYPE
)T0
;
505 CC_SRC
= src
>> (count
- 1);
508 CC_OP
= CC_OP_SARB
+ SHIFT
;
514 /* XXX: overflow flag might be incorrect in some cases in shldw */
515 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_im_cc
)(void)
521 res
= T1
| (T0
<< 16);
522 CC_SRC
= res
>> (32 - count
);
525 res
|= T1
<< (count
- 16);
530 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_ECX_cc
)(void)
537 res
= T1
| (T0
<< 16);
538 CC_SRC
= res
>> (32 - count
);
541 res
|= T1
<< (count
- 16);
544 CC_OP
= CC_OP_SARB
+ SHIFT
;
548 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_im_cc
)(void)
554 res
= (T0
& 0xffff) | (T1
<< 16);
555 CC_SRC
= res
>> (count
- 1);
558 res
|= T1
<< (32 - count
);
564 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_ECX_cc
)(void)
571 res
= (T0
& 0xffff) | (T1
<< 16);
572 CC_SRC
= res
>> (count
- 1);
575 res
|= T1
<< (32 - count
);
578 CC_OP
= CC_OP_SARB
+ SHIFT
;
584 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_im_cc
)(void)
590 CC_SRC
= T0
<< (count
- 1);
591 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
595 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_ECX_cc
)(void)
602 CC_SRC
= T0
<< (count
- 1);
603 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
605 CC_OP
= CC_OP_SHLB
+ SHIFT
;
609 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_im_cc
)(void)
615 CC_SRC
= T0
>> (count
- 1);
616 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
621 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_ECX_cc
)(void)
628 CC_SRC
= T0
>> (count
- 1);
629 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
631 CC_OP
= CC_OP_SARB
+ SHIFT
;
636 /* carry add/sub (we only need to set CC_OP differently) */
638 void OPPROTO
glue(glue(op_adc
, SUFFIX
), _T0_T1_cc
)(void)
641 cf
= cc_table
[CC_OP
].compute_c();
645 CC_OP
= CC_OP_ADDB
+ SHIFT
+ cf
* 3;
648 void OPPROTO
glue(glue(op_sbb
, SUFFIX
), _T0_T1_cc
)(void)
651 cf
= cc_table
[CC_OP
].compute_c();
655 CC_OP
= CC_OP_SUBB
+ SHIFT
+ cf
* 3;
658 void OPPROTO
glue(glue(op_cmpxchg
, SUFFIX
), _T0_T1_EAX_cc
)(void)
662 if ((DATA_TYPE
)CC_DST
== 0) {
665 EAX
= (EAX
& ~DATA_MASK
) | (T0
& DATA_MASK
);
673 void OPPROTO
glue(glue(op_bt
, SUFFIX
), _T0_T1_cc
)(void)
676 count
= T1
& SHIFT_MASK
;
677 CC_SRC
= T0
>> count
;
680 void OPPROTO
glue(glue(op_bts
, SUFFIX
), _T0_T1_cc
)(void)
683 count
= T1
& SHIFT_MASK
;
684 CC_SRC
= T0
>> count
;
688 void OPPROTO
glue(glue(op_btr
, SUFFIX
), _T0_T1_cc
)(void)
691 count
= T1
& SHIFT_MASK
;
692 CC_SRC
= T0
>> count
;
696 void OPPROTO
glue(glue(op_btc
, SUFFIX
), _T0_T1_cc
)(void)
699 count
= T1
& SHIFT_MASK
;
700 CC_SRC
= T0
>> count
;
704 void OPPROTO
glue(glue(op_bsf
, SUFFIX
), _T0_cc
)(void)
707 res
= T0
& DATA_MASK
;
710 while ((res
& 1) == 0) {
715 CC_DST
= 1; /* ZF = 1 */
717 CC_DST
= 0; /* ZF = 1 */
722 void OPPROTO
glue(glue(op_bsr
, SUFFIX
), _T0_cc
)(void)
725 res
= T0
& DATA_MASK
;
727 count
= DATA_BITS
- 1;
728 while ((res
& SIGN_MASK
) == 0) {
733 CC_DST
= 1; /* ZF = 1 */
735 CC_DST
= 0; /* ZF = 1 */
742 /* string operations */
743 /* XXX: maybe use lower level instructions to ease exception handling */
745 void OPPROTO
glue(op_movs
, SUFFIX
)(void)
748 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
749 glue(st
, SUFFIX
)((void *)EDI
, v
);
750 ESI
+= (DF
<< SHIFT
);
751 EDI
+= (DF
<< SHIFT
);
754 void OPPROTO
glue(op_rep_movs
, SUFFIX
)(void)
759 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
760 glue(st
, SUFFIX
)((void *)EDI
, v
);
767 void OPPROTO
glue(op_stos
, SUFFIX
)(void)
769 glue(st
, SUFFIX
)((void *)EDI
, EAX
);
770 EDI
+= (DF
<< SHIFT
);
773 void OPPROTO
glue(op_rep_stos
, SUFFIX
)(void)
778 glue(st
, SUFFIX
)((void *)EDI
, EAX
);
784 void OPPROTO
glue(op_lods
, SUFFIX
)(void)
787 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
789 EAX
= (EAX
& ~0xff) | v
;
791 EAX
= (EAX
& ~0xffff) | v
;
795 ESI
+= (DF
<< SHIFT
);
798 /* don't know if it is used */
799 void OPPROTO
glue(op_rep_lods
, SUFFIX
)(void)
804 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
806 EAX
= (EAX
& ~0xff) | v
;
808 EAX
= (EAX
& ~0xffff) | v
;
817 void OPPROTO
glue(op_scas
, SUFFIX
)(void)
821 v
= glue(ldu
, SUFFIX
)((void *)EDI
);
822 EDI
+= (DF
<< SHIFT
);
827 void OPPROTO
glue(op_repz_scas
, SUFFIX
)(void)
832 /* NOTE: the flags are not modified if ECX == 0 */
833 v1
= EAX
& DATA_MASK
;
836 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
844 CC_OP
= CC_OP_SUBB
+ SHIFT
;
848 void OPPROTO
glue(op_repnz_scas
, SUFFIX
)(void)
853 /* NOTE: the flags are not modified if ECX == 0 */
854 v1
= EAX
& DATA_MASK
;
857 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
865 CC_OP
= CC_OP_SUBB
+ SHIFT
;
869 void OPPROTO
glue(op_cmps
, SUFFIX
)(void)
872 v1
= glue(ldu
, SUFFIX
)((void *)ESI
);
873 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
874 ESI
+= (DF
<< SHIFT
);
875 EDI
+= (DF
<< SHIFT
);
880 void OPPROTO
glue(op_repz_cmps
, SUFFIX
)(void)
886 v1
= glue(ldu
, SUFFIX
)((void *)ESI
);
887 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
896 CC_OP
= CC_OP_SUBB
+ SHIFT
;
900 void OPPROTO
glue(op_repnz_cmps
, SUFFIX
)(void)
906 v1
= glue(ldu
, SUFFIX
)((void *)ESI
);
907 v2
= glue(ldu
, SUFFIX
)((void *)EDI
);
916 CC_OP
= CC_OP_SUBB
+ SHIFT
;
922 void OPPROTO
glue(op_outs
, SUFFIX
)(void)
926 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
927 glue(cpu_x86_out
, SUFFIX
)(dx
, v
);
928 ESI
+= (DF
<< SHIFT
);
931 void OPPROTO
glue(op_rep_outs
, SUFFIX
)(void)
937 v
= glue(ldu
, SUFFIX
)((void *)ESI
);
938 glue(cpu_x86_out
, SUFFIX
)(dx
, v
);
944 void OPPROTO
glue(op_ins
, SUFFIX
)(void)
948 v
= glue(cpu_x86_in
, SUFFIX
)(dx
);
949 glue(st
, SUFFIX
)((void *)EDI
, v
);
950 EDI
+= (DF
<< SHIFT
);
953 void OPPROTO
glue(op_rep_ins
, SUFFIX
)(void)
959 v
= glue(cpu_x86_in
, SUFFIX
)(dx
);
960 glue(st
, SUFFIX
)((void *)EDI
, v
);
961 EDI
+= (DF
<< SHIFT
);
966 void OPPROTO
glue(glue(op_out
, SUFFIX
), _T0_T1
)(void)
968 glue(cpu_x86_out
, SUFFIX
)(T0
& 0xffff, T1
& DATA_MASK
);
971 void OPPROTO
glue(glue(op_in
, SUFFIX
), _T0_T1
)(void)
973 T1
= glue(cpu_x86_in
, SUFFIX
)(T0
& 0xffff);