1 /****************************************************************************
2 *
3 *                                               Realmode X86 Emulator Library
4 *
5 *               Copyright (C) 1996-1999 SciTech Software, Inc.
6 *                                    Copyright (C) David Mosberger-Tang
7 *                                          Copyright (C) 1999 Egbert Eich
8 *
9 *  ========================================================================
10 *
11 *  Permission to use, copy, modify, distribute, and sell this software and
12 *  its documentation for any purpose is hereby granted without fee,
13 *  provided that the above copyright notice appear in all copies and that
14 *  both that copyright notice and this permission notice appear in
15 *  supporting documentation, and that the name of the authors not be used
16 *  in advertising or publicity pertaining to distribution of the software
17 *  without specific, written prior permission.  The authors makes no
18 *  representations about the suitability of this software for any purpose.
19 *  It is provided "as is" without express or implied warranty.
20 *
21 *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 *  PERFORMANCE OF THIS SOFTWARE.
28 *
29 *  ========================================================================
30 *
31 * Language:             ANSI C
32 * Environment:  Any
33 * Developer:    Kendall Bennett
34 *
35 * Description:  This file contains the code to implement the primitive
36 *                               machine operations used by the emulation code in ops.c
37 *
38 * Carry Chain Calculation
39 *
40 * This represents a somewhat expensive calculation which is
41 * apparently required to emulate the setting of the OF and AF flag.
42 * The latter is not so important, but the former is.  The overflow
43 * flag is the XOR of the top two bits of the carry chain for an
44 * addition (similar for subtraction).  Since we do not want to
45 * simulate the addition in a bitwise manner, we try to calculate the
46 * carry chain given the two operands and the result.
47 *
48 * So, given the following table, which represents the addition of two
49 * bits, we can derive a formula for the carry chain.
50 *
51 * a   b   cin   r     cout
52 * 0   0   0     0     0
53 * 0   0   1     1     0
54 * 0   1   0     1     0
55 * 0   1   1     0     1
56 * 1   0   0     1     0
57 * 1   0   1     0     1
58 * 1   1   0     0     1
59 * 1   1   1     1     1
60 *
61 * Construction of table for cout:
62 *
63 * ab
64 * r  \  00   01   11  10
65 * |------------------
66 * 0  |   0    1    1   1
67 * 1  |   0    0    1   0
68 *
69 * By inspection, one gets:  cc = ab +  r'(a + b)
70 *
71 * That represents alot of operations, but NO CHOICE....
72 *
73 * Borrow Chain Calculation.
74 *
75 * The following table represents the subtraction of two bits, from
76 * which we can derive a formula for the borrow chain.
77 *
78 * a   b   bin   r     bout
79 * 0   0   0     0     0
80 * 0   0   1     1     1
81 * 0   1   0     1     1
82 * 0   1   1     0     1
83 * 1   0   0     1     0
84 * 1   0   1     0     0
85 * 1   1   0     0     0
86 * 1   1   1     1     1
87 *
88 * Construction of table for cout:
89 *
90 * ab
91 * r  \  00   01   11  10
92 * |------------------
93 * 0  |   0    1    0   0
94 * 1  |   1    1    1   0
95 *
96 * By inspection, one gets:  bc = a'b +  r(a' + b)
97 *
98 ****************************************************************************/
99 
100 #define PRIM_OPS_NO_REDEFINE_ASM
101 #include "x86emu/x86emui.h"
102 
103 /*------------------------- Global Variables ------------------------------*/
104 
105 static u32 x86emu_parity_tab[8] =
106 {
107         0x96696996,
108         0x69969669,
109         0x69969669,
110         0x96696996,
111         0x69969669,
112         0x96696996,
113         0x96696996,
114         0x69969669,
115 };
116 
117 #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
118 #define XOR2(x)         (((x) ^ ((x)>>1)) & 0x1)
119 
120 /*----------------------------- Implementation ----------------------------*/
121 
122 /****************************************************************************
123 REMARKS:
124 Implements the AAA instruction and side effects.
125 ****************************************************************************/
126 u16 aaa_word(u16 d)
127 {
128         u16     res;
129         if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
130                 d += 0x6;
131                 d += 0x100;
132                 SET_FLAG(F_AF);
133                 SET_FLAG(F_CF);
134         } else {
135                 CLEAR_FLAG(F_CF);
136                 CLEAR_FLAG(F_AF);
137         }
138         res = (u16)(d & 0xFF0F);
139         CLEAR_FLAG(F_SF);
140         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
141         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
142         return res;
143 }
144 
145 /****************************************************************************
146 REMARKS:
147 Implements the AAA instruction and side effects.
148 ****************************************************************************/
149 u16 aas_word(u16 d)
150 {
151         u16     res;
152         if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
153                 d -= 0x6;
154                 d -= 0x100;
155                 SET_FLAG(F_AF);
156                 SET_FLAG(F_CF);
157         } else {
158                 CLEAR_FLAG(F_CF);
159                 CLEAR_FLAG(F_AF);
160         }
161         res = (u16)(d & 0xFF0F);
162         CLEAR_FLAG(F_SF);
163         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
164         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
165         return res;
166 }
167 
168 /****************************************************************************
169 REMARKS:
170 Implements the AAD instruction and side effects.
171 ****************************************************************************/
172 u16 aad_word(u16 d)
173 {
174         u16 l;
175         u8 hb, lb;
176 
177         hb = (u8)((d >> 8) & 0xff);
178         lb = (u8)((d & 0xff));
179         l = (u16)((lb + 10 * hb) & 0xFF);
180 
181         CLEAR_FLAG(F_CF);
182         CLEAR_FLAG(F_AF);
183         CLEAR_FLAG(F_OF);
184         CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
185         CONDITIONAL_SET_FLAG(l == 0, F_ZF);
186         CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
187         return l;
188 }
189 
190 /****************************************************************************
191 REMARKS:
192 Implements the AAM instruction and side effects.
193 ****************************************************************************/
194 u16 aam_word(u8 d)
195 {
196     u16 h, l;
197 
198         h = (u16)(d / 10);
199         l = (u16)(d % 10);
200         l |= (u16)(h << 8);
201 
202         CLEAR_FLAG(F_CF);
203         CLEAR_FLAG(F_AF);
204         CLEAR_FLAG(F_OF);
205         CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
206         CONDITIONAL_SET_FLAG(l == 0, F_ZF);
207         CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
208     return l;
209 }
210 
211 /****************************************************************************
212 REMARKS:
213 Implements the ADC instruction and side effects.
214 ****************************************************************************/
215 u8 adc_byte(u8 d, u8 s)
216 {
217         register u32 res;   /* all operands in native machine order */
218         register u32 cc;
219 
220         if (ACCESS_FLAG(F_CF))
221                 res = 1 + d + s;
222         else
223                 res = d + s;
224 
225         CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
226         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
227         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
228         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
229 
230         /* calculate the carry chain  SEE NOTE AT TOP. */
231         cc = (s & d) | ((~res) & (s | d));
232         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
233         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
234         return (u8)res;
235 }
236 
237 /****************************************************************************
238 REMARKS:
239 Implements the ADC instruction and side effects.
240 ****************************************************************************/
241 u16 adc_word(u16 d, u16 s)
242 {
243         register u32 res;   /* all operands in native machine order */
244         register u32 cc;
245 
246         if (ACCESS_FLAG(F_CF))
247                 res = 1 + d + s;
248         else
249                 res = d + s;
250 
251         CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
252         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
253         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
254         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
255 
256         /* calculate the carry chain  SEE NOTE AT TOP. */
257         cc = (s & d) | ((~res) & (s | d));
258         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
259         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
260         return (u16)res;
261 }
262 
263 /****************************************************************************
264 REMARKS:
265 Implements the ADC instruction and side effects.
266 ****************************************************************************/
267 u32 adc_long(u32 d, u32 s)
268 {
269         register u32 lo;        /* all operands in native machine order */
270         register u32 hi;
271         register u32 res;
272         register u32 cc;
273 
274         if (ACCESS_FLAG(F_CF)) {
275                 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
276                 res = 1 + d + s;
277                 }
278         else {
279                 lo = (d & 0xFFFF) + (s & 0xFFFF);
280                 res = d + s;
281                 }
282         hi = (lo >> 16) + (d >> 16) + (s >> 16);
283 
284         CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
285         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
286         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
287         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
288 
289         /* calculate the carry chain  SEE NOTE AT TOP. */
290         cc = (s & d) | ((~res) & (s | d));
291         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
292         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
293         return res;
294 }
295 
296 /****************************************************************************
297 REMARKS:
298 Implements the ADD instruction and side effects.
299 ****************************************************************************/
300 u8 add_byte(u8 d, u8 s)
301 {
302         register u32 res;   /* all operands in native machine order */
303         register u32 cc;
304 
305         res = d + s;
306         CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
307         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
308         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
309         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
310 
311         /* calculate the carry chain  SEE NOTE AT TOP. */
312         cc = (s & d) | ((~res) & (s | d));
313         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
314         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
315         return (u8)res;
316 }
317 
318 /****************************************************************************
319 REMARKS:
320 Implements the ADD instruction and side effects.
321 ****************************************************************************/
322 u16 add_word(u16 d, u16 s)
323 {
324         register u32 res;   /* all operands in native machine order */
325         register u32 cc;
326 
327         res = d + s;
328         CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
329         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
330         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
331         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
332 
333         /* calculate the carry chain  SEE NOTE AT TOP. */
334         cc = (s & d) | ((~res) & (s | d));
335         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
336         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
337         return (u16)res;
338 }
339 
340 /****************************************************************************
341 REMARKS:
342 Implements the ADD instruction and side effects.
343 ****************************************************************************/
344 u32 add_long(u32 d, u32 s)
345 {
346         register u32 lo;        /* all operands in native machine order */
347         register u32 hi;
348         register u32 res;
349         register u32 cc;
350 
351         lo = (d & 0xFFFF) + (s & 0xFFFF);
352         res = d + s;
353         hi = (lo >> 16) + (d >> 16) + (s >> 16);
354 
355         CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
356         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
357         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
358         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
359 
360     /* calculate the carry chain  SEE NOTE AT TOP. */
361     cc = (s & d) | ((~res) & (s | d));
362         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
363         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
364 
365     return res;
366 }
367 
368 /****************************************************************************
369 REMARKS:
370 Implements the AND instruction and side effects.
371 ****************************************************************************/
372 u8 and_byte(u8 d, u8 s)
373 {
374         register u8 res;    /* all operands in native machine order */
375 
376         res = d & s;
377 
378         /* set the flags  */
379         CLEAR_FLAG(F_OF);
380         CLEAR_FLAG(F_CF);
381         CLEAR_FLAG(F_AF);
382         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
383         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
384         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
385         return res;
386 }
387 
388 /****************************************************************************
389 REMARKS:
390 Implements the AND instruction and side effects.
391 ****************************************************************************/
392 u16 and_word(u16 d, u16 s)
393 {
394     register u16 res;   /* all operands in native machine order */
395 
396     res = d & s;
397 
398     /* set the flags  */
399         CLEAR_FLAG(F_OF);
400         CLEAR_FLAG(F_CF);
401         CLEAR_FLAG(F_AF);
402         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
403         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
404         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
405     return res;
406 }
407 
408 /****************************************************************************
409 REMARKS:
410 Implements the AND instruction and side effects.
411 ****************************************************************************/
412 u32 and_long(u32 d, u32 s)
413 {
414         register u32 res;   /* all operands in native machine order */
415 
416         res = d & s;
417 
418         /* set the flags  */
419         CLEAR_FLAG(F_OF);
420         CLEAR_FLAG(F_CF);
421         CLEAR_FLAG(F_AF);
422         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
423         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
424         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
425         return res;
426 }
427 
428 /****************************************************************************
429 REMARKS:
430 Implements the CMP instruction and side effects.
431 ****************************************************************************/
432 u8 cmp_byte(u8 d, u8 s)
433 {
434         register u32 res;   /* all operands in native machine order */
435         register u32 bc;
436 
437         res = d - s;
438         CLEAR_FLAG(F_CF);
439         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
440         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
441         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
442 
443         /* calculate the borrow chain.  See note at top */
444         bc = (res & (~d | s)) | (~d & s);
445         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
446         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
447         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
448         return d;
449 }
450 
451 /****************************************************************************
452 REMARKS:
453 Implements the CMP instruction and side effects.
454 ****************************************************************************/
455 u16 cmp_word(u16 d, u16 s)
456 {
457         register u32 res;   /* all operands in native machine order */
458         register u32 bc;
459 
460         res = d - s;
461         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
462         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
463         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
464 
465         /* calculate the borrow chain.  See note at top */
466     bc = (res & (~d | s)) | (~d & s);
467         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
468         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
469         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
470         return d;
471 }
472 
473 /****************************************************************************
474 REMARKS:
475 Implements the CMP instruction and side effects.
476 ****************************************************************************/
477 u32 cmp_long(u32 d, u32 s)
478 {
479         register u32 res;   /* all operands in native machine order */
480         register u32 bc;
481 
482         res = d - s;
483         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
484         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
485         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
486 
487         /* calculate the borrow chain.  See note at top */
488         bc = (res & (~d | s)) | (~d & s);
489         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
490         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
491         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
492         return d;
493 }
494 
495 /****************************************************************************
496 REMARKS:
497 Implements the DAA instruction and side effects.
498 ****************************************************************************/
499 u8 daa_byte(u8 d)
500 {
501         u32 res = d;
502         if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
503                 res += 6;
504                 SET_FLAG(F_AF);
505         }
506         if (res > 0x9F || ACCESS_FLAG(F_CF)) {
507                 res += 0x60;
508                 SET_FLAG(F_CF);
509         }
510         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
511         CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
512         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
513         return (u8)res;
514 }
515 
516 /****************************************************************************
517 REMARKS:
518 Implements the DAS instruction and side effects.
519 ****************************************************************************/
520 u8 das_byte(u8 d)
521 {
522         if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
523                 d -= 6;
524                 SET_FLAG(F_AF);
525         }
526         if (d > 0x9F || ACCESS_FLAG(F_CF)) {
527                 d -= 0x60;
528                 SET_FLAG(F_CF);
529         }
530         CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
531         CONDITIONAL_SET_FLAG(d == 0, F_ZF);
532         CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
533         return d;
534 }
535 
536 /****************************************************************************
537 REMARKS:
538 Implements the DEC instruction and side effects.
539 ****************************************************************************/
540 u8 dec_byte(u8 d)
541 {
542     register u32 res;   /* all operands in native machine order */
543     register u32 bc;
544 
545     res = d - 1;
546         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
547         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
548         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
549 
550         /* calculate the borrow chain.  See note at top */
551         /* based on sub_byte, uses s==1.  */
552         bc = (res & (~d | 1)) | (~d & 1);
553         /* carry flag unchanged */
554         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
555         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
556         return (u8)res;
557 }
558 
559 /****************************************************************************
560 REMARKS:
561 Implements the DEC instruction and side effects.
562 ****************************************************************************/
563 u16 dec_word(u16 d)
564 {
565     register u32 res;   /* all operands in native machine order */
566     register u32 bc;
567 
568     res = d - 1;
569         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
570         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
571         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
572 
573     /* calculate the borrow chain.  See note at top */
574     /* based on the sub_byte routine, with s==1 */
575     bc = (res & (~d | 1)) | (~d & 1);
576     /* carry flag unchanged */
577         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
578         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
579         return (u16)res;
580 }
581 
582 /****************************************************************************
583 REMARKS:
584 Implements the DEC instruction and side effects.
585 ****************************************************************************/
586 u32 dec_long(u32 d)
587 {
588     register u32 res;   /* all operands in native machine order */
589     register u32 bc;
590 
591     res = d - 1;
592 
593         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
594         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
595         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
596 
597     /* calculate the borrow chain.  See note at top */
598         bc = (res & (~d | 1)) | (~d & 1);
599         /* carry flag unchanged */
600         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
601         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
602         return res;
603 }
604 
605 /****************************************************************************
606 REMARKS:
607 Implements the INC instruction and side effects.
608 ****************************************************************************/
609 u8 inc_byte(u8 d)
610 {
611         register u32 res;   /* all operands in native machine order */
612         register u32 cc;
613 
614         res = d + 1;
615         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
616         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
617         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
618 
619         /* calculate the carry chain  SEE NOTE AT TOP. */
620         cc = ((1 & d) | (~res)) & (1 | d);
621         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
622         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
623         return (u8)res;
624 }
625 
626 /****************************************************************************
627 REMARKS:
628 Implements the INC instruction and side effects.
629 ****************************************************************************/
630 u16 inc_word(u16 d)
631 {
632         register u32 res;   /* all operands in native machine order */
633         register u32 cc;
634 
635         res = d + 1;
636         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
637         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
638         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
639 
640         /* calculate the carry chain  SEE NOTE AT TOP. */
641         cc = (1 & d) | ((~res) & (1 | d));
642         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
643         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
644         return (u16)res;
645 }
646 
647 /****************************************************************************
648 REMARKS:
649 Implements the INC instruction and side effects.
650 ****************************************************************************/
651 u32 inc_long(u32 d)
652 {
653         register u32 res;   /* all operands in native machine order */
654         register u32 cc;
655 
656         res = d + 1;
657         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
658         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
659         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
660 
661         /* calculate the carry chain  SEE NOTE AT TOP. */
662         cc = (1 & d) | ((~res) & (1 | d));
663         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
664         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
665         return res;
666 }
667 
668 /****************************************************************************
669 REMARKS:
670 Implements the OR instruction and side effects.
671 ****************************************************************************/
672 u8 or_byte(u8 d, u8 s)
673 {
674         register u8 res;    /* all operands in native machine order */
675 
676         res = d | s;
677         CLEAR_FLAG(F_OF);
678         CLEAR_FLAG(F_CF);
679         CLEAR_FLAG(F_AF);
680         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
681         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
682         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
683         return res;
684 }
685 
686 /****************************************************************************
687 REMARKS:
688 Implements the OR instruction and side effects.
689 ****************************************************************************/
690 u16 or_word(u16 d, u16 s)
691 {
692         register u16 res;   /* all operands in native machine order */
693 
694         res = d | s;
695         /* set the carry flag to be bit 8 */
696         CLEAR_FLAG(F_OF);
697         CLEAR_FLAG(F_CF);
698         CLEAR_FLAG(F_AF);
699         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
700         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
701         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
702         return res;
703 }
704 
705 /****************************************************************************
706 REMARKS:
707 Implements the OR instruction and side effects.
708 ****************************************************************************/
709 u32 or_long(u32 d, u32 s)
710 {
711         register u32 res;   /* all operands in native machine order */
712 
713         res = d | s;
714 
715         /* set the carry flag to be bit 8 */
716         CLEAR_FLAG(F_OF);
717         CLEAR_FLAG(F_CF);
718         CLEAR_FLAG(F_AF);
719         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
720         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
721         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
722         return res;
723 }
724 
725 /****************************************************************************
726 REMARKS:
727 Implements the OR instruction and side effects.
728 ****************************************************************************/
729 u8 neg_byte(u8 s)
730 {
731     register u8 res;
732     register u8 bc;
733 
734         CONDITIONAL_SET_FLAG(s != 0, F_CF);
735         res = (u8)-s;
736         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
737         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
738         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
739         /* calculate the borrow chain --- modified such that d=0.
740            substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
741            (the one used for sub) and simplifying, since ~d=0xff...,
742            ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
743            ~d&s == s.  So the simplified result is: */
744         bc = res | s;
745         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
746         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
747         return res;
748 }
749 
750 /****************************************************************************
751 REMARKS:
752 Implements the OR instruction and side effects.
753 ****************************************************************************/
754 u16 neg_word(u16 s)
755 {
756         register u16 res;
757         register u16 bc;
758 
759         CONDITIONAL_SET_FLAG(s != 0, F_CF);
760         res = (u16)-s;
761         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
762         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
763         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
764 
765         /* calculate the borrow chain --- modified such that d=0.
766            substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
767            (the one used for sub) and simplifying, since ~d=0xff...,
768            ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
769            ~d&s == s.  So the simplified result is: */
770         bc = res | s;
771         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
772         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
773         return res;
774 }
775 
776 /****************************************************************************
777 REMARKS:
778 Implements the OR instruction and side effects.
779 ****************************************************************************/
780 u32 neg_long(u32 s)
781 {
782         register u32 res;
783         register u32 bc;
784 
785         CONDITIONAL_SET_FLAG(s != 0, F_CF);
786         res = (u32)-s;
787         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
788         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
789         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
790 
791         /* calculate the borrow chain --- modified such that d=0.
792            substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
793            (the one used for sub) and simplifying, since ~d=0xff...,
794            ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
795            ~d&s == s.  So the simplified result is: */
796         bc = res | s;
797         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
798         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
799         return res;
800 }
801 
802 /****************************************************************************
803 REMARKS:
804 Implements the NOT instruction and side effects.
805 ****************************************************************************/
806 u8 not_byte(u8 s)
807 {
808         return ~s;
809 }
810 
811 /****************************************************************************
812 REMARKS:
813 Implements the NOT instruction and side effects.
814 ****************************************************************************/
815 u16 not_word(u16 s)
816 {
817         return ~s;
818 }
819 
820 /****************************************************************************
821 REMARKS:
822 Implements the NOT instruction and side effects.
823 ****************************************************************************/
824 u32 not_long(u32 s)
825 {
826         return ~s;
827 }
828 
829 /****************************************************************************
830 REMARKS:
831 Implements the RCL instruction and side effects.
832 ****************************************************************************/
833 u8 rcl_byte(u8 d, u8 s)
834 {
835     register unsigned int res, cnt, mask, cf;
836 
837     /* s is the rotate distance.  It varies from 0 - 8. */
838         /* have
839 
840        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
841 
842        want to rotate through the carry by "s" bits.  We could
843        loop, but that's inefficient.  So the width is 9,
844        and we split into three parts:
845 
846        The new carry flag   (was B_n)
847        the stuff in B_n-1 .. B_0
848        the stuff in B_7 .. B_n+1
849 
850        The new rotate is done mod 9, and given this,
851        for a rotation of n bits (mod 9) the new carry flag is
852        then located n bits from the MSB.  The low part is
853        then shifted up cnt bits, and the high part is or'd
854        in.  Using CAPS for new values, and lowercase for the
855        original values, this can be expressed as:
856 
857        IF n > 0
858        1) CF <-  b_(8-n)
859        2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
860        3) B_(n-1) <- cf
861        4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
862          */
863         res = d;
864         if ((cnt = s % 9) != 0) {
865         /* extract the new CARRY FLAG. */
866         /* CF <-  b_(8-n)             */
867         cf = (d >> (8 - cnt)) & 0x1;
868 
869         /* get the low stuff which rotated
870            into the range B_7 .. B_cnt */
871         /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
872         /* note that the right hand side done by the mask */
873                 res = (d << cnt) & 0xff;
874 
875         /* now the high stuff which rotated around
876            into the positions B_cnt-2 .. B_0 */
877         /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
878         /* shift it downward, 7-(n-2) = 9-n positions.
879            and mask off the result before or'ing in.
880          */
881         mask = (1 << (cnt - 1)) - 1;
882         res |= (d >> (9 - cnt)) & mask;
883 
884         /* if the carry flag was set, or it in.  */
885                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
886             /*  B_(n-1) <- cf */
887             res |= 1 << (cnt - 1);
888         }
889         /* set the new carry flag, based on the variable "cf" */
890                 CONDITIONAL_SET_FLAG(cf, F_CF);
891         /* OVERFLOW is set *IFF* cnt==1, then it is the
892            xor of CF and the most significant bit.  Blecck. */
893         /* parenthesized this expression since it appears to
894            be causing OF to be misset */
895         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
896                                                          F_OF);
897 
898     }
899         return (u8)res;
900 }
901 
902 /****************************************************************************
903 REMARKS:
904 Implements the RCL instruction and side effects.
905 ****************************************************************************/
906 u16 rcl_word(u16 d, u8 s)
907 {
908         register unsigned int res, cnt, mask, cf;
909 
910         res = d;
911         if ((cnt = s % 17) != 0) {
912                 cf = (d >> (16 - cnt)) & 0x1;
913                 res = (d << cnt) & 0xffff;
914                 mask = (1 << (cnt - 1)) - 1;
915                 res |= (d >> (17 - cnt)) & mask;
916                 if (ACCESS_FLAG(F_CF)) {
917                         res |= 1 << (cnt - 1);
918                 }
919                 CONDITIONAL_SET_FLAG(cf, F_CF);
920                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
921                                                          F_OF);
922         }
923         return (u16)res;
924 }
925 
926 /****************************************************************************
927 REMARKS:
928 Implements the RCL instruction and side effects.
929 ****************************************************************************/
930 u32 rcl_long(u32 d, u8 s)
931 {
932         register u32 res, cnt, mask, cf;
933 
934         res = d;
935         if ((cnt = s % 33) != 0) {
936                 cf = (d >> (32 - cnt)) & 0x1;
937                 res = (d << cnt) & 0xffffffff;
938                 mask = (1 << (cnt - 1)) - 1;
939                 res |= (d >> (33 - cnt)) & mask;
940                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
941                         res |= 1 << (cnt - 1);
942                 }
943                 CONDITIONAL_SET_FLAG(cf, F_CF);
944                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
945                                                          F_OF);
946         }
947         return res;
948 }
949 
950 /****************************************************************************
951 REMARKS:
952 Implements the RCR instruction and side effects.
953 ****************************************************************************/
954 u8 rcr_byte(u8 d, u8 s)
955 {
956         u32     res, cnt;
957         u32     mask, cf, ocf = 0;
958 
959         /* rotate right through carry */
960     /*
961        s is the rotate distance.  It varies from 0 - 8.
962        d is the byte object rotated.
963 
964        have
965 
966        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
967 
968        The new rotate is done mod 9, and given this,
969        for a rotation of n bits (mod 9) the new carry flag is
970        then located n bits from the LSB.  The low part is
971        then shifted up cnt bits, and the high part is or'd
972        in.  Using CAPS for new values, and lowercase for the
973        original values, this can be expressed as:
974 
975        IF n > 0
976        1) CF <-  b_(n-1)
977        2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
978        3) B_(8-n) <- cf
979        4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
980          */
981         res = d;
982         if ((cnt = s % 9) != 0) {
983         /* extract the new CARRY FLAG. */
984         /* CF <-  b_(n-1)              */
985         if (cnt == 1) {
986             cf = d & 0x1;
987             /* note hackery here.  Access_flag(..) evaluates to either
988                0 if flag not set
989                non-zero if flag is set.
990                doing access_flag(..) != 0 casts that into either
991                            0..1 in any representation of the flags register
992                (i.e. packed bit array or unpacked.)
993              */
994                         ocf = ACCESS_FLAG(F_CF) != 0;
995         } else
996             cf = (d >> (cnt - 1)) & 0x1;
997 
998         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
999         /* note that the right hand side done by the mask
1000            This is effectively done by shifting the
1001            object to the right.  The result must be masked,
1002            in case the object came in and was treated
1003            as a negative number.  Needed??? */
1004 
1005         mask = (1 << (8 - cnt)) - 1;
1006         res = (d >> cnt) & mask;
1007 
1008         /* now the high stuff which rotated around
1009            into the positions B_cnt-2 .. B_0 */
1010         /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
1011         /* shift it downward, 7-(n-2) = 9-n positions.
1012            and mask off the result before or'ing in.
1013          */
1014         res |= (d << (9 - cnt));
1015 
1016         /* if the carry flag was set, or it in.  */
1017                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1018             /*  B_(8-n) <- cf */
1019             res |= 1 << (8 - cnt);
1020         }
1021         /* set the new carry flag, based on the variable "cf" */
1022                 CONDITIONAL_SET_FLAG(cf, F_CF);
1023         /* OVERFLOW is set *IFF* cnt==1, then it is the
1024            xor of CF and the most significant bit.  Blecck. */
1025         /* parenthesized... */
1026                 if (cnt == 1) {
1027                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
1028                                                                  F_OF);
1029                 }
1030         }
1031         return (u8)res;
1032 }
1033 
1034 /****************************************************************************
1035 REMARKS:
1036 Implements the RCR instruction and side effects.
1037 ****************************************************************************/
1038 u16 rcr_word(u16 d, u8 s)
1039 {
1040         u32 res, cnt;
1041         u32     mask, cf, ocf = 0;
1042 
1043         /* rotate right through carry */
1044         res = d;
1045         if ((cnt = s % 17) != 0) {
1046                 if (cnt == 1) {
1047                         cf = d & 0x1;
1048                         ocf = ACCESS_FLAG(F_CF) != 0;
1049                 } else
1050                         cf = (d >> (cnt - 1)) & 0x1;
1051                 mask = (1 << (16 - cnt)) - 1;
1052                 res = (d >> cnt) & mask;
1053                 res |= (d << (17 - cnt));
1054                 if (ACCESS_FLAG(F_CF)) {
1055                         res |= 1 << (16 - cnt);
1056                 }
1057                 CONDITIONAL_SET_FLAG(cf, F_CF);
1058                 if (cnt == 1) {
1059                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
1060                                                                  F_OF);
1061                 }
1062         }
1063         return (u16)res;
1064 }
1065 
1066 /****************************************************************************
1067 REMARKS:
1068 Implements the RCR instruction and side effects.
1069 ****************************************************************************/
1070 u32 rcr_long(u32 d, u8 s)
1071 {
1072         u32 res, cnt;
1073         u32 mask, cf, ocf = 0;
1074 
1075         /* rotate right through carry */
1076         res = d;
1077         if ((cnt = s % 33) != 0) {
1078                 if (cnt == 1) {
1079                         cf = d & 0x1;
1080                         ocf = ACCESS_FLAG(F_CF) != 0;
1081                 } else
1082                         cf = (d >> (cnt - 1)) & 0x1;
1083                 mask = (1 << (32 - cnt)) - 1;
1084                 res = (d >> cnt) & mask;
1085                 if (cnt != 1)
1086                         res |= (d << (33 - cnt));
1087                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1088                         res |= 1 << (32 - cnt);
1089                 }
1090                 CONDITIONAL_SET_FLAG(cf, F_CF);
1091                 if (cnt == 1) {
1092                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
1093                                                                  F_OF);
1094                 }
1095         }
1096         return res;
1097 }
1098 
1099 /****************************************************************************
1100 REMARKS:
1101 Implements the ROL instruction and side effects.
1102 ****************************************************************************/
1103 u8 rol_byte(u8 d, u8 s)
1104 {
1105     register unsigned int res, cnt, mask;
1106 
1107     /* rotate left */
1108     /*
1109        s is the rotate distance.  It varies from 0 - 8.
1110        d is the byte object rotated.
1111 
1112        have
1113 
1114        CF  B_7 ... B_0
1115 
1116        The new rotate is done mod 8.
1117        Much simpler than the "rcl" or "rcr" operations.
1118 
1119        IF n > 0
1120        1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
1121        2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
1122          */
1123     res = d;
1124         if ((cnt = s % 8) != 0) {
1125                 /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1126                 res = (d << cnt);
1127 
1128                 /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1129                 mask = (1 << cnt) - 1;
1130                 res |= (d >> (8 - cnt)) & mask;
1131 
1132                 /* set the new carry flag, Note that it is the low order
1133                    bit of the result!!!                               */
1134                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1135                 /* OVERFLOW is set *IFF* s==1, then it is the
1136                    xor of CF and the most significant bit.  Blecck. */
1137                 CONDITIONAL_SET_FLAG(s == 1 &&
1138                                                          XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1139                                                          F_OF);
1140         } if (s != 0) {
1141                 /* set the new carry flag, Note that it is the low order
1142                    bit of the result!!!                               */
1143                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1144         }
1145         return (u8)res;
1146 }
1147 
1148 /****************************************************************************
1149 REMARKS:
1150 Implements the ROL instruction and side effects.
1151 ****************************************************************************/
1152 u16 rol_word(u16 d, u8 s)
1153 {
1154     register unsigned int res, cnt, mask;
1155 
1156         res = d;
1157         if ((cnt = s % 16) != 0) {
1158                 res = (d << cnt);
1159                 mask = (1 << cnt) - 1;
1160                 res |= (d >> (16 - cnt)) & mask;
1161                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1162                 CONDITIONAL_SET_FLAG(s == 1 &&
1163                                                          XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1164                                                          F_OF);
1165         } if (s != 0) {
1166                 /* set the new carry flag, Note that it is the low order
1167                    bit of the result!!!                               */
1168                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1169         }
1170         return (u16)res;
1171 }
1172 
1173 /****************************************************************************
1174 REMARKS:
1175 Implements the ROL instruction and side effects.
1176 ****************************************************************************/
1177 u32 rol_long(u32 d, u8 s)
1178 {
1179     register u32 res, cnt, mask;
1180 
1181         res = d;
1182         if ((cnt = s % 32) != 0) {
1183                 res = (d << cnt);
1184                 mask = (1 << cnt) - 1;
1185                 res |= (d >> (32 - cnt)) & mask;
1186                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1187                 CONDITIONAL_SET_FLAG(s == 1 &&
1188                                                          XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1189                                                          F_OF);
1190         } if (s != 0) {
1191                 /* set the new carry flag, Note that it is the low order
1192                    bit of the result!!!                               */
1193                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1194         }
1195         return res;
1196 }
1197 
1198 /****************************************************************************
1199 REMARKS:
1200 Implements the ROR instruction and side effects.
1201 ****************************************************************************/
1202 u8 ror_byte(u8 d, u8 s)
1203 {
1204     register unsigned int res, cnt, mask;
1205 
1206     /* rotate right */
1207     /*
1208        s is the rotate distance.  It varies from 0 - 8.
1209        d is the byte object rotated.
1210 
1211        have
1212 
1213        B_7 ... B_0
1214 
1215        The rotate is done mod 8.
1216 
1217        IF n > 0
1218        1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
1219        2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
1220          */
1221         res = d;
1222         if ((cnt = s % 8) != 0) {           /* not a typo, do nada if cnt==0 */
1223         /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
1224         res = (d << (8 - cnt));
1225 
1226         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
1227         mask = (1 << (8 - cnt)) - 1;
1228         res |= (d >> (cnt)) & mask;
1229 
1230         /* set the new carry flag, Note that it is the low order
1231            bit of the result!!!                               */
1232                 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1233                 /* OVERFLOW is set *IFF* s==1, then it is the
1234            xor of the two most significant bits.  Blecck. */
1235                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1236         } else if (s != 0) {
1237                 /* set the new carry flag, Note that it is the low order
1238                    bit of the result!!!                               */
1239                 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1240         }
1241         return (u8)res;
1242 }
1243 
1244 /****************************************************************************
1245 REMARKS:
1246 Implements the ROR instruction and side effects.
1247 ****************************************************************************/
1248 u16 ror_word(u16 d, u8 s)
1249 {
1250     register unsigned int res, cnt, mask;
1251 
1252         res = d;
1253         if ((cnt = s % 16) != 0) {
1254                 res = (d << (16 - cnt));
1255                 mask = (1 << (16 - cnt)) - 1;
1256                 res |= (d >> (cnt)) & mask;
1257                 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1258                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1259         } else if (s != 0) {
1260                 /* set the new carry flag, Note that it is the low order
1261                    bit of the result!!!                               */
1262                 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1263         }
1264         return (u16)res;
1265 }
1266 
1267 /****************************************************************************
1268 REMARKS:
1269 Implements the ROR instruction and side effects.
1270 ****************************************************************************/
1271 u32 ror_long(u32 d, u8 s)
1272 {
1273         register u32 res, cnt, mask;
1274 
1275         res = d;
1276         if ((cnt = s % 32) != 0) {
1277                 res = (d << (32 - cnt));
1278                 mask = (1 << (32 - cnt)) - 1;
1279                 res |= (d >> (cnt)) & mask;
1280                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1281                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1282         } else if (s != 0) {
1283                 /* set the new carry flag, Note that it is the low order
1284                    bit of the result!!!                               */
1285                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1286         }
1287         return res;
1288 }
1289 
1290 /****************************************************************************
1291 REMARKS:
1292 Implements the SHL instruction and side effects.
1293 ****************************************************************************/
1294 u8 shl_byte(u8 d, u8 s)
1295 {
1296         unsigned int cnt, res, cf;
1297 
1298         if (s < 8) {
1299                 cnt = s % 8;
1300 
1301                 /* last bit shifted out goes into carry flag */
1302                 if (cnt > 0) {
1303                         res = d << cnt;
1304                         cf = d & (1 << (8 - cnt));
1305                         CONDITIONAL_SET_FLAG(cf, F_CF);
1306                         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1307                         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1308                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1309                 } else {
1310                         res = (u8) d;
1311                 }
1312 
1313                 if (cnt == 1) {
1314                         /* Needs simplification. */
1315                         CONDITIONAL_SET_FLAG(
1316                                                                         (((res & 0x80) == 0x80) ^
1317                                                                          (ACCESS_FLAG(F_CF) != 0)),
1318                         /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1319                                                                         F_OF);
1320                 } else {
1321                         CLEAR_FLAG(F_OF);
1322                 }
1323         } else {
1324                 res = 0;
1325                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1326                 CLEAR_FLAG(F_OF);
1327                 CLEAR_FLAG(F_SF);
1328                 SET_FLAG(F_PF);
1329                 SET_FLAG(F_ZF);
1330     }
1331         return (u8)res;
1332 }
1333 
1334 /****************************************************************************
1335 REMARKS:
1336 Implements the SHL instruction and side effects.
1337 ****************************************************************************/
1338 u16 shl_word(u16 d, u8 s)
1339 {
1340     unsigned int cnt, res, cf;
1341 
1342         if (s < 16) {
1343                 cnt = s % 16;
1344                 if (cnt > 0) {
1345                         res = d << cnt;
1346                         cf = d & (1 << (16 - cnt));
1347                         CONDITIONAL_SET_FLAG(cf, F_CF);
1348                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1349                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1350                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1351                 } else {
1352                         res = (u16) d;
1353                 }
1354 
1355                 if (cnt == 1) {
1356                         CONDITIONAL_SET_FLAG(
1357                                                                         (((res & 0x8000) == 0x8000) ^
1358                                                                          (ACCESS_FLAG(F_CF) != 0)),
1359                                                                         F_OF);
1360         } else {
1361                         CLEAR_FLAG(F_OF);
1362         }
1363     } else {
1364                 res = 0;
1365                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1366                 CLEAR_FLAG(F_OF);
1367                 CLEAR_FLAG(F_SF);
1368                 SET_FLAG(F_PF);
1369                 SET_FLAG(F_ZF);
1370         }
1371         return (u16)res;
1372 }
1373 
1374 /****************************************************************************
1375 REMARKS:
1376 Implements the SHL instruction and side effects.
1377 ****************************************************************************/
1378 u32 shl_long(u32 d, u8 s)
1379 {
1380         unsigned int cnt, res, cf;
1381 
1382         if (s < 32) {
1383                 cnt = s % 32;
1384                 if (cnt > 0) {
1385                         res = d << cnt;
1386                         cf = d & (1 << (32 - cnt));
1387                         CONDITIONAL_SET_FLAG(cf, F_CF);
1388                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1389                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1390                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1391                 } else {
1392                         res = d;
1393                 }
1394                 if (cnt == 1) {
1395                         CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1396                                                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1397                 } else {
1398                         CLEAR_FLAG(F_OF);
1399                 }
1400         } else {
1401                 res = 0;
1402                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1403                 CLEAR_FLAG(F_OF);
1404                 CLEAR_FLAG(F_SF);
1405                 SET_FLAG(F_PF);
1406                 SET_FLAG(F_ZF);
1407         }
1408         return res;
1409 }
1410 
1411 /****************************************************************************
1412 REMARKS:
1413 Implements the SHR instruction and side effects.
1414 ****************************************************************************/
1415 u8 shr_byte(u8 d, u8 s)
1416 {
1417         unsigned int cnt, res, cf;
1418 
1419         if (s < 8) {
1420                 cnt = s % 8;
1421                 if (cnt > 0) {
1422                         cf = d & (1 << (cnt - 1));
1423                         res = d >> cnt;
1424                         CONDITIONAL_SET_FLAG(cf, F_CF);
1425                         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1426                         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1427                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1428                 } else {
1429                         res = (u8) d;
1430                 }
1431 
1432                 if (cnt == 1) {
1433                         CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1434                 } else {
1435                         CLEAR_FLAG(F_OF);
1436                 }
1437         } else {
1438                 res = 0;
1439                 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1440                 CLEAR_FLAG(F_OF);
1441                 CLEAR_FLAG(F_SF);
1442                 SET_FLAG(F_PF);
1443                 SET_FLAG(F_ZF);
1444         }
1445         return (u8)res;
1446 }
1447 
1448 /****************************************************************************
1449 REMARKS:
1450 Implements the SHR instruction and side effects.
1451 ****************************************************************************/
1452 u16 shr_word(u16 d, u8 s)
1453 {
1454         unsigned int cnt, res, cf;
1455 
1456         if (s < 16) {
1457                 cnt = s % 16;
1458                 if (cnt > 0) {
1459                         cf = d & (1 << (cnt - 1));
1460                         res = d >> cnt;
1461                         CONDITIONAL_SET_FLAG(cf, F_CF);
1462                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1463                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1464                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1465                 } else {
1466                         res = d;
1467                 }
1468 
1469                 if (cnt == 1) {
1470                         CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1471         } else {
1472                         CLEAR_FLAG(F_OF);
1473         }
1474         } else {
1475                 res = 0;
1476                 CLEAR_FLAG(F_CF);
1477                 CLEAR_FLAG(F_OF);
1478                 SET_FLAG(F_ZF);
1479                 CLEAR_FLAG(F_SF);
1480                 CLEAR_FLAG(F_PF);
1481     }
1482         return (u16)res;
1483 }
1484 
1485 /****************************************************************************
1486 REMARKS:
1487 Implements the SHR instruction and side effects.
1488 ****************************************************************************/
1489 u32 shr_long(u32 d, u8 s)
1490 {
1491         unsigned int cnt, res, cf;
1492 
1493         if (s < 32) {
1494                 cnt = s % 32;
1495                 if (cnt > 0) {
1496                         cf = d & (1 << (cnt - 1));
1497                         res = d >> cnt;
1498                         CONDITIONAL_SET_FLAG(cf, F_CF);
1499                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1500                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1501                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1502         } else {
1503             res = d;
1504         }
1505         if (cnt == 1) {
1506                         CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1507         } else {
1508                         CLEAR_FLAG(F_OF);
1509         }
1510     } else {
1511         res = 0;
1512                 CLEAR_FLAG(F_CF);
1513                 CLEAR_FLAG(F_OF);
1514                 SET_FLAG(F_ZF);
1515                 CLEAR_FLAG(F_SF);
1516                 CLEAR_FLAG(F_PF);
1517     }
1518     return res;
1519 }
1520 
1521 /****************************************************************************
1522 REMARKS:
1523 Implements the SAR instruction and side effects.
1524 ****************************************************************************/
1525 u8 sar_byte(u8 d, u8 s)
1526 {
1527         unsigned int cnt, res, cf, mask, sf;
1528 
1529         res = d;
1530         sf = d & 0x80;
1531     cnt = s % 8;
1532         if (cnt > 0 && cnt < 8) {
1533                 mask = (1 << (8 - cnt)) - 1;
1534                 cf = d & (1 << (cnt - 1));
1535                 res = (d >> cnt) & mask;
1536                 CONDITIONAL_SET_FLAG(cf, F_CF);
1537                 if (sf) {
1538                         res |= ~mask;
1539                 }
1540                 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1541                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1542                 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1543     } else if (cnt >= 8) {
1544         if (sf) {
1545             res = 0xff;
1546                         SET_FLAG(F_CF);
1547                         CLEAR_FLAG(F_ZF);
1548                         SET_FLAG(F_SF);
1549                         SET_FLAG(F_PF);
1550                 } else {
1551                         res = 0;
1552                         CLEAR_FLAG(F_CF);
1553                         SET_FLAG(F_ZF);
1554                         CLEAR_FLAG(F_SF);
1555                         CLEAR_FLAG(F_PF);
1556                 }
1557         }
1558         return (u8)res;
1559 }
1560 
1561 /****************************************************************************
1562 REMARKS:
1563 Implements the SAR instruction and side effects.
1564 ****************************************************************************/
1565 u16 sar_word(u16 d, u8 s)
1566 {
1567     unsigned int cnt, res, cf, mask, sf;
1568 
1569     sf = d & 0x8000;
1570     cnt = s % 16;
1571         res = d;
1572         if (cnt > 0 && cnt < 16) {
1573         mask = (1 << (16 - cnt)) - 1;
1574         cf = d & (1 << (cnt - 1));
1575         res = (d >> cnt) & mask;
1576                 CONDITIONAL_SET_FLAG(cf, F_CF);
1577         if (sf) {
1578             res |= ~mask;
1579         }
1580                 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1581                 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1582                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1583     } else if (cnt >= 16) {
1584         if (sf) {
1585             res = 0xffff;
1586                         SET_FLAG(F_CF);
1587                         CLEAR_FLAG(F_ZF);
1588                         SET_FLAG(F_SF);
1589                         SET_FLAG(F_PF);
1590         } else {
1591             res = 0;
1592                         CLEAR_FLAG(F_CF);
1593                         SET_FLAG(F_ZF);
1594                         CLEAR_FLAG(F_SF);
1595                         CLEAR_FLAG(F_PF);
1596         }
1597     }
1598         return (u16)res;
1599 }
1600 
1601 /****************************************************************************
1602 REMARKS:
1603 Implements the SAR instruction and side effects.
1604 ****************************************************************************/
1605 u32 sar_long(u32 d, u8 s)
1606 {
1607     u32 cnt, res, cf, mask, sf;
1608 
1609     sf = d & 0x80000000;
1610     cnt = s % 32;
1611         res = d;
1612         if (cnt > 0 && cnt < 32) {
1613         mask = (1 << (32 - cnt)) - 1;
1614                 cf = d & (1 << (cnt - 1));
1615         res = (d >> cnt) & mask;
1616                 CONDITIONAL_SET_FLAG(cf, F_CF);
1617         if (sf) {
1618             res |= ~mask;
1619         }
1620                 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1621                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1622                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1623     } else if (cnt >= 32) {
1624         if (sf) {
1625             res = 0xffffffff;
1626                         SET_FLAG(F_CF);
1627                         CLEAR_FLAG(F_ZF);
1628                         SET_FLAG(F_SF);
1629                         SET_FLAG(F_PF);
1630                 } else {
1631                         res = 0;
1632                         CLEAR_FLAG(F_CF);
1633                         SET_FLAG(F_ZF);
1634                         CLEAR_FLAG(F_SF);
1635                         CLEAR_FLAG(F_PF);
1636                 }
1637         }
1638         return res;
1639 }
1640 
1641 /****************************************************************************
1642 REMARKS:
1643 Implements the SHLD instruction and side effects.
1644 ****************************************************************************/
1645 u16 shld_word (u16 d, u16 fill, u8 s)
1646 {
1647         unsigned int cnt, res, cf;
1648 
1649         if (s < 16) {
1650                 cnt = s % 16;
1651                 if (cnt > 0) {
1652                         res = (d << cnt) | (fill >> (16-cnt));
1653                         cf = d & (1 << (16 - cnt));
1654                         CONDITIONAL_SET_FLAG(cf, F_CF);
1655                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1656                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1657                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1658                 } else {
1659                         res = d;
1660                 }
1661                 if (cnt == 1) {
1662                         CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1663                                                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1664                 } else {
1665                         CLEAR_FLAG(F_OF);
1666                 }
1667         } else {
1668                 res = 0;
1669                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1670                 CLEAR_FLAG(F_OF);
1671                 CLEAR_FLAG(F_SF);
1672                 SET_FLAG(F_PF);
1673                 SET_FLAG(F_ZF);
1674         }
1675         return (u16)res;
1676 }
1677 
1678 /****************************************************************************
1679 REMARKS:
1680 Implements the SHLD instruction and side effects.
1681 ****************************************************************************/
1682 u32 shld_long (u32 d, u32 fill, u8 s)
1683 {
1684         unsigned int cnt, res, cf;
1685 
1686         if (s < 32) {
1687                 cnt = s % 32;
1688                 if (cnt > 0) {
1689                         res = (d << cnt) | (fill >> (32-cnt));
1690                         cf = d & (1 << (32 - cnt));
1691                         CONDITIONAL_SET_FLAG(cf, F_CF);
1692                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1693                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1694                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1695                 } else {
1696                         res = d;
1697                 }
1698                 if (cnt == 1) {
1699                         CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1700                                                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1701                 } else {
1702                         CLEAR_FLAG(F_OF);
1703                 }
1704         } else {
1705                 res = 0;
1706                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1707                 CLEAR_FLAG(F_OF);
1708                 CLEAR_FLAG(F_SF);
1709                 SET_FLAG(F_PF);
1710                 SET_FLAG(F_ZF);
1711         }
1712         return res;
1713 }
1714 
1715 /****************************************************************************
1716 REMARKS:
1717 Implements the SHRD instruction and side effects.
1718 ****************************************************************************/
1719 u16 shrd_word (u16 d, u16 fill, u8 s)
1720 {
1721         unsigned int cnt, res, cf;
1722 
1723         if (s < 16) {
1724                 cnt = s % 16;
1725                 if (cnt > 0) {
1726                         cf = d & (1 << (cnt - 1));
1727                         res = (d >> cnt) | (fill << (16 - cnt));
1728                         CONDITIONAL_SET_FLAG(cf, F_CF);
1729                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1730                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1731                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1732                 } else {
1733                         res = d;
1734                 }
1735 
1736                 if (cnt == 1) {
1737                         CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1738         } else {
1739                         CLEAR_FLAG(F_OF);
1740         }
1741         } else {
1742                 res = 0;
1743                 CLEAR_FLAG(F_CF);
1744                 CLEAR_FLAG(F_OF);
1745                 SET_FLAG(F_ZF);
1746                 CLEAR_FLAG(F_SF);
1747                 CLEAR_FLAG(F_PF);
1748     }
1749         return (u16)res;
1750 }
1751 
1752 /****************************************************************************
1753 REMARKS:
1754 Implements the SHRD instruction and side effects.
1755 ****************************************************************************/
1756 u32 shrd_long (u32 d, u32 fill, u8 s)
1757 {
1758         unsigned int cnt, res, cf;
1759 
1760         if (s < 32) {
1761                 cnt = s % 32;
1762                 if (cnt > 0) {
1763                         cf = d & (1 << (cnt - 1));
1764                         res = (d >> cnt) | (fill << (32 - cnt));
1765                         CONDITIONAL_SET_FLAG(cf, F_CF);
1766                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1767                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1768                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1769                 } else {
1770                         res = d;
1771                 }
1772                 if (cnt == 1) {
1773                         CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1774         } else {
1775                         CLEAR_FLAG(F_OF);
1776         }
1777         } else {
1778                 res = 0;
1779                 CLEAR_FLAG(F_CF);
1780                 CLEAR_FLAG(F_OF);
1781                 SET_FLAG(F_ZF);
1782                 CLEAR_FLAG(F_SF);
1783                 CLEAR_FLAG(F_PF);
1784     }
1785         return res;
1786 }
1787 
1788 /****************************************************************************
1789 REMARKS:
1790 Implements the SBB instruction and side effects.
1791 ****************************************************************************/
1792 u8 sbb_byte(u8 d, u8 s)
1793 {
1794     register u32 res;   /* all operands in native machine order */
1795     register u32 bc;
1796 
1797         if (ACCESS_FLAG(F_CF))
1798                 res = d - s - 1;
1799         else
1800                 res = d - s;
1801         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1802         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1803         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1804 
1805         /* calculate the borrow chain.  See note at top */
1806         bc = (res & (~d | s)) | (~d & s);
1807         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1808         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1809         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1810         return (u8)res;
1811 }
1812 
1813 /****************************************************************************
1814 REMARKS:
1815 Implements the SBB instruction and side effects.
1816 ****************************************************************************/
1817 u16 sbb_word(u16 d, u16 s)
1818 {
1819     register u32 res;   /* all operands in native machine order */
1820     register u32 bc;
1821 
1822         if (ACCESS_FLAG(F_CF))
1823         res = d - s - 1;
1824     else
1825         res = d - s;
1826         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1827         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1828         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1829 
1830         /* calculate the borrow chain.  See note at top */
1831         bc = (res & (~d | s)) | (~d & s);
1832         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1833         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1834         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1835         return (u16)res;
1836 }
1837 
1838 /****************************************************************************
1839 REMARKS:
1840 Implements the SBB instruction and side effects.
1841 ****************************************************************************/
1842 u32 sbb_long(u32 d, u32 s)
1843 {
1844         register u32 res;   /* all operands in native machine order */
1845         register u32 bc;
1846 
1847         if (ACCESS_FLAG(F_CF))
1848         res = d - s - 1;
1849     else
1850         res = d - s;
1851         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1852         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1853         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1854 
1855         /* calculate the borrow chain.  See note at top */
1856         bc = (res & (~d | s)) | (~d & s);
1857         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1858         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1859         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1860         return res;
1861 }
1862 
1863 /****************************************************************************
1864 REMARKS:
1865 Implements the SUB instruction and side effects.
1866 ****************************************************************************/
1867 u8 sub_byte(u8 d, u8 s)
1868 {
1869         register u32 res;   /* all operands in native machine order */
1870         register u32 bc;
1871 
1872         res = d - s;
1873         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1874         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1875         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1876 
1877         /* calculate the borrow chain.  See note at top */
1878         bc = (res & (~d | s)) | (~d & s);
1879         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1880         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1881         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1882         return (u8)res;
1883 }
1884 
1885 /****************************************************************************
1886 REMARKS:
1887 Implements the SUB instruction and side effects.
1888 ****************************************************************************/
1889 u16 sub_word(u16 d, u16 s)
1890 {
1891     register u32 res;   /* all operands in native machine order */
1892     register u32 bc;
1893 
1894     res = d - s;
1895         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1896         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1897         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1898 
1899         /* calculate the borrow chain.  See note at top */
1900         bc = (res & (~d | s)) | (~d & s);
1901         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1902         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1903         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1904         return (u16)res;
1905 }
1906 
1907 /****************************************************************************
1908 REMARKS:
1909 Implements the SUB instruction and side effects.
1910 ****************************************************************************/
1911 u32 sub_long(u32 d, u32 s)
1912 {
1913         register u32 res;   /* all operands in native machine order */
1914         register u32 bc;
1915 
1916         res = d - s;
1917         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1918         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1919         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1920 
1921         /* calculate the borrow chain.  See note at top */
1922         bc = (res & (~d | s)) | (~d & s);
1923         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1924         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1925         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1926         return res;
1927 }
1928 
1929 /****************************************************************************
1930 REMARKS:
1931 Implements the TEST instruction and side effects.
1932 ****************************************************************************/
1933 void test_byte(u8 d, u8 s)
1934 {
1935     register u32 res;   /* all operands in native machine order */
1936 
1937     res = d & s;
1938 
1939         CLEAR_FLAG(F_OF);
1940         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1941         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1942         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1943     /* AF == dont care */
1944         CLEAR_FLAG(F_CF);
1945 }
1946 
1947 /****************************************************************************
1948 REMARKS:
1949 Implements the TEST instruction and side effects.
1950 ****************************************************************************/
1951 void test_word(u16 d, u16 s)
1952 {
1953         register u32 res;   /* all operands in native machine order */
1954 
1955         res = d & s;
1956 
1957         CLEAR_FLAG(F_OF);
1958         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1959         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1960         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1961         /* AF == dont care */
1962         CLEAR_FLAG(F_CF);
1963 }
1964 
1965 /****************************************************************************
1966 REMARKS:
1967 Implements the TEST instruction and side effects.
1968 ****************************************************************************/
1969 void test_long(u32 d, u32 s)
1970 {
1971         register u32 res;   /* all operands in native machine order */
1972 
1973         res = d & s;
1974 
1975         CLEAR_FLAG(F_OF);
1976         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1977         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1978         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1979         /* AF == dont care */
1980         CLEAR_FLAG(F_CF);
1981 }
1982 
1983 /****************************************************************************
1984 REMARKS:
1985 Implements the XOR instruction and side effects.
1986 ****************************************************************************/
1987 u8 xor_byte(u8 d, u8 s)
1988 {
1989         register u8 res;    /* all operands in native machine order */
1990 
1991         res = d ^ s;
1992         CLEAR_FLAG(F_OF);
1993         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1994         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1995         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
1996         CLEAR_FLAG(F_CF);
1997         CLEAR_FLAG(F_AF);
1998         return res;
1999 }
2000 
2001 /****************************************************************************
2002 REMARKS:
2003 Implements the XOR instruction and side effects.
2004 ****************************************************************************/
2005 u16 xor_word(u16 d, u16 s)
2006 {
2007         register u16 res;   /* all operands in native machine order */
2008 
2009         res = d ^ s;
2010         CLEAR_FLAG(F_OF);
2011         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2012         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2013         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2014         CLEAR_FLAG(F_CF);
2015         CLEAR_FLAG(F_AF);
2016         return res;
2017 }
2018 
2019 /****************************************************************************
2020 REMARKS:
2021 Implements the XOR instruction and side effects.
2022 ****************************************************************************/
2023 u32 xor_long(u32 d, u32 s)
2024 {
2025         register u32 res;   /* all operands in native machine order */
2026 
2027         res = d ^ s;
2028         CLEAR_FLAG(F_OF);
2029         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2030         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2031         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2032         CLEAR_FLAG(F_CF);
2033         CLEAR_FLAG(F_AF);
2034         return res;
2035 }
2036 
2037 /****************************************************************************
2038 REMARKS:
2039 Implements the IMUL instruction and side effects.
2040 ****************************************************************************/
2041 void imul_byte(u8 s)
2042 {
2043         s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
2044 
2045         M.x86.R_AX = res;
2046         if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2047                 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2048                 CLEAR_FLAG(F_CF);
2049                 CLEAR_FLAG(F_OF);
2050         } else {
2051                 SET_FLAG(F_CF);
2052                 SET_FLAG(F_OF);
2053         }
2054 }
2055 
2056 /****************************************************************************
2057 REMARKS:
2058 Implements the IMUL instruction and side effects.
2059 ****************************************************************************/
2060 void imul_word(u16 s)
2061 {
2062         s32 res = (s16)M.x86.R_AX * (s16)s;
2063 
2064         M.x86.R_AX = (u16)res;
2065         M.x86.R_DX = (u16)(res >> 16);
2066         if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
2067                 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
2068                 CLEAR_FLAG(F_CF);
2069                 CLEAR_FLAG(F_OF);
2070         } else {
2071                 SET_FLAG(F_CF);
2072                 SET_FLAG(F_OF);
2073         }
2074 }
2075 
2076 /****************************************************************************
2077 REMARKS:
2078 Implements the IMUL instruction and side effects.
2079 ****************************************************************************/
2080 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2081 {
2082 #ifdef  __HAS_LONG_LONG__
2083         s64 res = (s64)(s32)d * (s32)s;
2084 
2085         *res_lo = (u32)res;
2086         *res_hi = (u32)(res >> 32);
2087 #else
2088         u32     d_lo,d_hi,d_sign;
2089         u32     s_lo,s_hi,s_sign;
2090         u32     rlo_lo,rlo_hi,rhi_lo;
2091 
2092         if ((d_sign = d & 0x80000000) != 0)
2093                 d = -d;
2094         d_lo = d & 0xFFFF;
2095         d_hi = d >> 16;
2096         if ((s_sign = s & 0x80000000) != 0)
2097                 s = -s;
2098         s_lo = s & 0xFFFF;
2099         s_hi = s >> 16;
2100         rlo_lo = d_lo * s_lo;
2101         rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2102         rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2103         *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2104         *res_hi = rhi_lo;
2105         if (d_sign != s_sign) {
2106                 d = ~*res_lo;
2107                 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2108                 *res_lo = ~*res_lo+1;
2109                 *res_hi = ~*res_hi+(s >> 16);
2110                 }
2111 #endif
2112 }
2113 
2114 /****************************************************************************
2115 REMARKS:
2116 Implements the IMUL instruction and side effects.
2117 ****************************************************************************/
2118 void imul_long(u32 s)
2119 {
2120         imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
2121         if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
2122                 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
2123                 CLEAR_FLAG(F_CF);
2124                 CLEAR_FLAG(F_OF);
2125         } else {
2126                 SET_FLAG(F_CF);
2127                 SET_FLAG(F_OF);
2128         }
2129 }
2130 
2131 /****************************************************************************
2132 REMARKS:
2133 Implements the MUL instruction and side effects.
2134 ****************************************************************************/
2135 void mul_byte(u8 s)
2136 {
2137         u16 res = (u16)(M.x86.R_AL * s);
2138 
2139         M.x86.R_AX = res;
2140         if (M.x86.R_AH == 0) {
2141                 CLEAR_FLAG(F_CF);
2142                 CLEAR_FLAG(F_OF);
2143         } else {
2144                 SET_FLAG(F_CF);
2145                 SET_FLAG(F_OF);
2146         }
2147 }
2148 
2149 /****************************************************************************
2150 REMARKS:
2151 Implements the MUL instruction and side effects.
2152 ****************************************************************************/
2153 void mul_word(u16 s)
2154 {
2155         u32 res = M.x86.R_AX * s;
2156 
2157         M.x86.R_AX = (u16)res;
2158         M.x86.R_DX = (u16)(res >> 16);
2159         if (M.x86.R_DX == 0) {
2160                 CLEAR_FLAG(F_CF);
2161                 CLEAR_FLAG(F_OF);
2162     } else {
2163                 SET_FLAG(F_CF);
2164                 SET_FLAG(F_OF);
2165     }
2166 }
2167 
2168 /****************************************************************************
2169 REMARKS:
2170 Implements the MUL instruction and side effects.
2171 ****************************************************************************/
2172 void mul_long(u32 s)
2173 {
2174 #ifdef  __HAS_LONG_LONG__
2175         u64 res = (u64)M.x86.R_EAX * s;
2176 
2177         M.x86.R_EAX = (u32)res;
2178         M.x86.R_EDX = (u32)(res >> 32);
2179 #else
2180         u32     a,a_lo,a_hi;
2181         u32     s_lo,s_hi;
2182         u32     rlo_lo,rlo_hi,rhi_lo;
2183 
2184         a = M.x86.R_EAX;
2185         a_lo = a & 0xFFFF;
2186         a_hi = a >> 16;
2187         s_lo = s & 0xFFFF;
2188         s_hi = s >> 16;
2189         rlo_lo = a_lo * s_lo;
2190         rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2191         rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2192         M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2193         M.x86.R_EDX = rhi_lo;
2194 #endif
2195 
2196         if (M.x86.R_EDX == 0) {
2197                 CLEAR_FLAG(F_CF);
2198                 CLEAR_FLAG(F_OF);
2199         } else {
2200                 SET_FLAG(F_CF);
2201                 SET_FLAG(F_OF);
2202     }
2203 }
2204 
2205 /****************************************************************************
2206 REMARKS:
2207 Implements the IDIV instruction and side effects.
2208 ****************************************************************************/
2209 void idiv_byte(u8 s)
2210 {
2211     s32 dvd, div, mod;
2212 
2213         dvd = (s16)M.x86.R_AX;
2214         if (s == 0) {
2215                 x86emu_intr_raise(0);
2216         return;
2217         }
2218         div = dvd / (s8)s;
2219         mod = dvd % (s8)s;
2220         if (abs(div) > 0x7f) {
2221                 x86emu_intr_raise(0);
2222                 return;
2223         }
2224         M.x86.R_AL = (s8) div;
2225         M.x86.R_AH = (s8) mod;
2226 }
2227 
2228 /****************************************************************************
2229 REMARKS:
2230 Implements the IDIV instruction and side effects.
2231 ****************************************************************************/
2232 void idiv_word(u16 s)
2233 {
2234         s32 dvd, div, mod;
2235 
2236         dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2237         if (s == 0) {
2238                 x86emu_intr_raise(0);
2239                 return;
2240         }
2241         div = dvd / (s16)s;
2242         mod = dvd % (s16)s;
2243         if (abs(div) > 0x7fff) {
2244                 x86emu_intr_raise(0);
2245                 return;
2246         }
2247         CLEAR_FLAG(F_CF);
2248         CLEAR_FLAG(F_SF);
2249         CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2250         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2251 
2252         M.x86.R_AX = (u16)div;
2253         M.x86.R_DX = (u16)mod;
2254 }
2255 
2256 /****************************************************************************
2257 REMARKS:
2258 Implements the IDIV instruction and side effects.
2259 ****************************************************************************/
2260 void idiv_long(u32 s)
2261 {
2262 #ifdef  __HAS_LONG_LONG__
2263         s64 dvd, div, mod;
2264 
2265         dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2266         if (s == 0) {
2267                 x86emu_intr_raise(0);
2268                 return;
2269         }
2270         div = dvd / (s32)s;
2271         mod = dvd % (s32)s;
2272         if (((u64)div >> 32) != 0 &&
2273             ((u64)div >> 32) != 0xFFFFFFFFUL) {
2274                 x86emu_intr_raise(0);
2275                 return;
2276         }
2277 #else
2278         s32 div = 0, mod;
2279         s32 h_dvd = M.x86.R_EDX;
2280         u32 l_dvd = M.x86.R_EAX;
2281         u32 abs_s = s & 0x7FFFFFFF;
2282         u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2283         u32 h_s = abs_s >> 1;
2284         u32 l_s = abs_s << 31;
2285         int counter = 31;
2286         int carry;
2287 
2288         if (s == 0) {
2289                 x86emu_intr_raise(0);
2290                 return;
2291         }
2292         do {
2293                 div <<= 1;
2294                 carry = (l_dvd >= l_s) ? 0 : 1;
2295 
2296                 if (abs_h_dvd < (h_s + carry)) {
2297                         h_s >>= 1;
2298                         l_s = abs_s << (--counter);
2299                         continue;
2300                 } else {
2301                         abs_h_dvd -= (h_s + carry);
2302                         l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2303                                 : (l_dvd - l_s);
2304                         h_s >>= 1;
2305                         l_s = abs_s << (--counter);
2306                         div |= 1;
2307                         continue;
2308                 }
2309 
2310         } while (counter > -1);
2311         /* overflow */
2312         if (abs_h_dvd || (l_dvd > abs_s)) {
2313                 x86emu_intr_raise(0);
2314                 return;
2315         }
2316         /* sign */
2317         div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2318         mod = l_dvd;
2319 
2320 #endif
2321         CLEAR_FLAG(F_CF);
2322         CLEAR_FLAG(F_AF);
2323         CLEAR_FLAG(F_SF);
2324         SET_FLAG(F_ZF);
2325         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2326 
2327         M.x86.R_EAX = (u32)div;
2328         M.x86.R_EDX = (u32)mod;
2329 }
2330 
2331 /****************************************************************************
2332 REMARKS:
2333 Implements the DIV instruction and side effects.
2334 ****************************************************************************/
2335 void div_byte(u8 s)
2336 {
2337         u32 dvd, div, mod;
2338 
2339         dvd = M.x86.R_AX;
2340     if (s == 0) {
2341                 x86emu_intr_raise(0);
2342         return;
2343     }
2344         div = dvd / (u8)s;
2345         mod = dvd % (u8)s;
2346         if (div > 0xff) {
2347                 x86emu_intr_raise(0);
2348         return;
2349         }
2350         M.x86.R_AL = (u8)div;
2351         M.x86.R_AH = (u8)mod;
2352 }
2353 
2354 /****************************************************************************
2355 REMARKS:
2356 Implements the DIV instruction and side effects.
2357 ****************************************************************************/
2358 void div_word(u16 s)
2359 {
2360         u32 dvd, div, mod;
2361 
2362         dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2363         if (s == 0) {
2364                 x86emu_intr_raise(0);
2365         return;
2366     }
2367         div = dvd / (u16)s;
2368         mod = dvd % (u16)s;
2369         if (div > 0xffff) {
2370                 x86emu_intr_raise(0);
2371                 return;
2372         }
2373         CLEAR_FLAG(F_CF);
2374         CLEAR_FLAG(F_SF);
2375         CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2376         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2377 
2378         M.x86.R_AX = (u16)div;
2379         M.x86.R_DX = (u16)mod;
2380 }
2381 
2382 /****************************************************************************
2383 REMARKS:
2384 Implements the DIV instruction and side effects.
2385 ****************************************************************************/
2386 void div_long(u32 s)
2387 {
2388 #ifdef  __HAS_LONG_LONG__
2389         u64 dvd, div, mod;
2390 
2391         dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2392         if (s == 0) {
2393                 x86emu_intr_raise(0);
2394                 return;
2395         }
2396         div = dvd / (u32)s;
2397         mod = dvd % (u32)s;
2398         if (div > 0xffffffffULL) {
2399                 x86emu_intr_raise(0);
2400                 return;
2401         }
2402 #else
2403         s32 div = 0, mod;
2404         s32 h_dvd = M.x86.R_EDX;
2405         u32 l_dvd = M.x86.R_EAX;
2406 
2407         u32 h_s = s;
2408         u32 l_s = 0;
2409         int counter = 32;
2410         int carry;
2411 
2412         if (s == 0) {
2413                 x86emu_intr_raise(0);
2414                 return;
2415         }
2416         do {
2417                 div <<= 1;
2418                 carry = (l_dvd >= l_s) ? 0 : 1;
2419 
2420                 if (h_dvd < (h_s + carry)) {
2421                         h_s >>= 1;
2422                         l_s = s << (--counter);
2423                         continue;
2424                 } else {
2425                         h_dvd -= (h_s + carry);
2426                         l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2427                                 : (l_dvd - l_s);
2428                         h_s >>= 1;
2429                         l_s = s << (--counter);
2430                         div |= 1;
2431                         continue;
2432                 }
2433 
2434         } while (counter > -1);
2435         /* overflow */
2436         if (h_dvd || (l_dvd > s)) {
2437                 x86emu_intr_raise(0);
2438                 return;
2439         }
2440         mod = l_dvd;
2441 #endif
2442         CLEAR_FLAG(F_CF);
2443         CLEAR_FLAG(F_AF);
2444         CLEAR_FLAG(F_SF);
2445         SET_FLAG(F_ZF);
2446         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2447 
2448         M.x86.R_EAX = (u32)div;
2449         M.x86.R_EDX = (u32)mod;
2450 }
2451 
2452 /****************************************************************************
2453 REMARKS:
2454 Implements the IN string instruction and side effects.
2455 ****************************************************************************/
2456 void ins(int size)
2457 {
2458         int inc = size;
2459 
2460         if (ACCESS_FLAG(F_DF)) {
2461                 inc = -size;
2462         }
2463         if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2464         /* dont care whether REPE or REPNE */
2465         /* in until CX is ZERO. */
2466                 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2467                                          M.x86.R_ECX : M.x86.R_CX);
2468         switch (size) {
2469           case 1:
2470             while (count--) {
2471                                 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2472                                                                         (*sys_inb)(M.x86.R_DX));
2473                                 M.x86.R_DI += inc;
2474             }
2475             break;
2476 
2477           case 2:
2478             while (count--) {
2479                                 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2480                                                                         (*sys_inw)(M.x86.R_DX));
2481                                 M.x86.R_DI += inc;
2482             }
2483             break;
2484           case 4:
2485             while (count--) {
2486                                 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2487                                                                         (*sys_inl)(M.x86.R_DX));
2488                                 M.x86.R_DI += inc;
2489                 break;
2490             }
2491         }
2492                 M.x86.R_CX = 0;
2493                 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2494                         M.x86.R_ECX = 0;
2495         }
2496                 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2497     } else {
2498         switch (size) {
2499           case 1:
2500                         store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2501                                                                 (*sys_inb)(M.x86.R_DX));
2502             break;
2503           case 2:
2504                         store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2505                                                                 (*sys_inw)(M.x86.R_DX));
2506             break;
2507           case 4:
2508                         store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2509                                                                 (*sys_inl)(M.x86.R_DX));
2510             break;
2511         }
2512                 M.x86.R_DI += inc;
2513     }
2514 }
2515 
2516 /****************************************************************************
2517 REMARKS:
2518 Implements the OUT string instruction and side effects.
2519 ****************************************************************************/
2520 void outs(int size)
2521 {
2522     int inc = size;
2523 
2524         if (ACCESS_FLAG(F_DF)) {
2525         inc = -size;
2526     }
2527         if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2528         /* dont care whether REPE or REPNE */
2529         /* out until CX is ZERO. */
2530                 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2531                                          M.x86.R_ECX : M.x86.R_CX);
2532         switch (size) {
2533           case 1:
2534             while (count--) {
2535                                 (*sys_outb)(M.x86.R_DX,
2536                                                  fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2537                                 M.x86.R_SI += inc;
2538             }
2539             break;
2540 
2541           case 2:
2542             while (count--) {
2543                                 (*sys_outw)(M.x86.R_DX,
2544                                                  fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2545                                 M.x86.R_SI += inc;
2546             }
2547             break;
2548           case 4:
2549             while (count--) {
2550                                 (*sys_outl)(M.x86.R_DX,
2551                                                  fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2552                                 M.x86.R_SI += inc;
2553                 break;
2554             }
2555         }
2556                 M.x86.R_CX = 0;
2557                 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2558                         M.x86.R_ECX = 0;
2559         }
2560                 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2561     } else {
2562         switch (size) {
2563           case 1:
2564                         (*sys_outb)(M.x86.R_DX,
2565                                          fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2566             break;
2567           case 2:
2568                         (*sys_outw)(M.x86.R_DX,
2569                                          fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2570             break;
2571           case 4:
2572                         (*sys_outl)(M.x86.R_DX,
2573                                          fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2574             break;
2575         }
2576                 M.x86.R_SI += inc;
2577     }
2578 }
2579 
2580 /****************************************************************************
2581 PARAMETERS:
2582 addr    - Address to fetch word from
2583 
2584 REMARKS:
2585 Fetches a word from emulator memory using an absolute address.
2586 ****************************************************************************/
2587 u16 mem_access_word(int addr)
2588 {
2589 DB(     if (CHECK_MEM_ACCESS())
2590           x86emu_check_mem_access(addr);)
2591         return (*sys_rdw)(addr);
2592 }
2593 
2594 /****************************************************************************
2595 REMARKS:
2596 Pushes a word onto the stack.
2597 
2598 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2599 ****************************************************************************/
2600 void push_word(u16 w)
2601 {
2602 DB(     if (CHECK_SP_ACCESS())
2603           x86emu_check_sp_access();)
2604         M.x86.R_SP -= 2;
2605         (*sys_wrw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2606 }
2607 
2608 /****************************************************************************
2609 REMARKS:
2610 Pushes a long onto the stack.
2611 
2612 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2613 ****************************************************************************/
2614 void push_long(u32 w)
2615 {
2616 DB(     if (CHECK_SP_ACCESS())
2617           x86emu_check_sp_access();)
2618         M.x86.R_SP -= 4;
2619         (*sys_wrl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2620 }
2621 
2622 /****************************************************************************
2623 REMARKS:
2624 Pops a word from the stack.
2625 
2626 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2627 ****************************************************************************/
2628 u16 pop_word(void)
2629 {
2630         register u16 res;
2631 
2632 DB(     if (CHECK_SP_ACCESS())
2633           x86emu_check_sp_access();)
2634         res = (*sys_rdw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2635         M.x86.R_SP += 2;
2636         return res;
2637 }
2638 
2639 /****************************************************************************
2640 REMARKS:
2641 Pops a long from the stack.
2642 
2643 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2644 ****************************************************************************/
2645 u32 pop_long(void)
2646 {
2647     register u32 res;
2648 
2649 DB(     if (CHECK_SP_ACCESS())
2650           x86emu_check_sp_access();)
2651         res = (*sys_rdl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2652         M.x86.R_SP += 4;
2653     return res;
2654 }
2655 
2656