many fixes
[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 & 1;
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;
185 }
186
187 #if DATA_BITS == 32
188 static int glue(compute_c_shl, SUFFIX)(void)
189 {
190     return CC_SRC & 1;
191 }
192 #endif
193
194 static int glue(compute_all_sar, SUFFIX)(void)
195 {
196     int cf, pf, af, zf, sf, of;
197     cf = CC_SRC & 1;
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;
204 }
205
206 /* various optimized jumps cases */
207
208 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
209 {
210     int src1, src2;
211     src1 = CC_SRC;
212     src2 = CC_SRC - CC_DST;
213
214     if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
215         PC = PARAM1;
216     else
217         PC = PARAM2;
218     FORCE_RET();
219 }
220
221 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
222 {
223     if ((DATA_TYPE)CC_DST == 0)
224         PC = PARAM1;
225     else
226         PC = PARAM2;
227     FORCE_RET();
228 }
229
230 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
231 {
232     int src1, src2;
233     src1 = CC_SRC;
234     src2 = CC_SRC - CC_DST;
235
236     if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
237         PC = PARAM1;
238     else
239         PC = PARAM2;
240     FORCE_RET();
241 }
242
243 void OPPROTO glue(op_js_sub, SUFFIX)(void)
244 {
245     if (CC_DST & SIGN_MASK)
246         PC = PARAM1;
247     else
248         PC = PARAM2;
249     FORCE_RET();
250 }
251
252 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
253 {
254     int src1, src2;
255     src1 = CC_SRC;
256     src2 = CC_SRC - CC_DST;
257
258     if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
259         PC = PARAM1;
260     else
261         PC = PARAM2;
262     FORCE_RET();
263 }
264
265 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
266 {
267     int src1, src2;
268     src1 = CC_SRC;
269     src2 = CC_SRC - CC_DST;
270
271     if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
272         PC = PARAM1;
273     else
274         PC = PARAM2;
275     FORCE_RET();
276 }
277
278 /* various optimized set cases */
279
280 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
281 {
282     int src1, src2;
283     src1 = CC_SRC;
284     src2 = CC_SRC - CC_DST;
285
286     T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
287 }
288
289 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
290 {
291     T0 = ((DATA_TYPE)CC_DST == 0);
292 }
293
294 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
295 {
296     int src1, src2;
297     src1 = CC_SRC;
298     src2 = CC_SRC - CC_DST;
299
300     T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
301 }
302
303 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
304 {
305     T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
306 }
307
308 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
309 {
310     int src1, src2;
311     src1 = CC_SRC;
312     src2 = CC_SRC - CC_DST;
313
314     T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
315 }
316
317 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
318 {
319     int src1, src2;
320     src1 = CC_SRC;
321     src2 = CC_SRC - CC_DST;
322
323     T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
324 }
325
326 /* shifts */
327
328 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
329 {
330     int count, src;
331     count = T1 & SHIFT_MASK;
332     if (count) {
333         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
334         src = T0;
335         T0 &= DATA_MASK;
336         T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
337         CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
338             (T0 & CC_C);
339         CC_OP = CC_OP_EFLAGS;
340     }
341     FORCE_RET();
342 }
343
344 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
345 {
346     int count, src;
347     count = T1 & SHIFT_MASK;
348     if (count) {
349         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
350         src = T0;
351         T0 &= DATA_MASK;
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;
356     }
357     FORCE_RET();
358 }
359
360 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
361 {
362     int count, res, eflags;
363     unsigned int src;
364
365     count = T1 & 0x1f;
366 #if DATA_BITS == 16
367     count = rclw_table[count];
368 #elif DATA_BITS == 8
369     count = rclb_table[count];
370 #endif
371     if (count) {
372         eflags = cc_table[CC_OP].compute_all();
373         T0 &= DATA_MASK;
374         src = T0;
375         res = (T0 << count) | ((eflags & CC_C) << (count - 1));
376         if (count > 1)
377             res |= T0 >> (DATA_BITS + 1 - count);
378         T0 = res;
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;
383     }
384     FORCE_RET();
385 }
386
387 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
388 {
389     int count, res, eflags;
390     unsigned int src;
391
392     count = T1 & 0x1f;
393 #if DATA_BITS == 16
394     count = rclw_table[count];
395 #elif DATA_BITS == 8
396     count = rclb_table[count];
397 #endif
398     if (count) {
399         eflags = cc_table[CC_OP].compute_all();
400         T0 &= DATA_MASK;
401         src = T0;
402         res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
403         if (count > 1)
404             res |= T0 << (DATA_BITS + 1 - count);
405         T0 = res;
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;
410     }
411     FORCE_RET();
412 }
413
414 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
415 {
416     int count;
417     count = T1 & 0x1f;
418     if (count == 1) {
419         CC_SRC = T0;
420         T0 = T0 << 1;
421         CC_DST = T0;
422         CC_OP = CC_OP_ADDB + SHIFT;
423     } else if (count) {
424         CC_SRC = (DATA_TYPE)T0 >> (DATA_BITS - count);
425         T0 = T0 << count;
426         CC_DST = T0;
427         CC_OP = CC_OP_SHLB + SHIFT;
428     }
429     FORCE_RET();
430 }
431
432 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
433 {
434     int count;
435     count = T1 & 0x1f;
436     if (count) {
437         T0 &= DATA_MASK;
438         CC_SRC = T0 >> (count - 1);
439         T0 = T0 >> count;
440         CC_DST = T0;
441         CC_OP = CC_OP_SHLB + SHIFT;
442     }
443     FORCE_RET();
444 }
445
446 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
447 {
448     int count, src;
449     count = T1 & 0x1f;
450     if (count) {
451         src = (DATA_STYPE)T0;
452         CC_SRC =  src >> (count - 1);
453         T0 = src >> count;
454         CC_DST = T0;
455         CC_OP = CC_OP_SARB + SHIFT;
456     }
457     FORCE_RET();
458 }
459
460 /* carry add/sub (we only need to set CC_OP differently) */
461
462 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
463 {
464     int cf;
465     cf = cc_table[CC_OP].compute_c();
466     CC_SRC = T0;
467     T0 = T0 + T1 + cf;
468     CC_DST = T0;
469     CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
470 }
471
472 void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
473 {
474     int cf;
475     cf = cc_table[CC_OP].compute_c();
476     CC_SRC = T0;
477     T0 = T0 - T1 - cf;
478     CC_DST = T0;
479     CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
480 }
481
482 /* bit operations */
483 #if DATA_BITS >= 16
484
485 void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
486 {
487     int count;
488     count = T1 & SHIFT_MASK;
489     CC_SRC = T0 >> count;
490 }
491
492 void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
493 {
494     int count;
495     count = T1 & SHIFT_MASK;
496     CC_SRC = T0 >> count;
497     T0 |= (1 << count);
498 }
499
500 void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
501 {
502     int count;
503     count = T1 & SHIFT_MASK;
504     CC_SRC = T0 >> count;
505     T0 &= ~(1 << count);
506 }
507
508 void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
509 {
510     int count;
511     count = T1 & SHIFT_MASK;
512     CC_SRC = T0 >> count;
513     T0 ^= (1 << count);
514 }
515
516 #endif
517
518 /* string operations */
519 /* XXX: maybe use lower level instructions to ease exception handling */
520
521 void OPPROTO glue(op_movs, SUFFIX)(void)
522 {
523     int v;
524     v = glue(ldu, SUFFIX)((void *)ESI);
525     glue(st, SUFFIX)((void *)EDI, v);
526     ESI += (DF << SHIFT);
527     EDI += (DF << SHIFT);
528 }
529
530 void OPPROTO glue(op_rep_movs, SUFFIX)(void)
531 {
532     int v, inc;
533     inc = (DF << SHIFT);
534     while (ECX != 0) {
535         v = glue(ldu, SUFFIX)((void *)ESI);
536         glue(st, SUFFIX)((void *)EDI, v);
537         ESI += inc;
538         EDI += inc;
539         ECX--;
540     }
541 }
542
543 void OPPROTO glue(op_stos, SUFFIX)(void)
544 {
545     glue(st, SUFFIX)((void *)EDI, EAX);
546     EDI += (DF << SHIFT);
547 }
548
549 void OPPROTO glue(op_rep_stos, SUFFIX)(void)
550 {
551     int inc;
552     inc = (DF << SHIFT);
553     while (ECX != 0) {
554         glue(st, SUFFIX)((void *)EDI, EAX);
555         EDI += inc;
556         ECX--;
557     }
558 }
559
560 void OPPROTO glue(op_lods, SUFFIX)(void)
561 {
562     int v;
563     v = glue(ldu, SUFFIX)((void *)ESI);
564 #if SHIFT == 0
565     EAX = (EAX & ~0xff) | v;
566 #elif SHIFT == 1
567     EAX = (EAX & ~0xffff) | v;
568 #else
569     EAX = v;
570 #endif
571     ESI += (DF << SHIFT);
572 }
573
574 /* don't know if it is used */
575 void OPPROTO glue(op_rep_lods, SUFFIX)(void)
576 {
577     int v, inc;
578     inc = (DF << SHIFT);
579     while (ECX != 0) {
580         v = glue(ldu, SUFFIX)((void *)ESI);
581 #if SHIFT == 0
582         EAX = (EAX & ~0xff) | v;
583 #elif SHIFT == 1
584         EAX = (EAX & ~0xffff) | v;
585 #else
586         EAX = v;
587 #endif
588         ESI += inc;
589         ECX--;
590     }
591 }
592
593 void OPPROTO glue(op_scas, SUFFIX)(void)
594 {
595     int v;
596
597     v = glue(ldu, SUFFIX)((void *)EDI);
598     EDI += (DF << SHIFT);
599     CC_SRC = EAX;
600     CC_DST = EAX - v;
601 }
602
603 void OPPROTO glue(op_repz_scas, SUFFIX)(void)
604 {
605     int v1, v2, inc;
606
607     if (ECX != 0) {
608         /* NOTE: the flags are not modified if ECX == 0 */
609         v1 = EAX & DATA_MASK;
610         inc = (DF << SHIFT);
611         do {
612             v2 = glue(ldu, SUFFIX)((void *)EDI);
613             EDI += inc;
614             ECX--;
615             if (v1 != v2)
616                 break;
617         } while (ECX != 0);
618         CC_SRC = v1;
619         CC_DST = v1 - v2;
620         CC_OP = CC_OP_SUBB + SHIFT;
621     }
622 }
623
624 void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
625 {
626     int v1, v2, inc;
627
628     if (ECX != 0) {
629         /* NOTE: the flags are not modified if ECX == 0 */
630         v1 = EAX & DATA_MASK;
631         inc = (DF << SHIFT);
632         do {
633             v2 = glue(ldu, SUFFIX)((void *)EDI);
634             EDI += inc;
635             ECX--;
636             if (v1 == v2)
637                 break;
638         } while (ECX != 0);
639         CC_SRC = v1;
640         CC_DST = v1 - v2;
641         CC_OP = CC_OP_SUBB + SHIFT;
642     }
643 }
644
645 void OPPROTO glue(op_cmps, SUFFIX)(void)
646 {
647     int v1, v2;
648     v1 = glue(ldu, SUFFIX)((void *)ESI);
649     v2 = glue(ldu, SUFFIX)((void *)EDI);
650     ESI += (DF << SHIFT);
651     EDI += (DF << SHIFT);
652     CC_SRC = v1;
653     CC_DST = v1 - v2;
654 }
655
656 void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
657 {
658     int v1, v2, inc;
659     if (ECX != 0) {
660         inc = (DF << SHIFT);
661         do {
662             v1 = glue(ldu, SUFFIX)((void *)ESI);
663             v2 = glue(ldu, SUFFIX)((void *)EDI);
664             ESI += inc;
665             EDI += inc;
666             ECX--;
667             if (v1 != v2)
668                 break;
669         } while (ECX != 0);
670         CC_SRC = v1;
671         CC_DST = v1 - v2;
672         CC_OP = CC_OP_SUBB + SHIFT;
673     }
674 }
675
676 void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
677 {
678     int v1, v2, inc;
679     if (ECX != 0) {
680         inc = (DF << SHIFT);
681         do {
682             v1 = glue(ldu, SUFFIX)((void *)ESI);
683             v2 = glue(ldu, SUFFIX)((void *)EDI);
684             ESI += inc;
685             EDI += inc;
686             ECX--;
687             if (v1 == v2)
688                 break;
689         } while (ECX != 0);
690         CC_SRC = v1;
691         CC_DST = v1 - v2;
692         CC_OP = CC_OP_SUBB + SHIFT;
693     }
694 }
695
696 /* port I/O */
697
698 void OPPROTO glue(op_outs, SUFFIX)(void)
699 {
700     int v, dx;
701     dx = EDX & 0xffff;
702     v = glue(ldu, SUFFIX)((void *)ESI);
703     glue(cpu_x86_out, SUFFIX)(dx, v);
704     ESI += (DF << SHIFT);
705 }
706
707 void OPPROTO glue(op_rep_outs, SUFFIX)(void)
708 {
709     int v, dx, inc;
710     inc = (DF << SHIFT);
711     dx = EDX & 0xffff;
712     while (ECX != 0) {
713         v = glue(ldu, SUFFIX)((void *)ESI);
714         glue(cpu_x86_out, SUFFIX)(dx, v);
715         ESI += inc;
716         ECX--;
717     }
718 }
719
720 void OPPROTO glue(op_ins, SUFFIX)(void)
721 {
722     int v, dx;
723     dx = EDX & 0xffff;
724     v = glue(cpu_x86_in, SUFFIX)(dx);
725     glue(st, SUFFIX)((void *)EDI, v);
726     EDI += (DF << SHIFT);
727 }
728
729 void OPPROTO glue(op_rep_ins, SUFFIX)(void)
730 {
731     int v, dx, inc;
732     inc = (DF << SHIFT);
733     dx = EDX & 0xffff;
734     while (ECX != 0) {
735         v = glue(cpu_x86_in, SUFFIX)(dx);
736         glue(st, SUFFIX)((void *)EDI, v);
737         EDI += (DF << SHIFT);
738         ECX--;
739     }
740 }
741
742 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
743 {
744     glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
745 }
746
747 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
748 {
749     T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
750 }
751
752 #undef DATA_BITS
753 #undef SHIFT_MASK
754 #undef SIGN_MASK
755 #undef DATA_TYPE
756 #undef DATA_STYPE
757 #undef DATA_MASK
758 #undef SUFFIX