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