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 
122 /*----------------------------- Implementation ----------------------------*/
123 
124 
125 /*--------- Side effects helper functions -------*/
126 
127 /****************************************************************************
128 REMARKS:
129 implements side efects for byte operations that don't overflow
130 ****************************************************************************/
131 
set_parity_flag(u32 res)132 static void set_parity_flag(u32 res)
133 {
134     CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
135 }
136 
set_szp_flags_8(u8 res)137 static 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 
set_szp_flags_16(u16 res)144 static 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 
set_szp_flags_32(u32 res)151 static 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 
no_carry_byte_side_eff(u8 res)158 static 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 
no_carry_word_side_eff(u16 res)166 static 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 
no_carry_long_side_eff(u32 res)174 static 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 
calc_carry_chain(int bits,u32 d,u32 s,u32 res,int set_carry)182 static 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 
calc_borrow_chain(int bits,u32 d,u32 s,u32 res,int set_carry)194 static 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 /****************************************************************************
207 REMARKS:
208 Implements the AAA instruction and side effects.
209 ****************************************************************************/
aaa_word(u16 d)210 u16 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 /****************************************************************************
228 REMARKS:
229 Implements the AAA instruction and side effects.
230 ****************************************************************************/
aas_word(u16 d)231 u16 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 /****************************************************************************
249 REMARKS:
250 Implements the AAD instruction and side effects.
251 ****************************************************************************/
aad_word(u16 d)252 u16 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 /****************************************************************************
266 REMARKS:
267 Implements the AAM instruction and side effects.
268 ****************************************************************************/
aam_word(u8 d)269 u16 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 /****************************************************************************
282 REMARKS:
283 Implements the ADC instruction and side effects.
284 ****************************************************************************/
adc_byte(u8 d,u8 s)285 u8 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 /****************************************************************************
299 REMARKS:
300 Implements the ADC instruction and side effects.
301 ****************************************************************************/
adc_word(u16 d,u16 s)302 u16 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 /****************************************************************************
317 REMARKS:
318 Implements the ADC instruction and side effects.
319 ****************************************************************************/
adc_long(u32 d,u32 s)320 u32 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 /****************************************************************************
345 REMARKS:
346 Implements the ADD instruction and side effects.
347 ****************************************************************************/
add_byte(u8 d,u8 s)348 u8 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 /****************************************************************************
360 REMARKS:
361 Implements the ADD instruction and side effects.
362 ****************************************************************************/
add_word(u16 d,u16 s)363 u16 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 /****************************************************************************
375 REMARKS:
376 Implements the ADD instruction and side effects.
377 ****************************************************************************/
add_long(u32 d,u32 s)378 u32 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 /****************************************************************************
392 REMARKS:
393 Implements the AND instruction and side effects.
394 ****************************************************************************/
and_byte(u8 d,u8 s)395 u8 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 /****************************************************************************
406 REMARKS:
407 Implements the AND instruction and side effects.
408 ****************************************************************************/
and_word(u16 d,u16 s)409 u16 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 /****************************************************************************
420 REMARKS:
421 Implements the AND instruction and side effects.
422 ****************************************************************************/
and_long(u32 d,u32 s)423 u32 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 /****************************************************************************
433 REMARKS:
434 Implements the CMP instruction and side effects.
435 ****************************************************************************/
cmp_byte(u8 d,u8 s)436 u8 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 /****************************************************************************
448 REMARKS:
449 Implements the CMP instruction and side effects.
450 ****************************************************************************/
cmp_word(u16 d,u16 s)451 u16 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 /****************************************************************************
463 REMARKS:
464 Implements the CMP instruction and side effects.
465 ****************************************************************************/
cmp_long(u32 d,u32 s)466 u32 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 /****************************************************************************
478 REMARKS:
479 Implements the DAA instruction and side effects.
480 ****************************************************************************/
daa_byte(u8 d)481 u8 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 /****************************************************************************
497 REMARKS:
498 Implements the DAS instruction and side effects.
499 ****************************************************************************/
das_byte(u8 d)500 u8 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 /****************************************************************************
515 REMARKS:
516 Implements the DEC instruction and side effects.
517 ****************************************************************************/
dec_byte(u8 d)518 u8 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 /****************************************************************************
530 REMARKS:
531 Implements the DEC instruction and side effects.
532 ****************************************************************************/
dec_word(u16 d)533 u16 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 /****************************************************************************
545 REMARKS:
546 Implements the DEC instruction and side effects.
547 ****************************************************************************/
dec_long(u32 d)548 u32 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 /****************************************************************************
561 REMARKS:
562 Implements the INC instruction and side effects.
563 ****************************************************************************/
inc_byte(u8 d)564 u8 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 /****************************************************************************
576 REMARKS:
577 Implements the INC instruction and side effects.
578 ****************************************************************************/
inc_word(u16 d)579 u16 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 /****************************************************************************
591 REMARKS:
592 Implements the INC instruction and side effects.
593 ****************************************************************************/
inc_long(u32 d)594 u32 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 /****************************************************************************
606 REMARKS:
607 Implements the OR instruction and side effects.
608 ****************************************************************************/
or_byte(u8 d,u8 s)609 u8 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 /****************************************************************************
620 REMARKS:
621 Implements the OR instruction and side effects.
622 ****************************************************************************/
or_word(u16 d,u16 s)623 u16 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 /****************************************************************************
633 REMARKS:
634 Implements the OR instruction and side effects.
635 ****************************************************************************/
or_long(u32 d,u32 s)636 u32 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 /****************************************************************************
646 REMARKS:
647 Implements the OR instruction and side effects.
648 ****************************************************************************/
neg_byte(u8 s)649 u8 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 /****************************************************************************
662 REMARKS:
663 Implements the OR instruction and side effects.
664 ****************************************************************************/
neg_word(u16 s)665 u16 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 /****************************************************************************
678 REMARKS:
679 Implements the OR instruction and side effects.
680 ****************************************************************************/
neg_long(u32 s)681 u32 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 /****************************************************************************
694 REMARKS:
695 Implements the NOT instruction and side effects.
696 ****************************************************************************/
not_byte(u8 s)697 u8 not_byte(u8 s)
698 {
699     return ~s;
700 }
701 
702 /****************************************************************************
703 REMARKS:
704 Implements the NOT instruction and side effects.
705 ****************************************************************************/
not_word(u16 s)706 u16 not_word(u16 s)
707 {
708     return ~s;
709 }
710 
711 /****************************************************************************
712 REMARKS:
713 Implements the NOT instruction and side effects.
714 ****************************************************************************/
not_long(u32 s)715 u32 not_long(u32 s)
716 {
717     return ~s;
718 }
719 
720 /****************************************************************************
721 REMARKS:
722 Implements the RCL instruction and side effects.
723 ****************************************************************************/
rcl_byte(u8 d,u8 s)724 u8 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 /****************************************************************************
794 REMARKS:
795 Implements the RCL instruction and side effects.
796 ****************************************************************************/
rcl_word(u16 d,u8 s)797 u16 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 /****************************************************************************
818 REMARKS:
819 Implements the RCL instruction and side effects.
820 ****************************************************************************/
rcl_long(u32 d,u8 s)821 u32 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 /****************************************************************************
842 REMARKS:
843 Implements the RCR instruction and side effects.
844 ****************************************************************************/
rcr_byte(u8 d,u8 s)845 u8 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 /****************************************************************************
926 REMARKS:
927 Implements the RCR instruction and side effects.
928 ****************************************************************************/
rcr_word(u16 d,u8 s)929 u16 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 /****************************************************************************
958 REMARKS:
959 Implements the RCR instruction and side effects.
960 ****************************************************************************/
rcr_long(u32 d,u8 s)961 u32 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 /****************************************************************************
991 REMARKS:
992 Implements the ROL instruction and side effects.
993 ****************************************************************************/
rol_byte(u8 d,u8 s)994 u8 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 /****************************************************************************
1040 REMARKS:
1041 Implements the ROL instruction and side effects.
1042 ****************************************************************************/
rol_word(u16 d,u8 s)1043 u16 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 /****************************************************************************
1065 REMARKS:
1066 Implements the ROL instruction and side effects.
1067 ****************************************************************************/
rol_long(u32 d,u8 s)1068 u32 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 /****************************************************************************
1090 REMARKS:
1091 Implements the ROR instruction and side effects.
1092 ****************************************************************************/
ror_byte(u8 d,u8 s)1093 u8 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 /****************************************************************************
1136 REMARKS:
1137 Implements the ROR instruction and side effects.
1138 ****************************************************************************/
ror_word(u16 d,u8 s)1139 u16 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 /****************************************************************************
1159 REMARKS:
1160 Implements the ROR instruction and side effects.
1161 ****************************************************************************/
ror_long(u32 d,u8 s)1162 u32 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 /****************************************************************************
1182 REMARKS:
1183 Implements the SHL instruction and side effects.
1184 ****************************************************************************/
shl_byte(u8 d,u8 s)1185 u8 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 /****************************************************************************
1224 REMARKS:
1225 Implements the SHL instruction and side effects.
1226 ****************************************************************************/
shl_word(u16 d,u8 s)1227 u16 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 /****************************************************************************
1262 REMARKS:
1263 Implements the SHL instruction and side effects.
1264 ****************************************************************************/
shl_long(u32 d,u8 s)1265 u32 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 /****************************************************************************
1297 REMARKS:
1298 Implements the SHR instruction and side effects.
1299 ****************************************************************************/
shr_byte(u8 d,u8 s)1300 u8 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 /****************************************************************************
1332 REMARKS:
1333 Implements the SHR instruction and side effects.
1334 ****************************************************************************/
shr_word(u16 d,u8 s)1335 u16 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 /****************************************************************************
1367 REMARKS:
1368 Implements the SHR instruction and side effects.
1369 ****************************************************************************/
shr_long(u32 d,u8 s)1370 u32 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 /****************************************************************************
1401 REMARKS:
1402 Implements the SAR instruction and side effects.
1403 ****************************************************************************/
sar_byte(u8 d,u8 s)1404 u8 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 /****************************************************************************
1439 REMARKS:
1440 Implements the SAR instruction and side effects.
1441 ****************************************************************************/
sar_word(u16 d,u8 s)1442 u16 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 /****************************************************************************
1477 REMARKS:
1478 Implements the SAR instruction and side effects.
1479 ****************************************************************************/
sar_long(u32 d,u8 s)1480 u32 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 /****************************************************************************
1515 REMARKS:
1516 Implements the SHLD instruction and side effects.
1517 ****************************************************************************/
shld_word(u16 d,u16 fill,u8 s)1518 u16 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 /****************************************************************************
1550 REMARKS:
1551 Implements the SHLD instruction and side effects.
1552 ****************************************************************************/
shld_long(u32 d,u32 fill,u8 s)1553 u32 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 /****************************************************************************
1585 REMARKS:
1586 Implements the SHRD instruction and side effects.
1587 ****************************************************************************/
shrd_word(u16 d,u16 fill,u8 s)1588 u16 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 /****************************************************************************
1620 REMARKS:
1621 Implements the SHRD instruction and side effects.
1622 ****************************************************************************/
shrd_long(u32 d,u32 fill,u8 s)1623 u32 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 /****************************************************************************
1654 REMARKS:
1655 Implements the SBB instruction and side effects.
1656 ****************************************************************************/
sbb_byte(u8 d,u8 s)1657 u8 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 /****************************************************************************
1677 REMARKS:
1678 Implements the SBB instruction and side effects.
1679 ****************************************************************************/
sbb_word(u16 d,u16 s)1680 u16 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 /****************************************************************************
1700 REMARKS:
1701 Implements the SBB instruction and side effects.
1702 ****************************************************************************/
sbb_long(u32 d,u32 s)1703 u32 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 /****************************************************************************
1724 REMARKS:
1725 Implements the SUB instruction and side effects.
1726 ****************************************************************************/
sub_byte(u8 d,u8 s)1727 u8 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 /****************************************************************************
1744 REMARKS:
1745 Implements the SUB instruction and side effects.
1746 ****************************************************************************/
sub_word(u16 d,u16 s)1747 u16 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 /****************************************************************************
1764 REMARKS:
1765 Implements the SUB instruction and side effects.
1766 ****************************************************************************/
sub_long(u32 d,u32 s)1767 u32 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 /****************************************************************************
1784 REMARKS:
1785 Implements the TEST instruction and side effects.
1786 ****************************************************************************/
test_byte(u8 d,u8 s)1787 void 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 /****************************************************************************
1800 REMARKS:
1801 Implements the TEST instruction and side effects.
1802 ****************************************************************************/
test_word(u16 d,u16 s)1803 void 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 /****************************************************************************
1816 REMARKS:
1817 Implements the TEST instruction and side effects.
1818 ****************************************************************************/
test_long(u32 d,u32 s)1819 void 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 /****************************************************************************
1832 REMARKS:
1833 Implements the XOR instruction and side effects.
1834 ****************************************************************************/
xor_byte(u8 d,u8 s)1835 u8 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 /****************************************************************************
1845 REMARKS:
1846 Implements the XOR instruction and side effects.
1847 ****************************************************************************/
xor_word(u16 d,u16 s)1848 u16 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 /****************************************************************************
1858 REMARKS:
1859 Implements the XOR instruction and side effects.
1860 ****************************************************************************/
xor_long(u32 d,u32 s)1861 u32 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 /****************************************************************************
1871 REMARKS:
1872 Implements the IMUL instruction and side effects.
1873 ****************************************************************************/
imul_byte(u8 s)1874 void 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 /****************************************************************************
1890 REMARKS:
1891 Implements the IMUL instruction and side effects.
1892 ****************************************************************************/
imul_word(u16 s)1893 void 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 /****************************************************************************
1910 REMARKS:
1911 Implements the IMUL instruction and side effects.
1912 ****************************************************************************/
imul_long_direct(u32 * res_lo,u32 * res_hi,u32 d,u32 s)1913 void 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 /****************************************************************************
1948 REMARKS:
1949 Implements the IMUL instruction and side effects.
1950 ****************************************************************************/
imul_long(u32 s)1951 void 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 /****************************************************************************
1965 REMARKS:
1966 Implements the MUL instruction and side effects.
1967 ****************************************************************************/
mul_byte(u8 s)1968 void 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 /****************************************************************************
1983 REMARKS:
1984 Implements the MUL instruction and side effects.
1985 ****************************************************************************/
mul_word(u16 s)1986 void 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 /****************************************************************************
2002 REMARKS:
2003 Implements the MUL instruction and side effects.
2004 ****************************************************************************/
mul_long(u32 s)2005 void 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 /****************************************************************************
2038 REMARKS:
2039 Implements the IDIV instruction and side effects.
2040 ****************************************************************************/
idiv_byte(u8 s)2041 void 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 /****************************************************************************
2061 REMARKS:
2062 Implements the IDIV instruction and side effects.
2063 ****************************************************************************/
idiv_word(u16 s)2064 void 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 /****************************************************************************
2089 REMARKS:
2090 Implements the IDIV instruction and side effects.
2091 ****************************************************************************/
idiv_long(u32 s)2092 void 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 /****************************************************************************
2163 REMARKS:
2164 Implements the DIV instruction and side effects.
2165 ****************************************************************************/
div_byte(u8 s)2166 void 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 /****************************************************************************
2186 REMARKS:
2187 Implements the DIV instruction and side effects.
2188 ****************************************************************************/
div_word(u16 s)2189 void 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 /****************************************************************************
2214 REMARKS:
2215 Implements the DIV instruction and side effects.
2216 ****************************************************************************/
div_long(u32 s)2217 void 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 /****************************************************************************
2284 REMARKS:
2285 Implements the IN string instruction and side effects.
2286 ****************************************************************************/
2287 
single_in(int size)2288 static 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 
ins(int size)2298 void 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 /****************************************************************************
2327 REMARKS:
2328 Implements the OUT string instruction and side effects.
2329 ****************************************************************************/
2330 
single_out(int size)2331 static 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 
outs(int size)2341 void 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 /****************************************************************************
2369 PARAMETERS:
2370 addr	- Address to fetch word from
2371 
2372 REMARKS:
2373 Fetches a word from emulator memory using an absolute address.
2374 ****************************************************************************/
mem_access_word(int addr)2375 u16 mem_access_word(int addr)
2376 {
2377 DB( if (CHECK_MEM_ACCESS())
2378       x86emu_check_mem_access(addr);)
2379     return (*sys_rdw)(addr);
2380 }
2381 
2382 /****************************************************************************
2383 REMARKS:
2384 Pushes a word onto the stack.
2385 
2386 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2387 ****************************************************************************/
push_word(u16 w)2388 void push_word(u16 w)
2389 {
2390 DB( 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 /****************************************************************************
2397 REMARKS:
2398 Pushes a long onto the stack.
2399 
2400 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2401 ****************************************************************************/
push_long(u32 w)2402 void push_long(u32 w)
2403 {
2404 DB( 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 /****************************************************************************
2411 REMARKS:
2412 Pops a word from the stack.
2413 
2414 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2415 ****************************************************************************/
pop_word(void)2416 u16 pop_word(void)
2417 {
2418     u16 res;
2419 
2420 DB( 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 /****************************************************************************
2428 REMARKS:
2429 Pops a long from the stack.
2430 
2431 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2432 ****************************************************************************/
pop_long(void)2433 u32 pop_long(void)
2434 {
2435     u32 res;
2436 
2437 DB( 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