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