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