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;
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 = lshift(CC_SRC, 12 - DATA_BITS) & CC_O; /* only meaniful for shr with count == 1 */
184 return cf | pf | af | zf | sf | of;
188 static int glue(compute_c_shl, SUFFIX)(void)
194 static int glue(compute_all_sar, SUFFIX)(void)
196 int cf, pf, af, zf, sf, of;
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 = 0; /* only meaniful for shr with count == 1 */
203 return cf | pf | af | zf | sf | of;
206 /* various optimized jumps cases */
208 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
212 src2 = CC_SRC - CC_DST;
214 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
221 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
223 if ((DATA_TYPE)CC_DST == 0)
230 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
234 src2 = CC_SRC - CC_DST;
236 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
243 void OPPROTO glue(op_js_sub, SUFFIX)(void)
245 if (CC_DST & SIGN_MASK)
252 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
256 src2 = CC_SRC - CC_DST;
258 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
265 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
269 src2 = CC_SRC - CC_DST;
271 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
278 /* various optimized set cases */
280 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
284 src2 = CC_SRC - CC_DST;
286 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
289 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
291 T0 = ((DATA_TYPE)CC_DST == 0);
294 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
298 src2 = CC_SRC - CC_DST;
300 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
303 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
305 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
308 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
312 src2 = CC_SRC - CC_DST;
314 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
317 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
321 src2 = CC_SRC - CC_DST;
323 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
328 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
331 count = T1 & SHIFT_MASK;
333 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
336 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
337 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
339 CC_OP = CC_OP_EFLAGS;
344 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
347 count = T1 & SHIFT_MASK;
349 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
352 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
353 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
354 ((T0 >> (DATA_BITS - 1)) & CC_C);
355 CC_OP = CC_OP_EFLAGS;
360 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
362 int count, res, eflags;
367 count = rclw_table[count];
369 count = rclb_table[count];
372 eflags = cc_table[CC_OP].compute_all();
375 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
377 res |= T0 >> (DATA_BITS + 1 - count);
379 CC_SRC = (eflags & ~(CC_C | CC_O)) |
380 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
381 ((src >> (DATA_BITS - count)) & CC_C);
382 CC_OP = CC_OP_EFLAGS;
387 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
389 int count, res, eflags;
394 count = rclw_table[count];
396 count = rclb_table[count];
399 eflags = cc_table[CC_OP].compute_all();
402 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
404 res |= T0 << (DATA_BITS + 1 - count);
406 CC_SRC = (eflags & ~(CC_C | CC_O)) |
407 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
408 ((src >> (count - 1)) & CC_C);
409 CC_OP = CC_OP_EFLAGS;
414 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
422 CC_OP = CC_OP_ADDB + SHIFT;
424 CC_SRC = (DATA_TYPE)T0 >> (DATA_BITS - count);
427 CC_OP = CC_OP_SHLB + SHIFT;
432 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
438 CC_SRC = T0 >> (count - 1);
441 CC_OP = CC_OP_SHLB + SHIFT;
446 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
451 src = (DATA_STYPE)T0;
452 CC_SRC = src >> (count - 1);
455 CC_OP = CC_OP_SARB + SHIFT;
460 /* carry add/sub (we only need to set CC_OP differently) */
462 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
465 cf = cc_table[CC_OP].compute_c();
469 CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
472 void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
475 cf = cc_table[CC_OP].compute_c();
479 CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
485 void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
488 count = T1 & SHIFT_MASK;
489 CC_SRC = T0 >> count;
492 void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
495 count = T1 & SHIFT_MASK;
496 CC_SRC = T0 >> count;
500 void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
503 count = T1 & SHIFT_MASK;
504 CC_SRC = T0 >> count;
508 void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
511 count = T1 & SHIFT_MASK;
512 CC_SRC = T0 >> count;
518 /* string operations */
519 /* XXX: maybe use lower level instructions to ease exception handling */
521 void OPPROTO glue(op_movs, SUFFIX)(void)
524 v = glue(ldu, SUFFIX)((void *)ESI);
525 glue(st, SUFFIX)((void *)EDI, v);
526 ESI += (DF << SHIFT);
527 EDI += (DF << SHIFT);
530 void OPPROTO glue(op_rep_movs, SUFFIX)(void)
535 v = glue(ldu, SUFFIX)((void *)ESI);
536 glue(st, SUFFIX)((void *)EDI, v);
543 void OPPROTO glue(op_stos, SUFFIX)(void)
545 glue(st, SUFFIX)((void *)EDI, EAX);
546 EDI += (DF << SHIFT);
549 void OPPROTO glue(op_rep_stos, SUFFIX)(void)
554 glue(st, SUFFIX)((void *)EDI, EAX);
560 void OPPROTO glue(op_lods, SUFFIX)(void)
563 v = glue(ldu, SUFFIX)((void *)ESI);
565 EAX = (EAX & ~0xff) | v;
567 EAX = (EAX & ~0xffff) | v;
571 ESI += (DF << SHIFT);
574 /* don't know if it is used */
575 void OPPROTO glue(op_rep_lods, SUFFIX)(void)
580 v = glue(ldu, SUFFIX)((void *)ESI);
582 EAX = (EAX & ~0xff) | v;
584 EAX = (EAX & ~0xffff) | v;
593 void OPPROTO glue(op_scas, SUFFIX)(void)
597 v = glue(ldu, SUFFIX)((void *)EDI);
598 EDI += (DF << SHIFT);
603 void OPPROTO glue(op_repz_scas, SUFFIX)(void)
608 /* NOTE: the flags are not modified if ECX == 0 */
609 v1 = EAX & DATA_MASK;
612 v2 = glue(ldu, SUFFIX)((void *)EDI);
620 CC_OP = CC_OP_SUBB + SHIFT;
624 void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
629 /* NOTE: the flags are not modified if ECX == 0 */
630 v1 = EAX & DATA_MASK;
633 v2 = glue(ldu, SUFFIX)((void *)EDI);
641 CC_OP = CC_OP_SUBB + SHIFT;
645 void OPPROTO glue(op_cmps, SUFFIX)(void)
648 v1 = glue(ldu, SUFFIX)((void *)ESI);
649 v2 = glue(ldu, SUFFIX)((void *)EDI);
650 ESI += (DF << SHIFT);
651 EDI += (DF << SHIFT);
656 void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
662 v1 = glue(ldu, SUFFIX)((void *)ESI);
663 v2 = glue(ldu, SUFFIX)((void *)EDI);
672 CC_OP = CC_OP_SUBB + SHIFT;
676 void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
682 v1 = glue(ldu, SUFFIX)((void *)ESI);
683 v2 = glue(ldu, SUFFIX)((void *)EDI);
692 CC_OP = CC_OP_SUBB + SHIFT;
698 void OPPROTO glue(op_outs, SUFFIX)(void)
702 v = glue(ldu, SUFFIX)((void *)ESI);
703 glue(cpu_x86_out, SUFFIX)(dx, v);
704 ESI += (DF << SHIFT);
707 void OPPROTO glue(op_rep_outs, SUFFIX)(void)
713 v = glue(ldu, SUFFIX)((void *)ESI);
714 glue(cpu_x86_out, SUFFIX)(dx, v);
720 void OPPROTO glue(op_ins, SUFFIX)(void)
724 v = glue(cpu_x86_in, SUFFIX)(dx);
725 glue(st, SUFFIX)((void *)EDI, v);
726 EDI += (DF << SHIFT);
729 void OPPROTO glue(op_rep_ins, SUFFIX)(void)
735 v = glue(cpu_x86_in, SUFFIX)(dx);
736 glue(st, SUFFIX)((void *)EDI, v);
737 EDI += (DF << SHIFT);
742 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
744 glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
747 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
749 T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);