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);