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