added cmov instruction
[qemu] / ops_template.h
1
2 #define DATA_BITS (1 << (3 + SHIFT))
3 #define SHIFT_MASK (DATA_BITS - 1)
4 #define SIGN_MASK (1 << (DATA_BITS - 1))
5
6 #if DATA_BITS == 8
7 #define SUFFIX b
8 #define DATA_TYPE uint8_t
9 #define DATA_STYPE int8_t
10 #define DATA_MASK 0xff
11 #elif DATA_BITS == 16
12 #define SUFFIX w
13 #define DATA_TYPE uint16_t
14 #define DATA_STYPE int16_t
15 #define DATA_MASK 0xffff
16 #elif DATA_BITS == 32
17 #define SUFFIX l
18 #define DATA_TYPE uint32_t
19 #define DATA_STYPE int32_t
20 #define DATA_MASK 0xffffffff
21 #else
22 #error unhandled operand size
23 #endif
24
25 /* dynamic flags computation */
26
27 static int glue(compute_all_add, SUFFIX)(void)
28 {
29     int cf, pf, af, zf, sf, of;
30     int src1, src2;
31     src1 = CC_SRC;
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;
40 }
41
42 static int glue(compute_c_add, SUFFIX)(void)
43 {
44     int src1, cf;
45     src1 = CC_SRC;
46     cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
47     return cf;
48 }
49
50 static int glue(compute_all_adc, SUFFIX)(void)
51 {
52     int cf, pf, af, zf, sf, of;
53     int src1, src2;
54     src1 = CC_SRC;
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;
63 }
64
65 static int glue(compute_c_adc, SUFFIX)(void)
66 {
67     int src1, cf;
68     src1 = CC_SRC;
69     cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
70     return cf;
71 }
72
73 static int glue(compute_all_sub, SUFFIX)(void)
74 {
75     int cf, pf, af, zf, sf, of;
76     int src1, src2;
77     src1 = CC_SRC;
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;
86 }
87
88 static int glue(compute_c_sub, SUFFIX)(void)
89 {
90     int src1, src2, cf;
91     src1 = CC_SRC;
92     src2 = CC_SRC - CC_DST;
93     cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
94     return cf;
95 }
96
97 static int glue(compute_all_sbb, SUFFIX)(void)
98 {
99     int cf, pf, af, zf, sf, of;
100     int src1, src2;
101     src1 = CC_SRC;
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;
110 }
111
112 static int glue(compute_c_sbb, SUFFIX)(void)
113 {
114     int src1, src2, cf;
115     src1 = CC_SRC;
116     src2 = CC_SRC - CC_DST - 1;
117     cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
118     return cf;
119 }
120
121 static int glue(compute_all_logic, SUFFIX)(void)
122 {
123     int cf, pf, af, zf, sf, of;
124     cf = 0;
125     pf = parity_table[(uint8_t)CC_DST];
126     af = 0;
127     zf = ((DATA_TYPE)CC_DST == 0) << 6;
128     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
129     of = 0;
130     return cf | pf | af | zf | sf | of;
131 }
132
133 static int glue(compute_c_logic, SUFFIX)(void)
134 {
135     return 0;
136 }
137
138 static int glue(compute_all_inc, SUFFIX)(void)
139 {
140     int cf, pf, af, zf, sf, of;
141     int src1, src2;
142     src1 = CC_DST - 1;
143     src2 = 1;
144     cf = CC_SRC;
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;
151 }
152
153 #if DATA_BITS == 32
154 static int glue(compute_c_inc, SUFFIX)(void)
155 {
156     return CC_SRC;
157 }
158 #endif
159
160 static int glue(compute_all_dec, SUFFIX)(void)
161 {
162     int cf, pf, af, zf, sf, of;
163     int src1, src2;
164     src1 = CC_DST + 1;
165     src2 = 1;
166     cf = CC_SRC;
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;
173 }
174
175 static int glue(compute_all_shl, SUFFIX)(void)
176 {
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;
186 }
187
188 #if DATA_BITS == 32
189 static int glue(compute_c_shl, SUFFIX)(void)
190 {
191     return CC_SRC & 1;
192 }
193 #endif
194
195 static int glue(compute_all_sar, SUFFIX)(void)
196 {
197     int cf, pf, af, zf, sf, of;
198     cf = CC_SRC & 1;
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;
206 }
207
208 /* various optimized jumps cases */
209
210 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
211 {
212     int src1, src2;
213     src1 = CC_SRC;
214     src2 = CC_SRC - CC_DST;
215
216     if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
217         PC = PARAM1;
218     else
219         PC = PARAM2;
220     FORCE_RET();
221 }
222
223 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
224 {
225     if ((DATA_TYPE)CC_DST == 0)
226         PC = PARAM1;
227     else
228         PC = PARAM2;
229     FORCE_RET();
230 }
231
232 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
233 {
234     int src1, src2;
235     src1 = CC_SRC;
236     src2 = CC_SRC - CC_DST;
237
238     if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
239         PC = PARAM1;
240     else
241         PC = PARAM2;
242     FORCE_RET();
243 }
244
245 void OPPROTO glue(op_js_sub, SUFFIX)(void)
246 {
247     if (CC_DST & SIGN_MASK)
248         PC = PARAM1;
249     else
250         PC = PARAM2;
251     FORCE_RET();
252 }
253
254 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
255 {
256     int src1, src2;
257     src1 = CC_SRC;
258     src2 = CC_SRC - CC_DST;
259
260     if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
261         PC = PARAM1;
262     else
263         PC = PARAM2;
264     FORCE_RET();
265 }
266
267 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
268 {
269     int src1, src2;
270     src1 = CC_SRC;
271     src2 = CC_SRC - CC_DST;
272
273     if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
274         PC = PARAM1;
275     else
276         PC = PARAM2;
277     FORCE_RET();
278 }
279
280 /* oldies */
281
282 #if DATA_BITS >= 16
283
284 void OPPROTO glue(op_loopnz, SUFFIX)(void)
285 {
286     unsigned int tmp;
287     int eflags;
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))
292         PC = PARAM1;
293     else
294         PC = PARAM2;
295     FORCE_RET();
296 }
297
298 void OPPROTO glue(op_loopz, SUFFIX)(void)
299 {
300     unsigned int tmp;
301     int eflags;
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))
306         PC = PARAM1;
307     else
308         PC = PARAM2;
309     FORCE_RET();
310 }
311
312 void OPPROTO glue(op_loop, SUFFIX)(void)
313 {
314     unsigned int tmp;
315     tmp = (ECX - 1) & DATA_MASK;
316     ECX = (ECX & ~DATA_MASK) | tmp;
317     if (tmp != 0)
318         PC = PARAM1;
319     else
320         PC = PARAM2;
321     FORCE_RET();
322 }
323
324 void OPPROTO glue(op_jecxz, SUFFIX)(void)
325 {
326     if ((DATA_TYPE)ECX == 0)
327         PC = PARAM1;
328     else
329         PC = PARAM2;
330     FORCE_RET();
331 }
332
333 #endif
334
335 /* various optimized set cases */
336
337 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
338 {
339     int src1, src2;
340     src1 = CC_SRC;
341     src2 = CC_SRC - CC_DST;
342
343     T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
344 }
345
346 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
347 {
348     T0 = ((DATA_TYPE)CC_DST == 0);
349 }
350
351 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
352 {
353     int src1, src2;
354     src1 = CC_SRC;
355     src2 = CC_SRC - CC_DST;
356
357     T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
358 }
359
360 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
361 {
362     T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
363 }
364
365 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
366 {
367     int src1, src2;
368     src1 = CC_SRC;
369     src2 = CC_SRC - CC_DST;
370
371     T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
372 }
373
374 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
375 {
376     int src1, src2;
377     src1 = CC_SRC;
378     src2 = CC_SRC - CC_DST;
379
380     T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
381 }
382
383 /* shifts */
384
385 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
386 {
387     int count, src;
388     /* XXX: testing */
389     count = T1 & SHIFT_MASK;
390     if (count) {
391         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
392         src = T0;
393         T0 &= DATA_MASK;
394         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
395         CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
396             (T0 & CC_C);
397         CC_OP = CC_OP_EFLAGS;
398     }
399     FORCE_RET();
400 }
401
402 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
403 {
404     int count, src;
405     count = T1 & SHIFT_MASK;
406     if (count) {
407         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
408         src = T0;
409         T0 &= DATA_MASK;
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;
414     }
415     FORCE_RET();
416 }
417
418 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
419 {
420     int count, res, eflags;
421     unsigned int src;
422
423     count = T1 & 0x1f;
424 #if DATA_BITS == 16
425     count = rclw_table[count];
426 #elif DATA_BITS == 8
427     count = rclb_table[count];
428 #endif
429     if (count) {
430         eflags = cc_table[CC_OP].compute_all();
431         T0 &= DATA_MASK;
432         src = T0;
433         res = (T0 << count) | ((eflags & CC_C) << (count - 1));
434         if (count > 1)
435             res |= T0 >> (DATA_BITS + 1 - count);
436         T0 = res;
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;
441     }
442     FORCE_RET();
443 }
444
445 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
446 {
447     int count, res, eflags;
448     unsigned int src;
449
450     count = T1 & 0x1f;
451 #if DATA_BITS == 16
452     count = rclw_table[count];
453 #elif DATA_BITS == 8
454     count = rclb_table[count];
455 #endif
456     if (count) {
457         eflags = cc_table[CC_OP].compute_all();
458         T0 &= DATA_MASK;
459         src = T0;
460         res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
461         if (count > 1)
462             res |= T0 << (DATA_BITS + 1 - count);
463         T0 = res;
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;
468     }
469     FORCE_RET();
470 }
471
472 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
473 {
474     int count;
475     count = T1 & 0x1f;
476     if (count) {
477         CC_SRC = (DATA_TYPE)T0 << (count - 1);
478         T0 = T0 << count;
479         CC_DST = T0;
480         CC_OP = CC_OP_SHLB + SHIFT;
481     }
482     FORCE_RET();
483 }
484
485 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
486 {
487     int count;
488     count = T1 & 0x1f;
489     if (count) {
490         T0 &= DATA_MASK;
491         CC_SRC = T0 >> (count - 1);
492         T0 = T0 >> count;
493         CC_DST = T0;
494         CC_OP = CC_OP_SARB + SHIFT;
495     }
496     FORCE_RET();
497 }
498
499 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
500 {
501     int count, src;
502     count = T1 & 0x1f;
503     if (count) {
504         src = (DATA_STYPE)T0;
505         CC_SRC = src >> (count - 1);
506         T0 = src >> count;
507         CC_DST = T0;
508         CC_OP = CC_OP_SARB + SHIFT;
509     }
510     FORCE_RET();
511 }
512
513 #if DATA_BITS == 16
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)
516 {
517     int count;
518     unsigned int res;
519     count = PARAM1;
520     T1 &= 0xffff;
521     res = T1 | (T0 << 16);
522     CC_SRC = res >> (32 - count);
523     res <<= count;
524     if (count > 16)
525         res |= T1 << (count - 16);
526     T0 = res >> 16;
527     CC_DST = T0;
528 }
529
530 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
531 {
532     int count;
533     unsigned int res;
534     count = ECX & 0x1f;
535     if (count) {
536         T1 &= 0xffff;
537         res = T1 | (T0 << 16);
538         CC_SRC = res >> (32 - count);
539         res <<= count;
540         if (count > 16)
541           res |= T1 << (count - 16);
542         T0 = res >> 16;
543         CC_DST = T0;
544         CC_OP = CC_OP_SARB + SHIFT;
545     }
546 }
547
548 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
549 {
550     int count;
551     unsigned int res;
552
553     count = PARAM1;
554     res = (T0 & 0xffff) | (T1 << 16);
555     CC_SRC = res >> (count - 1);
556     res >>= count;
557     if (count > 16)
558         res |= T1 << (32 - count);
559     T0 = res;
560     CC_DST = T0;
561 }
562
563
564 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
565 {
566     int count;
567     unsigned int res;
568
569     count = ECX & 0x1f;
570     if (count) {
571         res = (T0 & 0xffff) | (T1 << 16);
572         CC_SRC = res >> (count - 1);
573         res >>= count;
574         if (count > 16)
575             res |= T1 << (32 - count);
576         T0 = res;
577         CC_DST = T0;
578         CC_OP = CC_OP_SARB + SHIFT;
579     }
580 }
581 #endif
582
583 #if DATA_BITS == 32
584 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
585 {
586     int count;
587     count = PARAM1;
588     T0 &= DATA_MASK;
589     T1 &= DATA_MASK;
590     CC_SRC = T0 << (count - 1);
591     T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
592     CC_DST = T0;
593 }
594
595 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
596 {
597     int count;
598     count = ECX & 0x1f;
599     if (count) {
600         T0 &= DATA_MASK;
601         T1 &= DATA_MASK;
602         CC_SRC = T0 << (count - 1);
603         T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
604         CC_DST = T0;
605         CC_OP = CC_OP_SHLB + SHIFT;
606     }
607 }
608
609 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
610 {
611     int count;
612     count = PARAM1;
613     T0 &= DATA_MASK;
614     T1 &= DATA_MASK;
615     CC_SRC = T0 >> (count - 1);
616     T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
617     CC_DST = T0;
618 }
619
620
621 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
622 {
623     int count;
624     count = ECX & 0x1f;
625     if (count) {
626         T0 &= DATA_MASK;
627         T1 &= DATA_MASK;
628         CC_SRC = T0 >> (count - 1);
629         T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
630         CC_DST = T0;
631         CC_OP = CC_OP_SARB + SHIFT;
632     }
633 }
634 #endif
635
636 /* carry add/sub (we only need to set CC_OP differently) */
637
638 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
639 {
640     int cf;
641     cf = cc_table[CC_OP].compute_c();
642     CC_SRC = T0;
643     T0 = T0 + T1 + cf;
644     CC_DST = T0;
645     CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
646 }
647
648 void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
649 {
650     int cf;
651     cf = cc_table[CC_OP].compute_c();
652     CC_SRC = T0;
653     T0 = T0 - T1 - cf;
654     CC_DST = T0;
655     CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
656 }
657
658 void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
659 {
660     CC_SRC = EAX;
661     CC_DST = EAX - T0;
662     if ((DATA_TYPE)CC_DST == 0) {
663         T0 = T1;
664     } else {
665         EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
666     }
667     FORCE_RET();
668 }
669
670 /* bit operations */
671 #if DATA_BITS >= 16
672
673 void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
674 {
675     int count;
676     count = T1 & SHIFT_MASK;
677     CC_SRC = T0 >> count;
678 }
679
680 void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
681 {
682     int count;
683     count = T1 & SHIFT_MASK;
684     CC_SRC = T0 >> count;
685     T0 |= (1 << count);
686 }
687
688 void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
689 {
690     int count;
691     count = T1 & SHIFT_MASK;
692     CC_SRC = T0 >> count;
693     T0 &= ~(1 << count);
694 }
695
696 void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
697 {
698     int count;
699     count = T1 & SHIFT_MASK;
700     CC_SRC = T0 >> count;
701     T0 ^= (1 << count);
702 }
703
704 void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
705 {
706     int res, count;
707     res = T0 & DATA_MASK;
708     if (res != 0) {
709         count = 0;
710         while ((res & 1) == 0) {
711             count++;
712             res >>= 1;
713         }
714         T0 = count;
715         CC_DST = 1; /* ZF = 1 */
716     } else {
717         CC_DST = 0; /* ZF = 1 */
718     }
719     FORCE_RET();
720 }
721
722 void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
723 {
724     int res, count;
725     res = T0 & DATA_MASK;
726     if (res != 0) {
727         count = DATA_BITS - 1;
728         while ((res & SIGN_MASK) == 0) {
729             count--;
730             res <<= 1;
731         }
732         T0 = count;
733         CC_DST = 1; /* ZF = 1 */
734     } else {
735         CC_DST = 0; /* ZF = 1 */
736     }
737     FORCE_RET();
738 }
739
740 #endif
741
742 /* string operations */
743 /* XXX: maybe use lower level instructions to ease exception handling */
744
745 void OPPROTO glue(op_movs, SUFFIX)(void)
746 {
747     int v;
748     v = glue(ldu, SUFFIX)((void *)ESI);
749     glue(st, SUFFIX)((void *)EDI, v);
750     ESI += (DF << SHIFT);
751     EDI += (DF << SHIFT);
752 }
753
754 void OPPROTO glue(op_rep_movs, SUFFIX)(void)
755 {
756     int v, inc;
757     inc = (DF << SHIFT);
758     while (ECX != 0) {
759         v = glue(ldu, SUFFIX)((void *)ESI);
760         glue(st, SUFFIX)((void *)EDI, v);
761         ESI += inc;
762         EDI += inc;
763         ECX--;
764     }
765 }
766
767 void OPPROTO glue(op_stos, SUFFIX)(void)
768 {
769     glue(st, SUFFIX)((void *)EDI, EAX);
770     EDI += (DF << SHIFT);
771 }
772
773 void OPPROTO glue(op_rep_stos, SUFFIX)(void)
774 {
775     int inc;
776     inc = (DF << SHIFT);
777     while (ECX != 0) {
778         glue(st, SUFFIX)((void *)EDI, EAX);
779         EDI += inc;
780         ECX--;
781     }
782 }
783
784 void OPPROTO glue(op_lods, SUFFIX)(void)
785 {
786     int v;
787     v = glue(ldu, SUFFIX)((void *)ESI);
788 #if SHIFT == 0
789     EAX = (EAX & ~0xff) | v;
790 #elif SHIFT == 1
791     EAX = (EAX & ~0xffff) | v;
792 #else
793     EAX = v;
794 #endif
795     ESI += (DF << SHIFT);
796 }
797
798 /* don't know if it is used */
799 void OPPROTO glue(op_rep_lods, SUFFIX)(void)
800 {
801     int v, inc;
802     inc = (DF << SHIFT);
803     while (ECX != 0) {
804         v = glue(ldu, SUFFIX)((void *)ESI);
805 #if SHIFT == 0
806         EAX = (EAX & ~0xff) | v;
807 #elif SHIFT == 1
808         EAX = (EAX & ~0xffff) | v;
809 #else
810         EAX = v;
811 #endif
812         ESI += inc;
813         ECX--;
814     }
815 }
816
817 void OPPROTO glue(op_scas, SUFFIX)(void)
818 {
819     int v;
820
821     v = glue(ldu, SUFFIX)((void *)EDI);
822     EDI += (DF << SHIFT);
823     CC_SRC = EAX;
824     CC_DST = EAX - v;
825 }
826
827 void OPPROTO glue(op_repz_scas, SUFFIX)(void)
828 {
829     int v1, v2, inc;
830
831     if (ECX != 0) {
832         /* NOTE: the flags are not modified if ECX == 0 */
833         v1 = EAX & DATA_MASK;
834         inc = (DF << SHIFT);
835         do {
836             v2 = glue(ldu, SUFFIX)((void *)EDI);
837             EDI += inc;
838             ECX--;
839             if (v1 != v2)
840                 break;
841         } while (ECX != 0);
842         CC_SRC = v1;
843         CC_DST = v1 - v2;
844         CC_OP = CC_OP_SUBB + SHIFT;
845     }
846 }
847
848 void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
849 {
850     int v1, v2, inc;
851
852     if (ECX != 0) {
853         /* NOTE: the flags are not modified if ECX == 0 */
854         v1 = EAX & DATA_MASK;
855         inc = (DF << SHIFT);
856         do {
857             v2 = glue(ldu, SUFFIX)((void *)EDI);
858             EDI += inc;
859             ECX--;
860             if (v1 == v2)
861                 break;
862         } while (ECX != 0);
863         CC_SRC = v1;
864         CC_DST = v1 - v2;
865         CC_OP = CC_OP_SUBB + SHIFT;
866     }
867 }
868
869 void OPPROTO glue(op_cmps, SUFFIX)(void)
870 {
871     int v1, v2;
872     v1 = glue(ldu, SUFFIX)((void *)ESI);
873     v2 = glue(ldu, SUFFIX)((void *)EDI);
874     ESI += (DF << SHIFT);
875     EDI += (DF << SHIFT);
876     CC_SRC = v1;
877     CC_DST = v1 - v2;
878 }
879
880 void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
881 {
882     int v1, v2, inc;
883     if (ECX != 0) {
884         inc = (DF << SHIFT);
885         do {
886             v1 = glue(ldu, SUFFIX)((void *)ESI);
887             v2 = glue(ldu, SUFFIX)((void *)EDI);
888             ESI += inc;
889             EDI += inc;
890             ECX--;
891             if (v1 != v2)
892                 break;
893         } while (ECX != 0);
894         CC_SRC = v1;
895         CC_DST = v1 - v2;
896         CC_OP = CC_OP_SUBB + SHIFT;
897     }
898 }
899
900 void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
901 {
902     int v1, v2, inc;
903     if (ECX != 0) {
904         inc = (DF << SHIFT);
905         do {
906             v1 = glue(ldu, SUFFIX)((void *)ESI);
907             v2 = glue(ldu, SUFFIX)((void *)EDI);
908             ESI += inc;
909             EDI += inc;
910             ECX--;
911             if (v1 == v2)
912                 break;
913         } while (ECX != 0);
914         CC_SRC = v1;
915         CC_DST = v1 - v2;
916         CC_OP = CC_OP_SUBB + SHIFT;
917     }
918 }
919
920 /* port I/O */
921
922 void OPPROTO glue(op_outs, SUFFIX)(void)
923 {
924     int v, dx;
925     dx = EDX & 0xffff;
926     v = glue(ldu, SUFFIX)((void *)ESI);
927     glue(cpu_x86_out, SUFFIX)(dx, v);
928     ESI += (DF << SHIFT);
929 }
930
931 void OPPROTO glue(op_rep_outs, SUFFIX)(void)
932 {
933     int v, dx, inc;
934     inc = (DF << SHIFT);
935     dx = EDX & 0xffff;
936     while (ECX != 0) {
937         v = glue(ldu, SUFFIX)((void *)ESI);
938         glue(cpu_x86_out, SUFFIX)(dx, v);
939         ESI += inc;
940         ECX--;
941     }
942 }
943
944 void OPPROTO glue(op_ins, SUFFIX)(void)
945 {
946     int v, dx;
947     dx = EDX & 0xffff;
948     v = glue(cpu_x86_in, SUFFIX)(dx);
949     glue(st, SUFFIX)((void *)EDI, v);
950     EDI += (DF << SHIFT);
951 }
952
953 void OPPROTO glue(op_rep_ins, SUFFIX)(void)
954 {
955     int v, dx, inc;
956     inc = (DF << SHIFT);
957     dx = EDX & 0xffff;
958     while (ECX != 0) {
959         v = glue(cpu_x86_in, SUFFIX)(dx);
960         glue(st, SUFFIX)((void *)EDI, v);
961         EDI += (DF << SHIFT);
962         ECX--;
963     }
964 }
965
966 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
967 {
968     glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
969 }
970
971 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
972 {
973     T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
974 }
975
976 #undef DATA_BITS
977 #undef SHIFT_MASK
978 #undef SIGN_MASK
979 #undef DATA_TYPE
980 #undef DATA_STYPE
981 #undef DATA_MASK
982 #undef SUFFIX