1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1991-2004 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
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.
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.
29 * ========================================================================
33 * Developer: Kendall Bennett
35 * Description: This file contains the code to implement the primitive
36 * machine operations used by the emulation code in ops.c
38 * Carry Chain Calculation
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.
48 * So, given the following table, which represents the addition of two
49 * bits, we can derive a formula for the carry chain.
61 * Construction of table for cout:
69 * By inspection, one gets: cc = ab + r'(a + b)
71 * That represents alot of operations, but NO CHOICE....
73 * Borrow Chain Calculation.
75 * The following table represents the subtraction of two bits, from
76 * which we can derive a formula for the borrow chain.
88 * Construction of table for cout:
96 * By inspection, one gets: bc = a'b + r(a' + b)
98 ****************************************************************************/
100 #define PRIM_OPS_NO_REDEFINE_ASM
101 #include "x86emu/x86emui.h"
103 /*------------------------- Global Variables ------------------------------*/
105 static u32 x86emu_parity_tab[8] =
117 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
118 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
119 /*----------------------------- Implementation ----------------------------*/
125 /*----------------------------- Implementation ----------------------------*/
128 /*--------- Side effects helper functions -------*/
130 /****************************************************************************
132 implements side efects for byte operations that don't overflow
133 ****************************************************************************/
135 static void set_parity_flag(u32 res)
137 CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
140 static void set_szp_flags_8(u8 res)
142 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
143 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
144 set_parity_flag(res);
147 static void set_szp_flags_16(u16 res)
149 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
150 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
151 set_parity_flag(res);
154 static void set_szp_flags_32(u32 res)
156 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
157 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
158 set_parity_flag(res);
161 static void no_carry_byte_side_eff(u8 res)
166 set_szp_flags_8(res);
169 static void no_carry_word_side_eff(u16 res)
174 set_szp_flags_16(res);
177 static void no_carry_long_side_eff(u32 res)
182 set_szp_flags_32(res);
185 static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
189 cc = (s & d) | ((~res) & (s | d));
190 CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
191 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
193 CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
197 static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
201 bc = (res & (~d | s)) | (~d & s);
202 CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
203 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
205 CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
209 /****************************************************************************
211 Implements the AAA instruction and side effects.
212 ****************************************************************************/
216 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
225 res = (u16)(d & 0xFF0F);
226 set_szp_flags_16(res);
230 /****************************************************************************
232 Implements the AAA instruction and side effects.
233 ****************************************************************************/
237 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
246 res = (u16)(d & 0xFF0F);
247 set_szp_flags_16(res);
251 /****************************************************************************
253 Implements the AAD instruction and side effects.
254 ****************************************************************************/
260 hb = (u8)((d >> 8) & 0xff);
261 lb = (u8)((d & 0xff));
262 l = (u16)((lb + 10 * hb) & 0xFF);
264 no_carry_byte_side_eff(l & 0xFF);
268 /****************************************************************************
270 Implements the AAM instruction and side effects.
271 ****************************************************************************/
280 no_carry_byte_side_eff(l & 0xFF);
284 /****************************************************************************
286 Implements the ADC instruction and side effects.
287 ****************************************************************************/
288 u8 adc_byte(u8 d, u8 s)
290 u32 res; /* all operands in native machine order */
293 if (ACCESS_FLAG(F_CF)) res++;
295 set_szp_flags_8(res);
296 calc_carry_chain(8,s,d,res,1);
301 /****************************************************************************
303 Implements the ADC instruction and side effects.
304 ****************************************************************************/
305 u16 adc_word(u16 d, u16 s)
307 u32 res; /* all operands in native machine order */
310 if (ACCESS_FLAG(F_CF))
313 set_szp_flags_16((u16)res);
314 calc_carry_chain(16,s,d,res,1);
319 /****************************************************************************
321 Implements the ADC instruction and side effects.
322 ****************************************************************************/
323 u32 adc_long(u32 d, u32 s)
325 u32 lo; /* all operands in native machine order */
329 lo = (d & 0xFFFF) + (s & 0xFFFF);
332 if (ACCESS_FLAG(F_CF)) {
337 hi = (lo >> 16) + (d >> 16) + (s >> 16);
339 set_szp_flags_32(res);
340 calc_carry_chain(32,s,d,res,0);
342 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
347 /****************************************************************************
349 Implements the ADD instruction and side effects.
350 ****************************************************************************/
351 u8 add_byte(u8 d, u8 s)
353 u32 res; /* all operands in native machine order */
356 set_szp_flags_8((u8)res);
357 calc_carry_chain(8,s,d,res,1);
362 /****************************************************************************
364 Implements the ADD instruction and side effects.
365 ****************************************************************************/
366 u16 add_word(u16 d, u16 s)
368 u32 res; /* all operands in native machine order */
371 set_szp_flags_16((u16)res);
372 calc_carry_chain(16,s,d,res,1);
377 /****************************************************************************
379 Implements the ADD instruction and side effects.
380 ****************************************************************************/
381 u32 add_long(u32 d, u32 s)
386 set_szp_flags_32(res);
387 calc_carry_chain(32,s,d,res,0);
389 CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
394 /****************************************************************************
396 Implements the AND instruction and side effects.
397 ****************************************************************************/
398 u8 and_byte(u8 d, u8 s)
400 u8 res; /* all operands in native machine order */
404 no_carry_byte_side_eff(res);
408 /****************************************************************************
410 Implements the AND instruction and side effects.
411 ****************************************************************************/
412 u16 and_word(u16 d, u16 s)
414 u16 res; /* all operands in native machine order */
418 no_carry_word_side_eff(res);
422 /****************************************************************************
424 Implements the AND instruction and side effects.
425 ****************************************************************************/
426 u32 and_long(u32 d, u32 s)
428 u32 res; /* all operands in native machine order */
431 no_carry_long_side_eff(res);
435 /****************************************************************************
437 Implements the CMP instruction and side effects.
438 ****************************************************************************/
439 u8 cmp_byte(u8 d, u8 s)
441 u32 res; /* all operands in native machine order */
444 set_szp_flags_8((u8)res);
445 calc_borrow_chain(8, d, s, res, 1);
450 /****************************************************************************
452 Implements the CMP instruction and side effects.
453 ****************************************************************************/
454 u16 cmp_word(u16 d, u16 s)
456 u32 res; /* all operands in native machine order */
459 set_szp_flags_16((u16)res);
460 calc_borrow_chain(16, d, s, res, 1);
465 /****************************************************************************
467 Implements the CMP instruction and side effects.
468 ****************************************************************************/
469 u32 cmp_long(u32 d, u32 s)
471 u32 res; /* all operands in native machine order */
474 set_szp_flags_32(res);
475 calc_borrow_chain(32, d, s, res, 1);
480 /****************************************************************************
482 Implements the DAA instruction and side effects.
483 ****************************************************************************/
487 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
491 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
495 set_szp_flags_8((u8)res);
499 /****************************************************************************
501 Implements the DAS instruction and side effects.
502 ****************************************************************************/
505 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
509 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
517 /****************************************************************************
519 Implements the DEC instruction and side effects.
520 ****************************************************************************/
523 u32 res; /* all operands in native machine order */
526 set_szp_flags_8((u8)res);
527 calc_borrow_chain(8, d, 1, res, 0);
532 /****************************************************************************
534 Implements the DEC instruction and side effects.
535 ****************************************************************************/
538 u32 res; /* all operands in native machine order */
541 set_szp_flags_16((u16)res);
542 calc_borrow_chain(16, d, 1, res, 0);
547 /****************************************************************************
549 Implements the DEC instruction and side effects.
550 ****************************************************************************/
553 u32 res; /* all operands in native machine order */
557 set_szp_flags_32(res);
558 calc_borrow_chain(32, d, 1, res, 0);
563 /****************************************************************************
565 Implements the INC instruction and side effects.
566 ****************************************************************************/
569 u32 res; /* all operands in native machine order */
572 set_szp_flags_8((u8)res);
573 calc_carry_chain(8, d, 1, res, 0);
578 /****************************************************************************
580 Implements the INC instruction and side effects.
581 ****************************************************************************/
584 u32 res; /* all operands in native machine order */
587 set_szp_flags_16((u16)res);
588 calc_carry_chain(16, d, 1, res, 0);
593 /****************************************************************************
595 Implements the INC instruction and side effects.
596 ****************************************************************************/
599 u32 res; /* all operands in native machine order */
602 set_szp_flags_32(res);
603 calc_carry_chain(32, d, 1, res, 0);
608 /****************************************************************************
610 Implements the OR instruction and side effects.
611 ****************************************************************************/
612 u8 or_byte(u8 d, u8 s)
614 u8 res; /* all operands in native machine order */
617 no_carry_byte_side_eff(res);
622 /****************************************************************************
624 Implements the OR instruction and side effects.
625 ****************************************************************************/
626 u16 or_word(u16 d, u16 s)
628 u16 res; /* all operands in native machine order */
631 no_carry_word_side_eff(res);
635 /****************************************************************************
637 Implements the OR instruction and side effects.
638 ****************************************************************************/
639 u32 or_long(u32 d, u32 s)
641 u32 res; /* all operands in native machine order */
644 no_carry_long_side_eff(res);
648 /****************************************************************************
650 Implements the OR instruction and side effects.
651 ****************************************************************************/
656 CONDITIONAL_SET_FLAG(s != 0, F_CF);
658 set_szp_flags_8(res);
659 calc_borrow_chain(8, 0, s, res, 0);
664 /****************************************************************************
666 Implements the OR instruction and side effects.
667 ****************************************************************************/
672 CONDITIONAL_SET_FLAG(s != 0, F_CF);
674 set_szp_flags_16((u16)res);
675 calc_borrow_chain(16, 0, s, res, 0);
680 /****************************************************************************
682 Implements the OR instruction and side effects.
683 ****************************************************************************/
688 CONDITIONAL_SET_FLAG(s != 0, F_CF);
690 set_szp_flags_32(res);
691 calc_borrow_chain(32, 0, s, res, 0);
696 /****************************************************************************
698 Implements the NOT instruction and side effects.
699 ****************************************************************************/
705 /****************************************************************************
707 Implements the NOT instruction and side effects.
708 ****************************************************************************/
714 /****************************************************************************
716 Implements the NOT instruction and side effects.
717 ****************************************************************************/
723 /****************************************************************************
725 Implements the RCL instruction and side effects.
726 ****************************************************************************/
727 u8 rcl_byte(u8 d, u8 s)
729 unsigned int res, cnt, mask, cf;
731 /* s is the rotate distance. It varies from 0 - 8. */
734 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
736 want to rotate through the carry by "s" bits. We could
737 loop, but that's inefficient. So the width is 9,
738 and we split into three parts:
740 The new carry flag (was B_n)
741 the stuff in B_n-1 .. B_0
742 the stuff in B_7 .. B_n+1
744 The new rotate is done mod 9, and given this,
745 for a rotation of n bits (mod 9) the new carry flag is
746 then located n bits from the MSB. The low part is
747 then shifted up cnt bits, and the high part is or'd
748 in. Using CAPS for new values, and lowercase for the
749 original values, this can be expressed as:
753 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
755 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
758 if ((cnt = s % 9) != 0) {
759 /* extract the new CARRY FLAG. */
761 cf = (d >> (8 - cnt)) & 0x1;
763 /* get the low stuff which rotated
764 into the range B_7 .. B_cnt */
765 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
766 /* note that the right hand side done by the mask */
767 res = (d << cnt) & 0xff;
769 /* now the high stuff which rotated around
770 into the positions B_cnt-2 .. B_0 */
771 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
772 /* shift it downward, 7-(n-2) = 9-n positions.
773 and mask off the result before or'ing in.
775 mask = (1 << (cnt - 1)) - 1;
776 res |= (d >> (9 - cnt)) & mask;
778 /* if the carry flag was set, or it in. */
779 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
781 res |= 1 << (cnt - 1);
783 /* set the new carry flag, based on the variable "cf" */
784 CONDITIONAL_SET_FLAG(cf, F_CF);
785 /* OVERFLOW is set *IFF* cnt==1, then it is the
786 xor of CF and the most significant bit. Blecck. */
787 /* parenthesized this expression since it appears to
788 be causing OF to be misset */
789 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
796 /****************************************************************************
798 Implements the RCL instruction and side effects.
799 ****************************************************************************/
800 u16 rcl_word(u16 d, u8 s)
802 unsigned int res, cnt, mask, cf;
805 if ((cnt = s % 17) != 0) {
806 cf = (d >> (16 - cnt)) & 0x1;
807 res = (d << cnt) & 0xffff;
808 mask = (1 << (cnt - 1)) - 1;
809 res |= (d >> (17 - cnt)) & mask;
810 if (ACCESS_FLAG(F_CF)) {
811 res |= 1 << (cnt - 1);
813 CONDITIONAL_SET_FLAG(cf, F_CF);
814 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
820 /****************************************************************************
822 Implements the RCL instruction and side effects.
823 ****************************************************************************/
824 u32 rcl_long(u32 d, u8 s)
826 u32 res, cnt, mask, cf;
829 if ((cnt = s % 33) != 0) {
830 cf = (d >> (32 - cnt)) & 0x1;
831 res = (d << cnt) & 0xffffffff;
832 mask = (1 << (cnt - 1)) - 1;
833 res |= (d >> (33 - cnt)) & mask;
834 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
835 res |= 1 << (cnt - 1);
837 CONDITIONAL_SET_FLAG(cf, F_CF);
838 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
844 /****************************************************************************
846 Implements the RCR instruction and side effects.
847 ****************************************************************************/
848 u8 rcr_byte(u8 d, u8 s)
851 u32 mask, cf, ocf = 0;
853 /* rotate right through carry */
855 s is the rotate distance. It varies from 0 - 8.
856 d is the byte object rotated.
860 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
862 The new rotate is done mod 9, and given this,
863 for a rotation of n bits (mod 9) the new carry flag is
864 then located n bits from the LSB. The low part is
865 then shifted up cnt bits, and the high part is or'd
866 in. Using CAPS for new values, and lowercase for the
867 original values, this can be expressed as:
871 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
873 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
876 if ((cnt = s % 9) != 0) {
877 /* extract the new CARRY FLAG. */
881 /* note hackery here. Access_flag(..) evaluates to either
883 non-zero if flag is set.
884 doing access_flag(..) != 0 casts that into either
885 0..1 in any representation of the flags register
886 (i.e. packed bit array or unpacked.)
888 ocf = ACCESS_FLAG(F_CF) != 0;
890 cf = (d >> (cnt - 1)) & 0x1;
892 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
893 /* note that the right hand side done by the mask
894 This is effectively done by shifting the
895 object to the right. The result must be masked,
896 in case the object came in and was treated
897 as a negative number. Needed??? */
899 mask = (1 << (8 - cnt)) - 1;
900 res = (d >> cnt) & mask;
902 /* now the high stuff which rotated around
903 into the positions B_cnt-2 .. B_0 */
904 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
905 /* shift it downward, 7-(n-2) = 9-n positions.
906 and mask off the result before or'ing in.
908 res |= (d << (9 - cnt));
910 /* if the carry flag was set, or it in. */
911 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
913 res |= 1 << (8 - cnt);
915 /* set the new carry flag, based on the variable "cf" */
916 CONDITIONAL_SET_FLAG(cf, F_CF);
917 /* OVERFLOW is set *IFF* cnt==1, then it is the
918 xor of CF and the most significant bit. Blecck. */
919 /* parenthesized... */
921 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
928 /****************************************************************************
930 Implements the RCR instruction and side effects.
931 ****************************************************************************/
932 u16 rcr_word(u16 d, u8 s)
935 u32 mask, cf, ocf = 0;
937 /* rotate right through carry */
939 if ((cnt = s % 17) != 0) {
942 ocf = ACCESS_FLAG(F_CF) != 0;
944 cf = (d >> (cnt - 1)) & 0x1;
945 mask = (1 << (16 - cnt)) - 1;
946 res = (d >> cnt) & mask;
947 res |= (d << (17 - cnt));
948 if (ACCESS_FLAG(F_CF)) {
949 res |= 1 << (16 - cnt);
951 CONDITIONAL_SET_FLAG(cf, F_CF);
953 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
960 /****************************************************************************
962 Implements the RCR instruction and side effects.
963 ****************************************************************************/
964 u32 rcr_long(u32 d, u8 s)
967 u32 mask, cf, ocf = 0;
969 /* rotate right through carry */
971 if ((cnt = s % 33) != 0) {
974 ocf = ACCESS_FLAG(F_CF) != 0;
976 cf = (d >> (cnt - 1)) & 0x1;
977 mask = (1 << (32 - cnt)) - 1;
978 res = (d >> cnt) & mask;
980 res |= (d << (33 - cnt));
981 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
982 res |= 1 << (32 - cnt);
984 CONDITIONAL_SET_FLAG(cf, F_CF);
986 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
993 /****************************************************************************
995 Implements the ROL instruction and side effects.
996 ****************************************************************************/
997 u8 rol_byte(u8 d, u8 s)
999 unsigned int res, cnt, mask;
1003 s is the rotate distance. It varies from 0 - 8.
1004 d is the byte object rotated.
1010 The new rotate is done mod 8.
1011 Much simpler than the "rcl" or "rcr" operations.
1014 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1015 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1018 if ((cnt = s % 8) != 0) {
1019 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1022 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1023 mask = (1 << cnt) - 1;
1024 res |= (d >> (8 - cnt)) & mask;
1026 /* set the new carry flag, Note that it is the low order
1027 bit of the result!!! */
1028 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1029 /* OVERFLOW is set *IFF* s==1, then it is the
1030 xor of CF and the most significant bit. Blecck. */
1031 CONDITIONAL_SET_FLAG(s == 1 &&
1032 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1035 /* set the new carry flag, Note that it is the low order
1036 bit of the result!!! */
1037 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1042 /****************************************************************************
1044 Implements the ROL instruction and side effects.
1045 ****************************************************************************/
1046 u16 rol_word(u16 d, u8 s)
1048 unsigned int res, cnt, mask;
1051 if ((cnt = s % 16) != 0) {
1053 mask = (1 << cnt) - 1;
1054 res |= (d >> (16 - cnt)) & mask;
1055 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1056 CONDITIONAL_SET_FLAG(s == 1 &&
1057 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1060 /* set the new carry flag, Note that it is the low order
1061 bit of the result!!! */
1062 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1067 /****************************************************************************
1069 Implements the ROL instruction and side effects.
1070 ****************************************************************************/
1071 u32 rol_long(u32 d, u8 s)
1076 if ((cnt = s % 32) != 0) {
1078 mask = (1 << cnt) - 1;
1079 res |= (d >> (32 - cnt)) & mask;
1080 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1081 CONDITIONAL_SET_FLAG(s == 1 &&
1082 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1085 /* set the new carry flag, Note that it is the low order
1086 bit of the result!!! */
1087 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1092 /****************************************************************************
1094 Implements the ROR instruction and side effects.
1095 ****************************************************************************/
1096 u8 ror_byte(u8 d, u8 s)
1098 unsigned int res, cnt, mask;
1102 s is the rotate distance. It varies from 0 - 8.
1103 d is the byte object rotated.
1109 The rotate is done mod 8.
1112 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1113 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1116 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
1117 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1118 res = (d << (8 - cnt));
1120 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1121 mask = (1 << (8 - cnt)) - 1;
1122 res |= (d >> (cnt)) & mask;
1124 /* set the new carry flag, Note that it is the low order
1125 bit of the result!!! */
1126 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1127 /* OVERFLOW is set *IFF* s==1, then it is the
1128 xor of the two most significant bits. Blecck. */
1129 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1130 } else if (s != 0) {
1131 /* set the new carry flag, Note that it is the low order
1132 bit of the result!!! */
1133 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1138 /****************************************************************************
1140 Implements the ROR instruction and side effects.
1141 ****************************************************************************/
1142 u16 ror_word(u16 d, u8 s)
1144 unsigned int res, cnt, mask;
1147 if ((cnt = s % 16) != 0) {
1148 res = (d << (16 - cnt));
1149 mask = (1 << (16 - cnt)) - 1;
1150 res |= (d >> (cnt)) & mask;
1151 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1152 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1153 } else if (s != 0) {
1154 /* set the new carry flag, Note that it is the low order
1155 bit of the result!!! */
1156 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1161 /****************************************************************************
1163 Implements the ROR instruction and side effects.
1164 ****************************************************************************/
1165 u32 ror_long(u32 d, u8 s)
1170 if ((cnt = s % 32) != 0) {
1171 res = (d << (32 - cnt));
1172 mask = (1 << (32 - cnt)) - 1;
1173 res |= (d >> (cnt)) & mask;
1174 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1175 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1176 } else if (s != 0) {
1177 /* set the new carry flag, Note that it is the low order
1178 bit of the result!!! */
1179 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1184 /****************************************************************************
1186 Implements the SHL instruction and side effects.
1187 ****************************************************************************/
1188 u8 shl_byte(u8 d, u8 s)
1190 unsigned int cnt, res, cf;
1195 /* last bit shifted out goes into carry flag */
1198 cf = d & (1 << (8 - cnt));
1199 CONDITIONAL_SET_FLAG(cf, F_CF);
1200 set_szp_flags_8((u8)res);
1206 /* Needs simplification. */
1207 CONDITIONAL_SET_FLAG(
1208 (((res & 0x80) == 0x80) ^
1209 (ACCESS_FLAG(F_CF) != 0)),
1210 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1217 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1226 /****************************************************************************
1228 Implements the SHL instruction and side effects.
1229 ****************************************************************************/
1230 u16 shl_word(u16 d, u8 s)
1232 unsigned int cnt, res, cf;
1238 cf = d & (1 << (16 - cnt));
1239 CONDITIONAL_SET_FLAG(cf, F_CF);
1240 set_szp_flags_16((u16)res);
1246 CONDITIONAL_SET_FLAG(
1247 (((res & 0x8000) == 0x8000) ^
1248 (ACCESS_FLAG(F_CF) != 0)),
1255 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1264 /****************************************************************************
1266 Implements the SHL instruction and side effects.
1267 ****************************************************************************/
1268 u32 shl_long(u32 d, u8 s)
1270 unsigned int cnt, res, cf;
1276 cf = d & (1 << (32 - cnt));
1277 CONDITIONAL_SET_FLAG(cf, F_CF);
1278 set_szp_flags_32((u32)res);
1283 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1284 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1290 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1299 /****************************************************************************
1301 Implements the SHR instruction and side effects.
1302 ****************************************************************************/
1303 u8 shr_byte(u8 d, u8 s)
1305 unsigned int cnt, res, cf;
1310 cf = d & (1 << (cnt - 1));
1312 CONDITIONAL_SET_FLAG(cf, F_CF);
1313 set_szp_flags_8((u8)res);
1319 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1325 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1334 /****************************************************************************
1336 Implements the SHR instruction and side effects.
1337 ****************************************************************************/
1338 u16 shr_word(u16 d, u8 s)
1340 unsigned int cnt, res, cf;
1345 cf = d & (1 << (cnt - 1));
1347 CONDITIONAL_SET_FLAG(cf, F_CF);
1348 set_szp_flags_16((u16)res);
1354 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1369 /****************************************************************************
1371 Implements the SHR instruction and side effects.
1372 ****************************************************************************/
1373 u32 shr_long(u32 d, u8 s)
1375 unsigned int cnt, res, cf;
1380 cf = d & (1 << (cnt - 1));
1382 CONDITIONAL_SET_FLAG(cf, F_CF);
1383 set_szp_flags_32((u32)res);
1388 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1403 /****************************************************************************
1405 Implements the SAR instruction and side effects.
1406 ****************************************************************************/
1407 u8 sar_byte(u8 d, u8 s)
1409 unsigned int cnt, res, cf, mask, sf;
1414 if (cnt > 0 && cnt < 8) {
1415 mask = (1 << (8 - cnt)) - 1;
1416 cf = d & (1 << (cnt - 1));
1417 res = (d >> cnt) & mask;
1418 CONDITIONAL_SET_FLAG(cf, F_CF);
1422 set_szp_flags_8((u8)res);
1423 } else if (cnt >= 8) {
1441 /****************************************************************************
1443 Implements the SAR instruction and side effects.
1444 ****************************************************************************/
1445 u16 sar_word(u16 d, u8 s)
1447 unsigned int cnt, res, cf, mask, sf;
1452 if (cnt > 0 && cnt < 16) {
1453 mask = (1 << (16 - cnt)) - 1;
1454 cf = d & (1 << (cnt - 1));
1455 res = (d >> cnt) & mask;
1456 CONDITIONAL_SET_FLAG(cf, F_CF);
1460 set_szp_flags_16((u16)res);
1461 } else if (cnt >= 16) {
1479 /****************************************************************************
1481 Implements the SAR instruction and side effects.
1482 ****************************************************************************/
1483 u32 sar_long(u32 d, u8 s)
1485 u32 cnt, res, cf, mask, sf;
1487 sf = d & 0x80000000;
1490 if (cnt > 0 && cnt < 32) {
1491 mask = (1 << (32 - cnt)) - 1;
1492 cf = d & (1 << (cnt - 1));
1493 res = (d >> cnt) & mask;
1494 CONDITIONAL_SET_FLAG(cf, F_CF);
1498 set_szp_flags_32(res);
1499 } else if (cnt >= 32) {
1517 /****************************************************************************
1519 Implements the SHLD instruction and side effects.
1520 ****************************************************************************/
1521 u16 shld_word (u16 d, u16 fill, u8 s)
1523 unsigned int cnt, res, cf;
1528 res = (d << cnt) | (fill >> (16-cnt));
1529 cf = d & (1 << (16 - cnt));
1530 CONDITIONAL_SET_FLAG(cf, F_CF);
1531 set_szp_flags_16((u16)res);
1536 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1537 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1543 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1552 /****************************************************************************
1554 Implements the SHLD instruction and side effects.
1555 ****************************************************************************/
1556 u32 shld_long (u32 d, u32 fill, u8 s)
1558 unsigned int cnt, res, cf;
1563 res = (d << cnt) | (fill >> (32-cnt));
1564 cf = d & (1 << (32 - cnt));
1565 CONDITIONAL_SET_FLAG(cf, F_CF);
1566 set_szp_flags_32((u32)res);
1571 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1572 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1578 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1587 /****************************************************************************
1589 Implements the SHRD instruction and side effects.
1590 ****************************************************************************/
1591 u16 shrd_word (u16 d, u16 fill, u8 s)
1593 unsigned int cnt, res, cf;
1598 cf = d & (1 << (cnt - 1));
1599 res = (d >> cnt) | (fill << (16 - cnt));
1600 CONDITIONAL_SET_FLAG(cf, F_CF);
1601 set_szp_flags_16((u16)res);
1607 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1622 /****************************************************************************
1624 Implements the SHRD instruction and side effects.
1625 ****************************************************************************/
1626 u32 shrd_long (u32 d, u32 fill, u8 s)
1628 unsigned int cnt, res, cf;
1633 cf = d & (1 << (cnt - 1));
1634 res = (d >> cnt) | (fill << (32 - cnt));
1635 CONDITIONAL_SET_FLAG(cf, F_CF);
1636 set_szp_flags_32((u32)res);
1641 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1656 /****************************************************************************
1658 Implements the SBB instruction and side effects.
1659 ****************************************************************************/
1660 u8 sbb_byte(u8 d, u8 s)
1662 u32 res; /* all operands in native machine order */
1665 if (ACCESS_FLAG(F_CF))
1669 set_szp_flags_8((u8)res);
1671 /* calculate the borrow chain. See note at top */
1672 bc = (res & (~d | s)) | (~d & s);
1673 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1674 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1675 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1679 /****************************************************************************
1681 Implements the SBB instruction and side effects.
1682 ****************************************************************************/
1683 u16 sbb_word(u16 d, u16 s)
1685 u32 res; /* all operands in native machine order */
1688 if (ACCESS_FLAG(F_CF))
1692 set_szp_flags_16((u16)res);
1694 /* calculate the borrow chain. See note at top */
1695 bc = (res & (~d | s)) | (~d & s);
1696 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1697 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1698 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1702 /****************************************************************************
1704 Implements the SBB instruction and side effects.
1705 ****************************************************************************/
1706 u32 sbb_long(u32 d, u32 s)
1708 u32 res; /* all operands in native machine order */
1711 if (ACCESS_FLAG(F_CF))
1716 set_szp_flags_32(res);
1718 /* calculate the borrow chain. See note at top */
1719 bc = (res & (~d | s)) | (~d & s);
1720 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1721 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1722 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1726 /****************************************************************************
1728 Implements the SUB instruction and side effects.
1729 ****************************************************************************/
1730 u8 sub_byte(u8 d, u8 s)
1732 u32 res; /* all operands in native machine order */
1736 set_szp_flags_8((u8)res);
1738 /* calculate the borrow chain. See note at top */
1739 bc = (res & (~d | s)) | (~d & s);
1740 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1741 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1742 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1746 /****************************************************************************
1748 Implements the SUB instruction and side effects.
1749 ****************************************************************************/
1750 u16 sub_word(u16 d, u16 s)
1752 u32 res; /* all operands in native machine order */
1756 set_szp_flags_16((u16)res);
1758 /* calculate the borrow chain. See note at top */
1759 bc = (res & (~d | s)) | (~d & s);
1760 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1761 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1762 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1766 /****************************************************************************
1768 Implements the SUB instruction and side effects.
1769 ****************************************************************************/
1770 u32 sub_long(u32 d, u32 s)
1772 u32 res; /* all operands in native machine order */
1776 set_szp_flags_32(res);
1778 /* calculate the borrow chain. See note at top */
1779 bc = (res & (~d | s)) | (~d & s);
1780 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1781 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1782 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1786 /****************************************************************************
1788 Implements the TEST instruction and side effects.
1789 ****************************************************************************/
1790 void test_byte(u8 d, u8 s)
1792 u32 res; /* all operands in native machine order */
1797 set_szp_flags_8((u8)res);
1798 /* AF == dont care */
1802 /****************************************************************************
1804 Implements the TEST instruction and side effects.
1805 ****************************************************************************/
1806 void test_word(u16 d, u16 s)
1808 u32 res; /* all operands in native machine order */
1813 set_szp_flags_16((u16)res);
1814 /* AF == dont care */
1818 /****************************************************************************
1820 Implements the TEST instruction and side effects.
1821 ****************************************************************************/
1822 void test_long(u32 d, u32 s)
1824 u32 res; /* all operands in native machine order */
1829 set_szp_flags_32(res);
1830 /* AF == dont care */
1834 /****************************************************************************
1836 Implements the XOR instruction and side effects.
1837 ****************************************************************************/
1838 u8 xor_byte(u8 d, u8 s)
1840 u8 res; /* all operands in native machine order */
1843 no_carry_byte_side_eff(res);
1847 /****************************************************************************
1849 Implements the XOR instruction and side effects.
1850 ****************************************************************************/
1851 u16 xor_word(u16 d, u16 s)
1853 u16 res; /* all operands in native machine order */
1856 no_carry_word_side_eff(res);
1860 /****************************************************************************
1862 Implements the XOR instruction and side effects.
1863 ****************************************************************************/
1864 u32 xor_long(u32 d, u32 s)
1866 u32 res; /* all operands in native machine order */
1869 no_carry_long_side_eff(res);
1873 /****************************************************************************
1875 Implements the IMUL instruction and side effects.
1876 ****************************************************************************/
1877 void imul_byte(u8 s)
1879 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1882 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
1883 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
1892 /****************************************************************************
1894 Implements the IMUL instruction and side effects.
1895 ****************************************************************************/
1896 void imul_word(u16 s)
1898 s32 res = (s16)M.x86.R_AX * (s16)s;
1900 M.x86.R_AX = (u16)res;
1901 M.x86.R_DX = (u16)(res >> 16);
1902 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
1903 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
1912 /****************************************************************************
1914 Implements the IMUL instruction and side effects.
1915 ****************************************************************************/
1916 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1918 #ifdef __HAS_LONG_LONG__
1919 s64 res = (s32)d * (s32)s;
1922 *res_hi = (u32)(res >> 32);
1924 u32 d_lo,d_hi,d_sign;
1925 u32 s_lo,s_hi,s_sign;
1926 u32 rlo_lo,rlo_hi,rhi_lo;
1928 if ((d_sign = d & 0x80000000) != 0)
1932 if ((s_sign = s & 0x80000000) != 0)
1936 rlo_lo = d_lo * s_lo;
1937 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
1938 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
1939 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
1941 if (d_sign != s_sign) {
1943 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1944 *res_lo = ~*res_lo+1;
1945 *res_hi = ~*res_hi+(s >> 16);
1950 /****************************************************************************
1952 Implements the IMUL instruction and side effects.
1953 ****************************************************************************/
1954 void imul_long(u32 s)
1956 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
1957 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
1958 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
1967 /****************************************************************************
1969 Implements the MUL instruction and side effects.
1970 ****************************************************************************/
1973 u16 res = (u16)(M.x86.R_AL * s);
1976 if (M.x86.R_AH == 0) {
1985 /****************************************************************************
1987 Implements the MUL instruction and side effects.
1988 ****************************************************************************/
1989 void mul_word(u16 s)
1991 u32 res = M.x86.R_AX * s;
1993 M.x86.R_AX = (u16)res;
1994 M.x86.R_DX = (u16)(res >> 16);
1995 if (M.x86.R_DX == 0) {
2004 /****************************************************************************
2006 Implements the MUL instruction and side effects.
2007 ****************************************************************************/
2008 void mul_long(u32 s)
2010 #ifdef __HAS_LONG_LONG__
2011 u64 res = (u32)M.x86.R_EAX * (u32)s;
2013 M.x86.R_EAX = (u32)res;
2014 M.x86.R_EDX = (u32)(res >> 32);
2018 u32 rlo_lo,rlo_hi,rhi_lo;
2025 rlo_lo = a_lo * s_lo;
2026 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2027 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2028 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2029 M.x86.R_EDX = rhi_lo;
2031 if (M.x86.R_EDX == 0) {
2040 /****************************************************************************
2042 Implements the IDIV instruction and side effects.
2043 ****************************************************************************/
2044 void idiv_byte(u8 s)
2048 dvd = (s16)M.x86.R_AX;
2050 x86emu_intr_raise(0);
2055 if (abs(div) > 0x7f) {
2056 x86emu_intr_raise(0);
2059 M.x86.R_AL = (s8) div;
2060 M.x86.R_AH = (s8) mod;
2063 /****************************************************************************
2065 Implements the IDIV instruction and side effects.
2066 ****************************************************************************/
2067 void idiv_word(u16 s)
2071 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2073 x86emu_intr_raise(0);
2078 if (abs(div) > 0x7fff) {
2079 x86emu_intr_raise(0);
2084 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2085 set_parity_flag(mod);
2087 M.x86.R_AX = (u16)div;
2088 M.x86.R_DX = (u16)mod;
2091 /****************************************************************************
2093 Implements the IDIV instruction and side effects.
2094 ****************************************************************************/
2095 void idiv_long(u32 s)
2097 #ifdef __HAS_LONG_LONG__
2100 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2102 x86emu_intr_raise(0);
2107 if (abs(div) > 0x7fffffff) {
2108 x86emu_intr_raise(0);
2113 s32 h_dvd = M.x86.R_EDX;
2114 u32 l_dvd = M.x86.R_EAX;
2115 u32 abs_s = s & 0x7FFFFFFF;
2116 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2117 u32 h_s = abs_s >> 1;
2118 u32 l_s = abs_s << 31;
2123 x86emu_intr_raise(0);
2128 carry = (l_dvd >= l_s) ? 0 : 1;
2130 if (abs_h_dvd < (h_s + carry)) {
2132 l_s = abs_s << (--counter);
2135 abs_h_dvd -= (h_s + carry);
2136 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2139 l_s = abs_s << (--counter);
2144 } while (counter > -1);
2146 if (abs_h_dvd || (l_dvd > abs_s)) {
2147 x86emu_intr_raise(0);
2151 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2159 set_parity_flag(mod);
2161 M.x86.R_EAX = (u32)div;
2162 M.x86.R_EDX = (u32)mod;
2165 /****************************************************************************
2167 Implements the DIV instruction and side effects.
2168 ****************************************************************************/
2175 x86emu_intr_raise(0);
2180 if (abs(div) > 0xff) {
2181 x86emu_intr_raise(0);
2184 M.x86.R_AL = (u8)div;
2185 M.x86.R_AH = (u8)mod;
2188 /****************************************************************************
2190 Implements the DIV instruction and side effects.
2191 ****************************************************************************/
2192 void div_word(u16 s)
2196 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2198 x86emu_intr_raise(0);
2203 if (abs(div) > 0xffff) {
2204 x86emu_intr_raise(0);
2209 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2210 set_parity_flag(mod);
2212 M.x86.R_AX = (u16)div;
2213 M.x86.R_DX = (u16)mod;
2216 /****************************************************************************
2218 Implements the DIV instruction and side effects.
2219 ****************************************************************************/
2220 void div_long(u32 s)
2222 #ifdef __HAS_LONG_LONG__
2225 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2227 x86emu_intr_raise(0);
2232 if (abs(div) > 0xffffffff) {
2233 x86emu_intr_raise(0);
2238 s32 h_dvd = M.x86.R_EDX;
2239 u32 l_dvd = M.x86.R_EAX;
2247 x86emu_intr_raise(0);
2252 carry = (l_dvd >= l_s) ? 0 : 1;
2254 if (h_dvd < (h_s + carry)) {
2256 l_s = s << (--counter);
2259 h_dvd -= (h_s + carry);
2260 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2263 l_s = s << (--counter);
2268 } while (counter > -1);
2270 if (h_dvd || (l_dvd > s)) {
2271 x86emu_intr_raise(0);
2280 set_parity_flag(mod);
2282 M.x86.R_EAX = (u32)div;
2283 M.x86.R_EDX = (u32)mod;
2286 /****************************************************************************
2288 Implements the IN string instruction and side effects.
2289 ****************************************************************************/
2291 static void single_in(int size)
2294 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
2296 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
2298 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
2305 if (ACCESS_FLAG(F_DF)) {
2308 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2309 /* dont care whether REPE or REPNE */
2310 /* in until CX is ZERO. */
2311 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2312 M.x86.R_ECX : M.x86.R_CX);
2319 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2322 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2329 /****************************************************************************
2331 Implements the OUT string instruction and side effects.
2332 ****************************************************************************/
2334 static void single_out(int size)
2337 (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2339 (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2341 (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2348 if (ACCESS_FLAG(F_DF)) {
2351 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2352 /* dont care whether REPE or REPNE */
2353 /* out until CX is ZERO. */
2354 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2355 M.x86.R_ECX : M.x86.R_CX);
2361 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2364 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2371 /****************************************************************************
2373 addr - Address to fetch word from
2376 Fetches a word from emulator memory using an absolute address.
2377 ****************************************************************************/
2378 u16 mem_access_word(int addr)
2380 DB( if (CHECK_MEM_ACCESS())
2381 x86emu_check_mem_access(addr);)
2382 return (*sys_rdw)(addr);
2385 /****************************************************************************
2387 Pushes a word onto the stack.
2389 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2390 ****************************************************************************/
2391 void push_word(u16 w)
2393 DB( if (CHECK_SP_ACCESS())
2394 x86emu_check_sp_access();)
2396 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2399 /****************************************************************************
2401 Pushes a long onto the stack.
2403 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2404 ****************************************************************************/
2405 void push_long(u32 w)
2407 DB( if (CHECK_SP_ACCESS())
2408 x86emu_check_sp_access();)
2410 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2413 /****************************************************************************
2415 Pops a word from the stack.
2417 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2418 ****************************************************************************/
2423 DB( if (CHECK_SP_ACCESS())
2424 x86emu_check_sp_access();)
2425 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2430 /****************************************************************************
2432 Pops a long from the stack.
2434 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2435 ****************************************************************************/
2440 DB( if (CHECK_SP_ACCESS())
2441 x86emu_check_sp_access();)
2442 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);