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