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 #include <common.h>
101 
102 #define PRIM_OPS_NO_REDEFINE_ASM
103 
104 #if defined(CONFIG_BIOSEMU)
105 
106 #include "x86emu/x86emui.h"
107 
108 /*------------------------- Global Variables ------------------------------*/
109 
110 static u32 x86emu_parity_tab[8] =
111 {
112     0x96696996,
113     0x69969669,
114     0x69969669,
115     0x96696996,
116     0x69969669,
117     0x96696996,
118     0x96696996,
119     0x69969669,
120 };
121 
122 #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
123 #define XOR2(x)	    (((x) ^ ((x)>>1)) & 0x1)
124 /*----------------------------- Implementation ----------------------------*/
125 int abs(int v)
126 {
127 	return (v>0)?v:-v;
128 }
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 = (s32)d * (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 = (u32)M.x86.R_EAX * (u32)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 CX is ZERO. */
2316 	u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2317 		     M.x86.R_ECX : M.x86.R_CX);
2318 
2319 	while (count--) {
2320 	  single_in(size);
2321 	  M.x86.R_DI += inc;
2322 	  }
2323 	M.x86.R_CX = 0;
2324 	if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2325 	    M.x86.R_ECX = 0;
2326 	}
2327 	M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2328     } else {
2329 	single_in(size);
2330 	M.x86.R_DI += inc;
2331     }
2332 }
2333 
2334 /****************************************************************************
2335 REMARKS:
2336 Implements the OUT string instruction and side effects.
2337 ****************************************************************************/
2338 
2339 static void single_out(int size)
2340 {
2341      if(size == 1)
2342        (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2343      else if (size == 2)
2344        (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2345      else
2346        (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2347 }
2348 
2349 void outs(int size)
2350 {
2351     int inc = size;
2352 
2353     if (ACCESS_FLAG(F_DF)) {
2354 	inc = -size;
2355     }
2356     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2357 	/* dont care whether REPE or REPNE */
2358 	/* out until CX is ZERO. */
2359 	u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2360 		     M.x86.R_ECX : M.x86.R_CX);
2361 	while (count--) {
2362 	  single_out(size);
2363 	  M.x86.R_SI += inc;
2364 	  }
2365 	M.x86.R_CX = 0;
2366 	if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2367 	    M.x86.R_ECX = 0;
2368 	}
2369 	M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2370     } else {
2371 	single_out(size);
2372 	M.x86.R_SI += inc;
2373     }
2374 }
2375 
2376 /****************************************************************************
2377 PARAMETERS:
2378 addr	- Address to fetch word from
2379 
2380 REMARKS:
2381 Fetches a word from emulator memory using an absolute address.
2382 ****************************************************************************/
2383 u16 mem_access_word(int addr)
2384 {
2385 DB( if (CHECK_MEM_ACCESS())
2386       x86emu_check_mem_access(addr);)
2387     return (*sys_rdw)(addr);
2388 }
2389 
2390 /****************************************************************************
2391 REMARKS:
2392 Pushes a word onto the stack.
2393 
2394 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2395 ****************************************************************************/
2396 void push_word(u16 w)
2397 {
2398 DB( if (CHECK_SP_ACCESS())
2399       x86emu_check_sp_access();)
2400     M.x86.R_SP -= 2;
2401     (*sys_wrw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2402 }
2403 
2404 /****************************************************************************
2405 REMARKS:
2406 Pushes a long onto the stack.
2407 
2408 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2409 ****************************************************************************/
2410 void push_long(u32 w)
2411 {
2412 DB( if (CHECK_SP_ACCESS())
2413       x86emu_check_sp_access();)
2414     M.x86.R_SP -= 4;
2415     (*sys_wrl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2416 }
2417 
2418 /****************************************************************************
2419 REMARKS:
2420 Pops a word from the stack.
2421 
2422 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2423 ****************************************************************************/
2424 u16 pop_word(void)
2425 {
2426     u16 res;
2427 
2428 DB( if (CHECK_SP_ACCESS())
2429       x86emu_check_sp_access();)
2430     res = (*sys_rdw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2431     M.x86.R_SP += 2;
2432     return res;
2433 }
2434 
2435 /****************************************************************************
2436 REMARKS:
2437 Pops a long from the stack.
2438 
2439 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2440 ****************************************************************************/
2441 u32 pop_long(void)
2442 {
2443     u32 res;
2444 
2445 DB( if (CHECK_SP_ACCESS())
2446       x86emu_check_sp_access();)
2447     res = (*sys_rdl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2448     M.x86.R_SP += 4;
2449     return res;
2450 }
2451 
2452 #endif
2453