745c27d7e5426aea4ca918596f86ba44a8ffef78
[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 /* various optimized set cases */
281
282 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
283 {
284     int src1, src2;
285     src1 = CC_SRC;
286     src2 = CC_SRC - CC_DST;
287
288     T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
289 }
290
291 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
292 {
293     T0 = ((DATA_TYPE)CC_DST == 0);
294 }
295
296 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
297 {
298     int src1, src2;
299     src1 = CC_SRC;
300     src2 = CC_SRC - CC_DST;
301
302     T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
303 }
304
305 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
306 {
307     T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
308 }
309
310 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
311 {
312     int src1, src2;
313     src1 = CC_SRC;
314     src2 = CC_SRC - CC_DST;
315
316     T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
317 }
318
319 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
320 {
321     int src1, src2;
322     src1 = CC_SRC;
323     src2 = CC_SRC - CC_DST;
324
325     T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
326 }
327
328 /* shifts */
329
330 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
331 {
332     int count, src;
333     count = T1 & SHIFT_MASK;
334     if (count) {
335         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
336         src = T0;
337         T0 &= DATA_MASK;
338         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
339         CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
340             (T0 & CC_C);
341         CC_OP = CC_OP_EFLAGS;
342     }
343     FORCE_RET();
344 }
345
346 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
347 {
348     int count, src;
349     count = T1 & SHIFT_MASK;
350     if (count) {
351         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
352         src = T0;
353         T0 &= DATA_MASK;
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;
358     }
359     FORCE_RET();
360 }
361
362 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
363 {
364     int count, res, eflags;
365     unsigned int src;
366
367     count = T1 & 0x1f;
368 #if DATA_BITS == 16
369     count = rclw_table[count];
370 #elif DATA_BITS == 8
371     count = rclb_table[count];
372 #endif
373     if (count) {
374         eflags = cc_table[CC_OP].compute_all();
375         T0 &= DATA_MASK;
376         src = T0;
377         res = (T0 << count) | ((eflags & CC_C) << (count - 1));
378         if (count > 1)
379             res |= T0 >> (DATA_BITS + 1 - count);
380         T0 = res;
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;
385     }
386     FORCE_RET();
387 }
388
389 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
390 {
391     int count, res, eflags;
392     unsigned int src;
393
394     count = T1 & 0x1f;
395 #if DATA_BITS == 16
396     count = rclw_table[count];
397 #elif DATA_BITS == 8
398     count = rclb_table[count];
399 #endif
400     if (count) {
401         eflags = cc_table[CC_OP].compute_all();
402         T0 &= DATA_MASK;
403         src = T0;
404         res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
405         if (count > 1)
406             res |= T0 << (DATA_BITS + 1 - count);
407         T0 = res;
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;
412     }
413     FORCE_RET();
414 }
415
416 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
417 {
418     int count;
419     count = T1 & 0x1f;
420     if (count) {
421         CC_SRC = (DATA_TYPE)T0 << (count - 1);
422         T0 = T0 << count;
423         CC_DST = T0;
424         CC_OP = CC_OP_SHLB + SHIFT;
425     }
426     FORCE_RET();
427 }
428
429 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
430 {
431     int count;
432     count = T1 & 0x1f;
433     if (count) {
434         T0 &= DATA_MASK;
435         CC_SRC = T0 >> (count - 1);
436         T0 = T0 >> count;
437         CC_DST = T0;
438         CC_OP = CC_OP_SARB + SHIFT;
439     }
440     FORCE_RET();
441 }
442
443 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
444 {
445     int count, src;
446     count = T1 & 0x1f;
447     if (count) {
448         src = (DATA_STYPE)T0;
449         CC_SRC = src >> (count - 1);
450         T0 = src >> count;
451         CC_DST = T0;
452         CC_OP = CC_OP_SARB + SHIFT;
453     }
454     FORCE_RET();
455 }
456
457 #if DATA_BITS == 16
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)
460 {
461     int count;
462     unsigned int res;
463     count = PARAM1;
464     T1 &= 0xffff;
465     res = T1 | (T0 << 16);
466     CC_SRC = res >> (32 - count);
467     res <<= count;
468     if (count > 16)
469         res |= T1 << (count - 16);
470     T0 = res >> 16;
471     CC_DST = T0;
472 }
473
474 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
475 {
476     int count;
477     unsigned int res;
478     count = ECX & 0x1f;
479     if (count) {
480         T1 &= 0xffff;
481         res = T1 | (T0 << 16);
482         CC_SRC = res >> (32 - count);
483         res <<= count;
484         if (count > 16)
485           res |= T1 << (count - 16);
486         T0 = res >> 16;
487         CC_DST = T0;
488         CC_OP = CC_OP_SARB + SHIFT;
489     }
490 }
491
492 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
493 {
494     int count;
495     unsigned int res;
496
497     count = PARAM1;
498     res = (T0 & 0xffff) | (T1 << 16);
499     CC_SRC = res >> (count - 1);
500     res >>= count;
501     if (count > 16)
502         res |= T1 << (32 - count);
503     T0 = res;
504     CC_DST = T0;
505 }
506
507
508 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
509 {
510     int count;
511     unsigned int res;
512
513     count = ECX & 0x1f;
514     if (count) {
515         res = (T0 & 0xffff) | (T1 << 16);
516         CC_SRC = res >> (count - 1);
517         res >>= count;
518         if (count > 16)
519             res |= T1 << (32 - count);
520         T0 = res;
521         CC_DST = T0;
522         CC_OP = CC_OP_SARB + SHIFT;
523     }
524 }
525 #endif
526
527 #if DATA_BITS == 32
528 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
529 {
530     int count;
531     count = PARAM1;
532     T0 &= DATA_MASK;
533     T1 &= DATA_MASK;
534     CC_SRC = T0 << (count - 1);
535     T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
536     CC_DST = T0;
537 }
538
539 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
540 {
541     int count;
542     count = ECX & 0x1f;
543     if (count) {
544         T0 &= DATA_MASK;
545         T1 &= DATA_MASK;
546         CC_SRC = T0 << (count - 1);
547         T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
548         CC_DST = T0;
549         CC_OP = CC_OP_SHLB + SHIFT;
550     }
551 }
552
553 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
554 {
555     int count;
556     count = PARAM1;
557     T0 &= DATA_MASK;
558     T1 &= DATA_MASK;
559     CC_SRC = T0 >> (count - 1);
560     T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
561     CC_DST = T0;
562 }
563
564
565 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
566 {
567     int count;
568     count = ECX & 0x1f;
569     if (count) {
570         T0 &= DATA_MASK;
571         T1 &= DATA_MASK;
572         CC_SRC = T0 >> (count - 1);
573         T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
574         CC_DST = T0;
575         CC_OP = CC_OP_SARB + SHIFT;
576     }
577 }
578 #endif
579
580 /* carry add/sub (we only need to set CC_OP differently) */
581
582 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
583 {
584     int cf;
585     cf = cc_table[CC_OP].compute_c();
586     CC_SRC = T0;
587     T0 = T0 + T1 + cf;
588     CC_DST = T0;
589     CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
590 }
591
592 void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
593 {
594     int cf;
595     cf = cc_table[CC_OP].compute_c();
596     CC_SRC = T0;
597     T0 = T0 - T1 - cf;
598     CC_DST = T0;
599     CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
600 }
601
602 /* bit operations */
603 #if DATA_BITS >= 16
604
605 void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
606 {
607     int count;
608     count = T1 & SHIFT_MASK;
609     CC_SRC = T0 >> count;
610 }
611
612 void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
613 {
614     int count;
615     count = T1 & SHIFT_MASK;
616     CC_SRC = T0 >> count;
617     T0 |= (1 << count);
618 }
619
620 void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
621 {
622     int count;
623     count = T1 & SHIFT_MASK;
624     CC_SRC = T0 >> count;
625     T0 &= ~(1 << count);
626 }
627
628 void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
629 {
630     int count;
631     count = T1 & SHIFT_MASK;
632     CC_SRC = T0 >> count;
633     T0 ^= (1 << count);
634 }
635
636 void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
637 {
638     int res, count;
639     res = T0 & DATA_MASK;
640     if (res != 0) {
641         count = 0;
642         while ((res & 1) == 0) {
643             count++;
644             res >>= 1;
645         }
646         T0 = count;
647         CC_DST = 1; /* ZF = 1 */
648     } else {
649         CC_DST = 0; /* ZF = 1 */
650     }
651     FORCE_RET();
652 }
653
654 void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
655 {
656     int res, count;
657     res = T0 & DATA_MASK;
658     if (res != 0) {
659         count = DATA_BITS - 1;
660         while ((res & SIGN_MASK) == 0) {
661             count--;
662             res <<= 1;
663         }
664         T0 = count;
665         CC_DST = 1; /* ZF = 1 */
666     } else {
667         CC_DST = 0; /* ZF = 1 */
668     }
669     FORCE_RET();
670 }
671
672 #endif
673
674 /* string operations */
675 /* XXX: maybe use lower level instructions to ease exception handling */
676
677 void OPPROTO glue(op_movs, SUFFIX)(void)
678 {
679     int v;
680     v = glue(ldu, SUFFIX)((void *)ESI);
681     glue(st, SUFFIX)((void *)EDI, v);
682     ESI += (DF << SHIFT);
683     EDI += (DF << SHIFT);
684 }
685
686 void OPPROTO glue(op_rep_movs, SUFFIX)(void)
687 {
688     int v, inc;
689     inc = (DF << SHIFT);
690     while (ECX != 0) {
691         v = glue(ldu, SUFFIX)((void *)ESI);
692         glue(st, SUFFIX)((void *)EDI, v);
693         ESI += inc;
694         EDI += inc;
695         ECX--;
696     }
697 }
698
699 void OPPROTO glue(op_stos, SUFFIX)(void)
700 {
701     glue(st, SUFFIX)((void *)EDI, EAX);
702     EDI += (DF << SHIFT);
703 }
704
705 void OPPROTO glue(op_rep_stos, SUFFIX)(void)
706 {
707     int inc;
708     inc = (DF << SHIFT);
709     while (ECX != 0) {
710         glue(st, SUFFIX)((void *)EDI, EAX);
711         EDI += inc;
712         ECX--;
713     }
714 }
715
716 void OPPROTO glue(op_lods, SUFFIX)(void)
717 {
718     int v;
719     v = glue(ldu, SUFFIX)((void *)ESI);
720 #if SHIFT == 0
721     EAX = (EAX & ~0xff) | v;
722 #elif SHIFT == 1
723     EAX = (EAX & ~0xffff) | v;
724 #else
725     EAX = v;
726 #endif
727     ESI += (DF << SHIFT);
728 }
729
730 /* don't know if it is used */
731 void OPPROTO glue(op_rep_lods, SUFFIX)(void)
732 {
733     int v, inc;
734     inc = (DF << SHIFT);
735     while (ECX != 0) {
736         v = glue(ldu, SUFFIX)((void *)ESI);
737 #if SHIFT == 0
738         EAX = (EAX & ~0xff) | v;
739 #elif SHIFT == 1
740         EAX = (EAX & ~0xffff) | v;
741 #else
742         EAX = v;
743 #endif
744         ESI += inc;
745         ECX--;
746     }
747 }
748
749 void OPPROTO glue(op_scas, SUFFIX)(void)
750 {
751     int v;
752
753     v = glue(ldu, SUFFIX)((void *)EDI);
754     EDI += (DF << SHIFT);
755     CC_SRC = EAX;
756     CC_DST = EAX - v;
757 }
758
759 void OPPROTO glue(op_repz_scas, SUFFIX)(void)
760 {
761     int v1, v2, inc;
762
763     if (ECX != 0) {
764         /* NOTE: the flags are not modified if ECX == 0 */
765         v1 = EAX & DATA_MASK;
766         inc = (DF << SHIFT);
767         do {
768             v2 = glue(ldu, SUFFIX)((void *)EDI);
769             EDI += inc;
770             ECX--;
771             if (v1 != v2)
772                 break;
773         } while (ECX != 0);
774         CC_SRC = v1;
775         CC_DST = v1 - v2;
776         CC_OP = CC_OP_SUBB + SHIFT;
777     }
778 }
779
780 void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
781 {
782     int v1, v2, inc;
783
784     if (ECX != 0) {
785         /* NOTE: the flags are not modified if ECX == 0 */
786         v1 = EAX & DATA_MASK;
787         inc = (DF << SHIFT);
788         do {
789             v2 = glue(ldu, SUFFIX)((void *)EDI);
790             EDI += inc;
791             ECX--;
792             if (v1 == v2)
793                 break;
794         } while (ECX != 0);
795         CC_SRC = v1;
796         CC_DST = v1 - v2;
797         CC_OP = CC_OP_SUBB + SHIFT;
798     }
799 }
800
801 void OPPROTO glue(op_cmps, SUFFIX)(void)
802 {
803     int v1, v2;
804     v1 = glue(ldu, SUFFIX)((void *)ESI);
805     v2 = glue(ldu, SUFFIX)((void *)EDI);
806     ESI += (DF << SHIFT);
807     EDI += (DF << SHIFT);
808     CC_SRC = v1;
809     CC_DST = v1 - v2;
810 }
811
812 void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
813 {
814     int v1, v2, inc;
815     if (ECX != 0) {
816         inc = (DF << SHIFT);
817         do {
818             v1 = glue(ldu, SUFFIX)((void *)ESI);
819             v2 = glue(ldu, SUFFIX)((void *)EDI);
820             ESI += inc;
821             EDI += inc;
822             ECX--;
823             if (v1 != v2)
824                 break;
825         } while (ECX != 0);
826         CC_SRC = v1;
827         CC_DST = v1 - v2;
828         CC_OP = CC_OP_SUBB + SHIFT;
829     }
830 }
831
832 void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
833 {
834     int v1, v2, inc;
835     if (ECX != 0) {
836         inc = (DF << SHIFT);
837         do {
838             v1 = glue(ldu, SUFFIX)((void *)ESI);
839             v2 = glue(ldu, SUFFIX)((void *)EDI);
840             ESI += inc;
841             EDI += inc;
842             ECX--;
843             if (v1 == v2)
844                 break;
845         } while (ECX != 0);
846         CC_SRC = v1;
847         CC_DST = v1 - v2;
848         CC_OP = CC_OP_SUBB + SHIFT;
849     }
850 }
851
852 /* port I/O */
853
854 void OPPROTO glue(op_outs, SUFFIX)(void)
855 {
856     int v, dx;
857     dx = EDX & 0xffff;
858     v = glue(ldu, SUFFIX)((void *)ESI);
859     glue(cpu_x86_out, SUFFIX)(dx, v);
860     ESI += (DF << SHIFT);
861 }
862
863 void OPPROTO glue(op_rep_outs, SUFFIX)(void)
864 {
865     int v, dx, inc;
866     inc = (DF << SHIFT);
867     dx = EDX & 0xffff;
868     while (ECX != 0) {
869         v = glue(ldu, SUFFIX)((void *)ESI);
870         glue(cpu_x86_out, SUFFIX)(dx, v);
871         ESI += inc;
872         ECX--;
873     }
874 }
875
876 void OPPROTO glue(op_ins, SUFFIX)(void)
877 {
878     int v, dx;
879     dx = EDX & 0xffff;
880     v = glue(cpu_x86_in, SUFFIX)(dx);
881     glue(st, SUFFIX)((void *)EDI, v);
882     EDI += (DF << SHIFT);
883 }
884
885 void OPPROTO glue(op_rep_ins, SUFFIX)(void)
886 {
887     int v, dx, inc;
888     inc = (DF << SHIFT);
889     dx = EDX & 0xffff;
890     while (ECX != 0) {
891         v = glue(cpu_x86_in, SUFFIX)(dx);
892         glue(st, SUFFIX)((void *)EDI, v);
893         EDI += (DF << SHIFT);
894         ECX--;
895     }
896 }
897
898 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
899 {
900     glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
901 }
902
903 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
904 {
905     T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
906 }
907
908 #undef DATA_BITS
909 #undef SHIFT_MASK
910 #undef SIGN_MASK
911 #undef DATA_TYPE
912 #undef DATA_STYPE
913 #undef DATA_MASK
914 #undef SUFFIX