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 OF 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 a lot 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
105 (__x < 0) ? -__x : __x; \
110 (__x < 0) ? -__x : __x; \
113 /*------------------------- Global Variables ------------------------------*/
115 static u32 x86emu_parity_tab
[8] =
127 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
128 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
130 /*----------------------------- Implementation ----------------------------*/
132 /*--------- Side effects helper functions -------*/
134 /****************************************************************************
136 implements side effects for byte operations that don't overflow
137 ****************************************************************************/
139 static void set_parity_flag(u32 res
)
141 CONDITIONAL_SET_FLAG(PARITY(res
& 0xFF), F_PF
);
144 static void set_szp_flags_8(u8 res
)
146 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
147 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
148 set_parity_flag(res
);
151 static void set_szp_flags_16(u16 res
)
153 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
154 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
155 set_parity_flag(res
);
158 static void set_szp_flags_32(u32 res
)
160 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
161 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
162 set_parity_flag(res
);
165 static void no_carry_byte_side_eff(u8 res
)
170 set_szp_flags_8(res
);
173 static void no_carry_word_side_eff(u16 res
)
178 set_szp_flags_16(res
);
181 static void no_carry_long_side_eff(u32 res
)
186 set_szp_flags_32(res
);
189 static void calc_carry_chain(int bits
, u32 d
, u32 s
, u32 res
, int set_carry
)
193 cc
= (s
& d
) | ((~res
) & (s
| d
));
194 CONDITIONAL_SET_FLAG(XOR2(cc
>> (bits
- 2)), F_OF
);
195 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
197 CONDITIONAL_SET_FLAG(res
& (1 << bits
), F_CF
);
201 static void calc_borrow_chain(int bits
, u32 d
, u32 s
, u32 res
, int set_carry
)
205 bc
= (res
& (~d
| s
)) | (~d
& s
);
206 CONDITIONAL_SET_FLAG(XOR2(bc
>> (bits
- 2)), F_OF
);
207 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
209 CONDITIONAL_SET_FLAG(bc
& (1 << (bits
- 1)), F_CF
);
213 /****************************************************************************
215 Implements the AAA instruction and side effects.
216 ****************************************************************************/
220 if ((d
& 0xf) > 0x9 || ACCESS_FLAG(F_AF
)) {
229 res
= (u16
)(d
& 0xFF0F);
230 set_szp_flags_16(res
);
234 /****************************************************************************
236 Implements the AAA instruction and side effects.
237 ****************************************************************************/
241 if ((d
& 0xf) > 0x9 || ACCESS_FLAG(F_AF
)) {
250 res
= (u16
)(d
& 0xFF0F);
251 set_szp_flags_16(res
);
255 /****************************************************************************
257 Implements the AAD instruction and side effects.
258 ****************************************************************************/
264 hb
= (u8
)((d
>> 8) & 0xff);
265 lb
= (u8
)((d
& 0xff));
266 l
= (u16
)((lb
+ 10 * hb
) & 0xFF);
268 no_carry_byte_side_eff(l
& 0xFF);
272 /****************************************************************************
274 Implements the AAM instruction and side effects.
275 ****************************************************************************/
284 no_carry_byte_side_eff(l
& 0xFF);
288 /****************************************************************************
290 Implements the ADC instruction and side effects.
291 ****************************************************************************/
292 u8
adc_byte(u8 d
, u8 s
)
294 u32 res
; /* all operands in native machine order */
297 if (ACCESS_FLAG(F_CF
)) res
++;
299 set_szp_flags_8(res
);
300 calc_carry_chain(8,s
,d
,res
,1);
305 /****************************************************************************
307 Implements the ADC instruction and side effects.
308 ****************************************************************************/
309 u16
adc_word(u16 d
, u16 s
)
311 u32 res
; /* all operands in native machine order */
314 if (ACCESS_FLAG(F_CF
))
317 set_szp_flags_16((u16
)res
);
318 calc_carry_chain(16,s
,d
,res
,1);
323 /****************************************************************************
325 Implements the ADC instruction and side effects.
326 ****************************************************************************/
327 u32
adc_long(u32 d
, u32 s
)
329 u32 lo
; /* all operands in native machine order */
333 lo
= (d
& 0xFFFF) + (s
& 0xFFFF);
336 if (ACCESS_FLAG(F_CF
)) {
341 hi
= (lo
>> 16) + (d
>> 16) + (s
>> 16);
343 set_szp_flags_32(res
);
344 calc_carry_chain(32,s
,d
,res
,0);
346 CONDITIONAL_SET_FLAG(hi
& 0x10000, F_CF
);
351 /****************************************************************************
353 Implements the ADD instruction and side effects.
354 ****************************************************************************/
355 u8
add_byte(u8 d
, u8 s
)
357 u32 res
; /* all operands in native machine order */
360 set_szp_flags_8((u8
)res
);
361 calc_carry_chain(8,s
,d
,res
,1);
366 /****************************************************************************
368 Implements the ADD instruction and side effects.
369 ****************************************************************************/
370 u16
add_word(u16 d
, u16 s
)
372 u32 res
; /* all operands in native machine order */
375 set_szp_flags_16((u16
)res
);
376 calc_carry_chain(16,s
,d
,res
,1);
381 /****************************************************************************
383 Implements the ADD instruction and side effects.
384 ****************************************************************************/
385 u32
add_long(u32 d
, u32 s
)
390 set_szp_flags_32(res
);
391 calc_carry_chain(32,s
,d
,res
,0);
393 CONDITIONAL_SET_FLAG(res
< d
|| res
< s
, F_CF
);
398 /****************************************************************************
400 Implements the AND instruction and side effects.
401 ****************************************************************************/
402 u8
and_byte(u8 d
, u8 s
)
404 u8 res
; /* all operands in native machine order */
408 no_carry_byte_side_eff(res
);
412 /****************************************************************************
414 Implements the AND instruction and side effects.
415 ****************************************************************************/
416 u16
and_word(u16 d
, u16 s
)
418 u16 res
; /* all operands in native machine order */
422 no_carry_word_side_eff(res
);
426 /****************************************************************************
428 Implements the AND instruction and side effects.
429 ****************************************************************************/
430 u32
and_long(u32 d
, u32 s
)
432 u32 res
; /* all operands in native machine order */
435 no_carry_long_side_eff(res
);
439 /****************************************************************************
441 Implements the CMP instruction and side effects.
442 ****************************************************************************/
443 u8
cmp_byte(u8 d
, u8 s
)
445 u32 res
; /* all operands in native machine order */
448 set_szp_flags_8((u8
)res
);
449 calc_borrow_chain(8, d
, s
, res
, 1);
454 /****************************************************************************
456 Implements the CMP instruction and side effects.
457 ****************************************************************************/
458 u16
cmp_word(u16 d
, u16 s
)
460 u32 res
; /* all operands in native machine order */
463 set_szp_flags_16((u16
)res
);
464 calc_borrow_chain(16, d
, s
, res
, 1);
469 /****************************************************************************
471 Implements the CMP instruction and side effects.
472 ****************************************************************************/
473 u32
cmp_long(u32 d
, u32 s
)
475 u32 res
; /* all operands in native machine order */
478 set_szp_flags_32(res
);
479 calc_borrow_chain(32, d
, s
, res
, 1);
484 /****************************************************************************
486 Implements the DAA instruction and side effects.
487 ****************************************************************************/
491 if ((d
& 0xf) > 9 || ACCESS_FLAG(F_AF
)) {
495 if (res
> 0x9F || ACCESS_FLAG(F_CF
)) {
499 set_szp_flags_8((u8
)res
);
503 /****************************************************************************
505 Implements the DAS instruction and side effects.
506 ****************************************************************************/
509 if ((d
& 0xf) > 9 || ACCESS_FLAG(F_AF
)) {
513 if (d
> 0x9F || ACCESS_FLAG(F_CF
)) {
521 /****************************************************************************
523 Implements the DEC instruction and side effects.
524 ****************************************************************************/
527 u32 res
; /* all operands in native machine order */
530 set_szp_flags_8((u8
)res
);
531 calc_borrow_chain(8, d
, 1, res
, 0);
536 /****************************************************************************
538 Implements the DEC instruction and side effects.
539 ****************************************************************************/
542 u32 res
; /* all operands in native machine order */
545 set_szp_flags_16((u16
)res
);
546 calc_borrow_chain(16, d
, 1, res
, 0);
551 /****************************************************************************
553 Implements the DEC instruction and side effects.
554 ****************************************************************************/
557 u32 res
; /* all operands in native machine order */
561 set_szp_flags_32(res
);
562 calc_borrow_chain(32, d
, 1, res
, 0);
567 /****************************************************************************
569 Implements the INC instruction and side effects.
570 ****************************************************************************/
573 u32 res
; /* all operands in native machine order */
576 set_szp_flags_8((u8
)res
);
577 calc_carry_chain(8, d
, 1, res
, 0);
582 /****************************************************************************
584 Implements the INC instruction and side effects.
585 ****************************************************************************/
588 u32 res
; /* all operands in native machine order */
591 set_szp_flags_16((u16
)res
);
592 calc_carry_chain(16, d
, 1, res
, 0);
597 /****************************************************************************
599 Implements the INC instruction and side effects.
600 ****************************************************************************/
603 u32 res
; /* all operands in native machine order */
606 set_szp_flags_32(res
);
607 calc_carry_chain(32, d
, 1, res
, 0);
612 /****************************************************************************
614 Implements the OR instruction and side effects.
615 ****************************************************************************/
616 u8
or_byte(u8 d
, u8 s
)
618 u8 res
; /* all operands in native machine order */
621 no_carry_byte_side_eff(res
);
626 /****************************************************************************
628 Implements the OR instruction and side effects.
629 ****************************************************************************/
630 u16
or_word(u16 d
, u16 s
)
632 u16 res
; /* all operands in native machine order */
635 no_carry_word_side_eff(res
);
639 /****************************************************************************
641 Implements the OR instruction and side effects.
642 ****************************************************************************/
643 u32
or_long(u32 d
, u32 s
)
645 u32 res
; /* all operands in native machine order */
648 no_carry_long_side_eff(res
);
652 /****************************************************************************
654 Implements the OR instruction and side effects.
655 ****************************************************************************/
660 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
662 set_szp_flags_8(res
);
663 calc_borrow_chain(8, 0, s
, res
, 0);
668 /****************************************************************************
670 Implements the OR instruction and side effects.
671 ****************************************************************************/
676 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
678 set_szp_flags_16((u16
)res
);
679 calc_borrow_chain(16, 0, s
, res
, 0);
684 /****************************************************************************
686 Implements the OR instruction and side effects.
687 ****************************************************************************/
692 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
694 set_szp_flags_32(res
);
695 calc_borrow_chain(32, 0, s
, res
, 0);
700 /****************************************************************************
702 Implements the NOT instruction and side effects.
703 ****************************************************************************/
709 /****************************************************************************
711 Implements the NOT instruction and side effects.
712 ****************************************************************************/
718 /****************************************************************************
720 Implements the NOT instruction and side effects.
721 ****************************************************************************/
727 /****************************************************************************
729 Implements the RCL instruction and side effects.
730 ****************************************************************************/
731 u8
rcl_byte(u8 d
, u8 s
)
733 unsigned int res
, cnt
, mask
, cf
;
735 /* s is the rotate distance. It varies from 0 - 8. */
738 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
740 want to rotate through the carry by "s" bits. We could
741 loop, but that's inefficient. So the width is 9,
742 and we split into three parts:
744 The new carry flag (was B_n)
745 the stuff in B_n-1 .. B_0
746 the stuff in B_7 .. B_n+1
748 The new rotate is done mod 9, and given this,
749 for a rotation of n bits (mod 9) the new carry flag is
750 then located n bits from the MSB. The low part is
751 then shifted up cnt bits, and the high part is or'd
752 in. Using CAPS for new values, and lowercase for the
753 original values, this can be expressed as:
757 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
759 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
762 if ((cnt
= s
% 9) != 0) {
763 /* extract the new CARRY FLAG. */
765 cf
= (d
>> (8 - cnt
)) & 0x1;
767 /* get the low stuff which rotated
768 into the range B_7 .. B_cnt */
769 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
770 /* note that the right hand side done by the mask */
771 res
= (d
<< cnt
) & 0xff;
773 /* now the high stuff which rotated around
774 into the positions B_cnt-2 .. B_0 */
775 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
776 /* shift it downward, 7-(n-2) = 9-n positions.
777 and mask off the result before or'ing in.
779 mask
= (1 << (cnt
- 1)) - 1;
780 res
|= (d
>> (9 - cnt
)) & mask
;
782 /* if the carry flag was set, or it in. */
783 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
785 res
|= 1 << (cnt
- 1);
787 /* set the new carry flag, based on the variable "cf" */
788 CONDITIONAL_SET_FLAG(cf
, F_CF
);
789 /* OVERFLOW is set *IFF* cnt==1, then it is the
790 xor of CF and the most significant bit. Blecck. */
791 /* parenthesized this expression since it appears to
792 be causing OF to be missed */
793 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 6) & 0x2)),
800 /****************************************************************************
802 Implements the RCL instruction and side effects.
803 ****************************************************************************/
804 u16
rcl_word(u16 d
, u8 s
)
806 unsigned int res
, cnt
, mask
, cf
;
809 if ((cnt
= s
% 17) != 0) {
810 cf
= (d
>> (16 - cnt
)) & 0x1;
811 res
= (d
<< cnt
) & 0xffff;
812 mask
= (1 << (cnt
- 1)) - 1;
813 res
|= (d
>> (17 - cnt
)) & mask
;
814 if (ACCESS_FLAG(F_CF
)) {
815 res
|= 1 << (cnt
- 1);
817 CONDITIONAL_SET_FLAG(cf
, F_CF
);
818 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 14) & 0x2)),
824 /****************************************************************************
826 Implements the RCL instruction and side effects.
827 ****************************************************************************/
828 u32
rcl_long(u32 d
, u8 s
)
830 u32 res
, cnt
, mask
, cf
;
833 if ((cnt
= s
% 33) != 0) {
834 cf
= (d
>> (32 - cnt
)) & 0x1;
835 res
= (d
<< cnt
) & 0xffffffff;
836 mask
= (1 << (cnt
- 1)) - 1;
837 res
|= (d
>> (33 - cnt
)) & mask
;
838 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
839 res
|= 1 << (cnt
- 1);
841 CONDITIONAL_SET_FLAG(cf
, F_CF
);
842 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 30) & 0x2)),
848 /****************************************************************************
850 Implements the RCR instruction and side effects.
851 ****************************************************************************/
852 u8
rcr_byte(u8 d
, u8 s
)
855 u32 mask
, cf
, ocf
= 0;
857 /* rotate right through carry */
859 s is the rotate distance. It varies from 0 - 8.
860 d is the byte object rotated.
864 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
866 The new rotate is done mod 9, and given this,
867 for a rotation of n bits (mod 9) the new carry flag is
868 then located n bits from the LSB. The low part is
869 then shifted up cnt bits, and the high part is or'd
870 in. Using CAPS for new values, and lowercase for the
871 original values, this can be expressed as:
875 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
877 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
880 if ((cnt
= s
% 9) != 0) {
881 /* extract the new CARRY FLAG. */
885 /* note hackery here. Access_flag(..) evaluates to either
887 non-zero if flag is set.
888 doing access_flag(..) != 0 casts that into either
889 0..1 in any representation of the flags register
890 (i.e. packed bit array or unpacked.)
892 ocf
= ACCESS_FLAG(F_CF
) != 0;
894 cf
= (d
>> (cnt
- 1)) & 0x1;
896 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
897 /* note that the right hand side done by the mask
898 This is effectively done by shifting the
899 object to the right. The result must be masked,
900 in case the object came in and was treated
901 as a negative number. Needed??? */
903 mask
= (1 << (8 - cnt
)) - 1;
904 res
= (d
>> cnt
) & mask
;
906 /* now the high stuff which rotated around
907 into the positions B_cnt-2 .. B_0 */
908 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
909 /* shift it downward, 7-(n-2) = 9-n positions.
910 and mask off the result before or'ing in.
912 res
|= (d
<< (9 - cnt
));
914 /* if the carry flag was set, or it in. */
915 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
917 res
|= 1 << (8 - cnt
);
919 /* set the new carry flag, based on the variable "cf" */
920 CONDITIONAL_SET_FLAG(cf
, F_CF
);
921 /* OVERFLOW is set *IFF* cnt==1, then it is the
922 xor of CF and the most significant bit. Blecck. */
923 /* parenthesized... */
925 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 6) & 0x2)),
932 /****************************************************************************
934 Implements the RCR instruction and side effects.
935 ****************************************************************************/
936 u16
rcr_word(u16 d
, u8 s
)
939 u32 mask
, cf
, ocf
= 0;
941 /* rotate right through carry */
943 if ((cnt
= s
% 17) != 0) {
946 ocf
= ACCESS_FLAG(F_CF
) != 0;
948 cf
= (d
>> (cnt
- 1)) & 0x1;
949 mask
= (1 << (16 - cnt
)) - 1;
950 res
= (d
>> cnt
) & mask
;
951 res
|= (d
<< (17 - cnt
));
952 if (ACCESS_FLAG(F_CF
)) {
953 res
|= 1 << (16 - cnt
);
955 CONDITIONAL_SET_FLAG(cf
, F_CF
);
957 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 14) & 0x2)),
964 /****************************************************************************
966 Implements the RCR instruction and side effects.
967 ****************************************************************************/
968 u32
rcr_long(u32 d
, u8 s
)
971 u32 mask
, cf
, ocf
= 0;
973 /* rotate right through carry */
975 if ((cnt
= s
% 33) != 0) {
978 ocf
= ACCESS_FLAG(F_CF
) != 0;
980 cf
= (d
>> (cnt
- 1)) & 0x1;
981 mask
= (1 << (32 - cnt
)) - 1;
982 res
= (d
>> cnt
) & mask
;
984 res
|= (d
<< (33 - cnt
));
985 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
986 res
|= 1 << (32 - cnt
);
988 CONDITIONAL_SET_FLAG(cf
, F_CF
);
990 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 30) & 0x2)),
997 /****************************************************************************
999 Implements the ROL instruction and side effects.
1000 ****************************************************************************/
1001 u8
rol_byte(u8 d
, u8 s
)
1003 unsigned int res
, cnt
, mask
;
1007 s is the rotate distance. It varies from 0 - 8.
1008 d is the byte object rotated.
1014 The new rotate is done mod 8.
1015 Much simpler than the "rcl" or "rcr" operations.
1018 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1019 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1022 if ((cnt
= s
% 8) != 0) {
1023 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1026 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1027 mask
= (1 << cnt
) - 1;
1028 res
|= (d
>> (8 - cnt
)) & mask
;
1030 /* set the new carry flag, Note that it is the low order
1031 bit of the result!!! */
1032 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1033 /* OVERFLOW is set *IFF* s==1, then it is the
1034 xor of CF and the most significant bit. Blecck. */
1035 CONDITIONAL_SET_FLAG(s
== 1 &&
1036 XOR2((res
& 0x1) + ((res
>> 6) & 0x2)),
1039 /* set the new carry flag, Note that it is the low order
1040 bit of the result!!! */
1041 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1046 /****************************************************************************
1048 Implements the ROL instruction and side effects.
1049 ****************************************************************************/
1050 u16
rol_word(u16 d
, u8 s
)
1052 unsigned int res
, cnt
, mask
;
1055 if ((cnt
= s
% 16) != 0) {
1057 mask
= (1 << cnt
) - 1;
1058 res
|= (d
>> (16 - cnt
)) & mask
;
1059 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1060 CONDITIONAL_SET_FLAG(s
== 1 &&
1061 XOR2((res
& 0x1) + ((res
>> 14) & 0x2)),
1064 /* set the new carry flag, Note that it is the low order
1065 bit of the result!!! */
1066 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1071 /****************************************************************************
1073 Implements the ROL instruction and side effects.
1074 ****************************************************************************/
1075 u32
rol_long(u32 d
, u8 s
)
1080 if ((cnt
= s
% 32) != 0) {
1082 mask
= (1 << cnt
) - 1;
1083 res
|= (d
>> (32 - cnt
)) & mask
;
1084 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1085 CONDITIONAL_SET_FLAG(s
== 1 &&
1086 XOR2((res
& 0x1) + ((res
>> 30) & 0x2)),
1089 /* set the new carry flag, Note that it is the low order
1090 bit of the result!!! */
1091 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1096 /****************************************************************************
1098 Implements the ROR instruction and side effects.
1099 ****************************************************************************/
1100 u8
ror_byte(u8 d
, u8 s
)
1102 unsigned int res
, cnt
, mask
;
1106 s is the rotate distance. It varies from 0 - 8.
1107 d is the byte object rotated.
1113 The rotate is done mod 8.
1116 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1117 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1120 if ((cnt
= s
% 8) != 0) { /* not a typo, do nada if cnt==0 */
1121 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1122 res
= (d
<< (8 - cnt
));
1124 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1125 mask
= (1 << (8 - cnt
)) - 1;
1126 res
|= (d
>> (cnt
)) & mask
;
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 /* OVERFLOW is set *IFF* s==1, then it is the
1132 xor of the two most significant bits. Blecck. */
1133 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 6), F_OF
);
1134 } else if (s
!= 0) {
1135 /* set the new carry flag, Note that it is the low order
1136 bit of the result!!! */
1137 CONDITIONAL_SET_FLAG(res
& 0x80, F_CF
);
1142 /****************************************************************************
1144 Implements the ROR instruction and side effects.
1145 ****************************************************************************/
1146 u16
ror_word(u16 d
, u8 s
)
1148 unsigned int res
, cnt
, mask
;
1151 if ((cnt
= s
% 16) != 0) {
1152 res
= (d
<< (16 - cnt
));
1153 mask
= (1 << (16 - cnt
)) - 1;
1154 res
|= (d
>> (cnt
)) & mask
;
1155 CONDITIONAL_SET_FLAG(res
& 0x8000, F_CF
);
1156 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 14), F_OF
);
1157 } else if (s
!= 0) {
1158 /* set the new carry flag, Note that it is the low order
1159 bit of the result!!! */
1160 CONDITIONAL_SET_FLAG(res
& 0x8000, F_CF
);
1165 /****************************************************************************
1167 Implements the ROR instruction and side effects.
1168 ****************************************************************************/
1169 u32
ror_long(u32 d
, u8 s
)
1174 if ((cnt
= s
% 32) != 0) {
1175 res
= (d
<< (32 - cnt
));
1176 mask
= (1 << (32 - cnt
)) - 1;
1177 res
|= (d
>> (cnt
)) & mask
;
1178 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_CF
);
1179 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 30), F_OF
);
1180 } else if (s
!= 0) {
1181 /* set the new carry flag, Note that it is the low order
1182 bit of the result!!! */
1183 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_CF
);
1188 /****************************************************************************
1190 Implements the SHL instruction and side effects.
1191 ****************************************************************************/
1192 u8
shl_byte(u8 d
, u8 s
)
1194 unsigned int cnt
, res
, cf
;
1199 /* last bit shifted out goes into carry flag */
1202 cf
= d
& (1 << (8 - cnt
));
1203 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1204 set_szp_flags_8((u8
)res
);
1210 /* Needs simplification. */
1211 CONDITIONAL_SET_FLAG(
1212 (((res
& 0x80) == 0x80) ^
1213 (ACCESS_FLAG(F_CF
) != 0)),
1214 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1221 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x80, F_CF
);
1230 /****************************************************************************
1232 Implements the SHL instruction and side effects.
1233 ****************************************************************************/
1234 u16
shl_word(u16 d
, u8 s
)
1236 unsigned int cnt
, res
, cf
;
1242 cf
= d
& (1 << (16 - cnt
));
1243 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1244 set_szp_flags_16((u16
)res
);
1250 CONDITIONAL_SET_FLAG(
1251 (((res
& 0x8000) == 0x8000) ^
1252 (ACCESS_FLAG(F_CF
) != 0)),
1259 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x8000, F_CF
);
1268 /****************************************************************************
1270 Implements the SHL instruction and side effects.
1271 ****************************************************************************/
1272 u32
shl_long(u32 d
, u8 s
)
1274 unsigned int cnt
, res
, cf
;
1280 cf
= d
& (1 << (32 - cnt
));
1281 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1282 set_szp_flags_32((u32
)res
);
1287 CONDITIONAL_SET_FLAG((((res
& 0x80000000) == 0x80000000) ^
1288 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
1294 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x80000000, F_CF
);
1303 /****************************************************************************
1305 Implements the SHR instruction and side effects.
1306 ****************************************************************************/
1307 u8
shr_byte(u8 d
, u8 s
)
1309 unsigned int cnt
, res
, cf
;
1314 cf
= d
& (1 << (cnt
- 1));
1316 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1317 set_szp_flags_8((u8
)res
);
1323 CONDITIONAL_SET_FLAG(XOR2(res
>> 6), F_OF
);
1329 CONDITIONAL_SET_FLAG((d
>> (s
-1)) & 0x1, F_CF
);
1338 /****************************************************************************
1340 Implements the SHR instruction and side effects.
1341 ****************************************************************************/
1342 u16
shr_word(u16 d
, u8 s
)
1344 unsigned int cnt
, res
, cf
;
1349 cf
= d
& (1 << (cnt
- 1));
1351 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1352 set_szp_flags_16((u16
)res
);
1358 CONDITIONAL_SET_FLAG(XOR2(res
>> 14), F_OF
);
1373 /****************************************************************************
1375 Implements the SHR instruction and side effects.
1376 ****************************************************************************/
1377 u32
shr_long(u32 d
, u8 s
)
1379 unsigned int cnt
, res
, cf
;
1384 cf
= d
& (1 << (cnt
- 1));
1386 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1387 set_szp_flags_32((u32
)res
);
1392 CONDITIONAL_SET_FLAG(XOR2(res
>> 30), F_OF
);
1407 /****************************************************************************
1409 Implements the SAR instruction and side effects.
1410 ****************************************************************************/
1411 u8
sar_byte(u8 d
, u8 s
)
1413 unsigned int cnt
, res
, cf
, mask
, sf
;
1418 if (cnt
> 0 && cnt
< 8) {
1419 mask
= (1 << (8 - cnt
)) - 1;
1420 cf
= d
& (1 << (cnt
- 1));
1421 res
= (d
>> cnt
) & mask
;
1422 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1426 set_szp_flags_8((u8
)res
);
1427 } else if (cnt
>= 8) {
1445 /****************************************************************************
1447 Implements the SAR instruction and side effects.
1448 ****************************************************************************/
1449 u16
sar_word(u16 d
, u8 s
)
1451 unsigned int cnt
, res
, cf
, mask
, sf
;
1456 if (cnt
> 0 && cnt
< 16) {
1457 mask
= (1 << (16 - cnt
)) - 1;
1458 cf
= d
& (1 << (cnt
- 1));
1459 res
= (d
>> cnt
) & mask
;
1460 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1464 set_szp_flags_16((u16
)res
);
1465 } else if (cnt
>= 16) {
1483 /****************************************************************************
1485 Implements the SAR instruction and side effects.
1486 ****************************************************************************/
1487 u32
sar_long(u32 d
, u8 s
)
1489 u32 cnt
, res
, cf
, mask
, sf
;
1491 sf
= d
& 0x80000000;
1494 if (cnt
> 0 && cnt
< 32) {
1495 mask
= (1 << (32 - cnt
)) - 1;
1496 cf
= d
& (1 << (cnt
- 1));
1497 res
= (d
>> cnt
) & mask
;
1498 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1502 set_szp_flags_32(res
);
1503 } else if (cnt
>= 32) {
1521 /****************************************************************************
1523 Implements the SHLD instruction and side effects.
1524 ****************************************************************************/
1525 u16
shld_word (u16 d
, u16 fill
, u8 s
)
1527 unsigned int cnt
, res
, cf
;
1532 res
= (d
<< cnt
) | (fill
>> (16-cnt
));
1533 cf
= d
& (1 << (16 - cnt
));
1534 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1535 set_szp_flags_16((u16
)res
);
1540 CONDITIONAL_SET_FLAG((((res
& 0x8000) == 0x8000) ^
1541 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
1547 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x8000, F_CF
);
1556 /****************************************************************************
1558 Implements the SHLD instruction and side effects.
1559 ****************************************************************************/
1560 u32
shld_long (u32 d
, u32 fill
, u8 s
)
1562 unsigned int cnt
, res
, cf
;
1567 res
= (d
<< cnt
) | (fill
>> (32-cnt
));
1568 cf
= d
& (1 << (32 - cnt
));
1569 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1570 set_szp_flags_32((u32
)res
);
1575 CONDITIONAL_SET_FLAG((((res
& 0x80000000) == 0x80000000) ^
1576 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
1582 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x80000000, F_CF
);
1591 /****************************************************************************
1593 Implements the SHRD instruction and side effects.
1594 ****************************************************************************/
1595 u16
shrd_word (u16 d
, u16 fill
, u8 s
)
1597 unsigned int cnt
, res
, cf
;
1602 cf
= d
& (1 << (cnt
- 1));
1603 res
= (d
>> cnt
) | (fill
<< (16 - cnt
));
1604 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1605 set_szp_flags_16((u16
)res
);
1611 CONDITIONAL_SET_FLAG(XOR2(res
>> 14), F_OF
);
1626 /****************************************************************************
1628 Implements the SHRD instruction and side effects.
1629 ****************************************************************************/
1630 u32
shrd_long (u32 d
, u32 fill
, u8 s
)
1632 unsigned int cnt
, res
, cf
;
1637 cf
= d
& (1 << (cnt
- 1));
1638 res
= (d
>> cnt
) | (fill
<< (32 - cnt
));
1639 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1640 set_szp_flags_32((u32
)res
);
1645 CONDITIONAL_SET_FLAG(XOR2(res
>> 30), F_OF
);
1660 /****************************************************************************
1662 Implements the SBB instruction and side effects.
1663 ****************************************************************************/
1664 u8
sbb_byte(u8 d
, u8 s
)
1666 u32 res
; /* all operands in native machine order */
1669 if (ACCESS_FLAG(F_CF
))
1673 set_szp_flags_8((u8
)res
);
1675 /* calculate the borrow chain. See note at top */
1676 bc
= (res
& (~d
| s
)) | (~d
& s
);
1677 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
1678 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
1679 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1683 /****************************************************************************
1685 Implements the SBB instruction and side effects.
1686 ****************************************************************************/
1687 u16
sbb_word(u16 d
, u16 s
)
1689 u32 res
; /* all operands in native machine order */
1692 if (ACCESS_FLAG(F_CF
))
1696 set_szp_flags_16((u16
)res
);
1698 /* calculate the borrow chain. See note at top */
1699 bc
= (res
& (~d
| s
)) | (~d
& s
);
1700 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
1701 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
1702 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1706 /****************************************************************************
1708 Implements the SBB instruction and side effects.
1709 ****************************************************************************/
1710 u32
sbb_long(u32 d
, u32 s
)
1712 u32 res
; /* all operands in native machine order */
1715 if (ACCESS_FLAG(F_CF
))
1720 set_szp_flags_32(res
);
1722 /* calculate the borrow chain. See note at top */
1723 bc
= (res
& (~d
| s
)) | (~d
& s
);
1724 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
1725 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
1726 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1730 /****************************************************************************
1732 Implements the SUB instruction and side effects.
1733 ****************************************************************************/
1734 u8
sub_byte(u8 d
, u8 s
)
1736 u32 res
; /* all operands in native machine order */
1740 set_szp_flags_8((u8
)res
);
1742 /* calculate the borrow chain. See note at top */
1743 bc
= (res
& (~d
| s
)) | (~d
& s
);
1744 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
1745 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
1746 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1750 /****************************************************************************
1752 Implements the SUB instruction and side effects.
1753 ****************************************************************************/
1754 u16
sub_word(u16 d
, u16 s
)
1756 u32 res
; /* all operands in native machine order */
1760 set_szp_flags_16((u16
)res
);
1762 /* calculate the borrow chain. See note at top */
1763 bc
= (res
& (~d
| s
)) | (~d
& s
);
1764 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
1765 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
1766 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1770 /****************************************************************************
1772 Implements the SUB instruction and side effects.
1773 ****************************************************************************/
1774 u32
sub_long(u32 d
, u32 s
)
1776 u32 res
; /* all operands in native machine order */
1780 set_szp_flags_32(res
);
1782 /* calculate the borrow chain. See note at top */
1783 bc
= (res
& (~d
| s
)) | (~d
& s
);
1784 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
1785 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
1786 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1790 /****************************************************************************
1792 Implements the TEST instruction and side effects.
1793 ****************************************************************************/
1794 void test_byte(u8 d
, u8 s
)
1796 u32 res
; /* all operands in native machine order */
1801 set_szp_flags_8((u8
)res
);
1802 /* AF == don't care */
1806 /****************************************************************************
1808 Implements the TEST instruction and side effects.
1809 ****************************************************************************/
1810 void test_word(u16 d
, u16 s
)
1812 u32 res
; /* all operands in native machine order */
1817 set_szp_flags_16((u16
)res
);
1818 /* AF == don't care */
1822 /****************************************************************************
1824 Implements the TEST instruction and side effects.
1825 ****************************************************************************/
1826 void test_long(u32 d
, u32 s
)
1828 u32 res
; /* all operands in native machine order */
1833 set_szp_flags_32(res
);
1834 /* AF == don't care */
1838 /****************************************************************************
1840 Implements the XOR instruction and side effects.
1841 ****************************************************************************/
1842 u8
xor_byte(u8 d
, u8 s
)
1844 u8 res
; /* all operands in native machine order */
1847 no_carry_byte_side_eff(res
);
1851 /****************************************************************************
1853 Implements the XOR instruction and side effects.
1854 ****************************************************************************/
1855 u16
xor_word(u16 d
, u16 s
)
1857 u16 res
; /* all operands in native machine order */
1860 no_carry_word_side_eff(res
);
1864 /****************************************************************************
1866 Implements the XOR instruction and side effects.
1867 ****************************************************************************/
1868 u32
xor_long(u32 d
, u32 s
)
1870 u32 res
; /* all operands in native machine order */
1873 no_carry_long_side_eff(res
);
1877 /****************************************************************************
1879 Implements the IMUL instruction and side effects.
1880 ****************************************************************************/
1881 void imul_byte(u8 s
)
1883 s16 res
= (s16
)((s8
)M
.x86
.R_AL
* (s8
)s
);
1886 if (((M
.x86
.R_AL
& 0x80) == 0 && M
.x86
.R_AH
== 0x00) ||
1887 ((M
.x86
.R_AL
& 0x80) != 0 && M
.x86
.R_AH
== 0xFF)) {
1896 /****************************************************************************
1898 Implements the IMUL instruction and side effects.
1899 ****************************************************************************/
1900 void imul_word(u16 s
)
1902 s32 res
= (s16
)M
.x86
.R_AX
* (s16
)s
;
1904 M
.x86
.R_AX
= (u16
)res
;
1905 M
.x86
.R_DX
= (u16
)(res
>> 16);
1906 if (((M
.x86
.R_AX
& 0x8000) == 0 && M
.x86
.R_DX
== 0x0000) ||
1907 ((M
.x86
.R_AX
& 0x8000) != 0 && M
.x86
.R_DX
== 0xFFFF)) {
1916 /****************************************************************************
1918 Implements the IMUL instruction and side effects.
1919 ****************************************************************************/
1920 void imul_long_direct(u32
*res_lo
, u32
* res_hi
,u32 d
, u32 s
)
1922 #ifdef __HAS_LONG_LONG__
1923 s64 res
= (s64
)(s32
)d
* (s64
)(s32
)s
;
1926 *res_hi
= (u32
)(res
>> 32);
1928 u32 d_lo
,d_hi
,d_sign
;
1929 u32 s_lo
,s_hi
,s_sign
;
1930 u32 rlo_lo
,rlo_hi
,rhi_lo
;
1932 if ((d_sign
= d
& 0x80000000) != 0)
1936 if ((s_sign
= s
& 0x80000000) != 0)
1940 rlo_lo
= d_lo
* s_lo
;
1941 rlo_hi
= (d_hi
* s_lo
+ d_lo
* s_hi
) + (rlo_lo
>> 16);
1942 rhi_lo
= d_hi
* s_hi
+ (rlo_hi
>> 16);
1943 *res_lo
= (rlo_hi
<< 16) | (rlo_lo
& 0xFFFF);
1945 if (d_sign
!= s_sign
) {
1947 s
= (((d
& 0xFFFF) + 1) >> 16) + (d
>> 16);
1948 *res_lo
= ~*res_lo
+1;
1949 *res_hi
= ~*res_hi
+(s
>> 16);
1954 /****************************************************************************
1956 Implements the IMUL instruction and side effects.
1957 ****************************************************************************/
1958 void imul_long(u32 s
)
1960 imul_long_direct(&M
.x86
.R_EAX
,&M
.x86
.R_EDX
,M
.x86
.R_EAX
,s
);
1961 if (((M
.x86
.R_EAX
& 0x80000000) == 0 && M
.x86
.R_EDX
== 0x00000000) ||
1962 ((M
.x86
.R_EAX
& 0x80000000) != 0 && M
.x86
.R_EDX
== 0xFFFFFFFF)) {
1971 /****************************************************************************
1973 Implements the MUL instruction and side effects.
1974 ****************************************************************************/
1977 u16 res
= (u16
)(M
.x86
.R_AL
* s
);
1980 if (M
.x86
.R_AH
== 0) {
1989 /****************************************************************************
1991 Implements the MUL instruction and side effects.
1992 ****************************************************************************/
1993 void mul_word(u16 s
)
1995 u32 res
= M
.x86
.R_AX
* s
;
1997 M
.x86
.R_AX
= (u16
)res
;
1998 M
.x86
.R_DX
= (u16
)(res
>> 16);
1999 if (M
.x86
.R_DX
== 0) {
2008 /****************************************************************************
2010 Implements the MUL instruction and side effects.
2011 ****************************************************************************/
2012 void mul_long(u32 s
)
2014 #ifdef __HAS_LONG_LONG__
2015 u64 res
= (u64
)M
.x86
.R_EAX
* s
;
2017 M
.x86
.R_EAX
= (u32
)res
;
2018 M
.x86
.R_EDX
= (u32
)(res
>> 32);
2022 u32 rlo_lo
,rlo_hi
,rhi_lo
;
2029 rlo_lo
= a_lo
* s_lo
;
2030 rlo_hi
= (a_hi
* s_lo
+ a_lo
* s_hi
) + (rlo_lo
>> 16);
2031 rhi_lo
= a_hi
* s_hi
+ (rlo_hi
>> 16);
2032 M
.x86
.R_EAX
= (rlo_hi
<< 16) | (rlo_lo
& 0xFFFF);
2033 M
.x86
.R_EDX
= rhi_lo
;
2035 if (M
.x86
.R_EDX
== 0) {
2044 /****************************************************************************
2046 Implements the IDIV instruction and side effects.
2047 ****************************************************************************/
2048 void idiv_byte(u8 s
)
2052 dvd
= (s16
)M
.x86
.R_AX
;
2054 x86emu_intr_raise(0);
2059 if (abs(div
) > 0x7f) {
2060 x86emu_intr_raise(0);
2063 M
.x86
.R_AL
= (s8
) div
;
2064 M
.x86
.R_AH
= (s8
) mod
;
2067 /****************************************************************************
2069 Implements the IDIV instruction and side effects.
2070 ****************************************************************************/
2071 void idiv_word(u16 s
)
2075 dvd
= (((s32
)M
.x86
.R_DX
) << 16) | M
.x86
.R_AX
;
2077 x86emu_intr_raise(0);
2082 if (abs(div
) > 0x7fff) {
2083 x86emu_intr_raise(0);
2088 CONDITIONAL_SET_FLAG(div
== 0, F_ZF
);
2089 set_parity_flag(mod
);
2091 M
.x86
.R_AX
= (u16
)div
;
2092 M
.x86
.R_DX
= (u16
)mod
;
2095 /****************************************************************************
2097 Implements the IDIV instruction and side effects.
2098 ****************************************************************************/
2099 void idiv_long(u32 s
)
2101 #ifdef __HAS_LONG_LONG__
2104 dvd
= (((s64
)M
.x86
.R_EDX
) << 32) | M
.x86
.R_EAX
;
2106 x86emu_intr_raise(0);
2111 if (abs(div
) > 0x7fffffff) {
2112 x86emu_intr_raise(0);
2117 s32 h_dvd
= M
.x86
.R_EDX
;
2118 u32 l_dvd
= M
.x86
.R_EAX
;
2119 u32 abs_s
= s
& 0x7FFFFFFF;
2120 u32 abs_h_dvd
= h_dvd
& 0x7FFFFFFF;
2121 u32 h_s
= abs_s
>> 1;
2122 u32 l_s
= abs_s
<< 31;
2127 x86emu_intr_raise(0);
2132 carry
= (l_dvd
>= l_s
) ? 0 : 1;
2134 if (abs_h_dvd
< (h_s
+ carry
)) {
2136 l_s
= abs_s
<< (--counter
);
2139 abs_h_dvd
-= (h_s
+ carry
);
2140 l_dvd
= carry
? ((0xFFFFFFFF - l_s
) + l_dvd
+ 1)
2143 l_s
= abs_s
<< (--counter
);
2148 } while (counter
> -1);
2150 if (abs_h_dvd
|| (l_dvd
> abs_s
)) {
2151 x86emu_intr_raise(0);
2155 div
|= ((h_dvd
& 0x10000000) ^ (s
& 0x10000000));
2163 set_parity_flag(mod
);
2165 M
.x86
.R_EAX
= (u32
)div
;
2166 M
.x86
.R_EDX
= (u32
)mod
;
2169 /****************************************************************************
2171 Implements the DIV instruction and side effects.
2172 ****************************************************************************/
2179 x86emu_intr_raise(0);
2184 if (abs(div
) > 0xff) {
2185 x86emu_intr_raise(0);
2188 M
.x86
.R_AL
= (u8
)div
;
2189 M
.x86
.R_AH
= (u8
)mod
;
2192 /****************************************************************************
2194 Implements the DIV instruction and side effects.
2195 ****************************************************************************/
2196 void div_word(u16 s
)
2200 dvd
= (((u32
)M
.x86
.R_DX
) << 16) | M
.x86
.R_AX
;
2202 x86emu_intr_raise(0);
2207 if (abs(div
) > 0xffff) {
2208 x86emu_intr_raise(0);
2213 CONDITIONAL_SET_FLAG(div
== 0, F_ZF
);
2214 set_parity_flag(mod
);
2216 M
.x86
.R_AX
= (u16
)div
;
2217 M
.x86
.R_DX
= (u16
)mod
;
2220 /****************************************************************************
2222 Implements the DIV instruction and side effects.
2223 ****************************************************************************/
2224 void div_long(u32 s
)
2226 #ifdef __HAS_LONG_LONG__
2229 dvd
= (((u64
)M
.x86
.R_EDX
) << 32) | M
.x86
.R_EAX
;
2231 x86emu_intr_raise(0);
2236 if (abs(div
) > 0xffffffff) {
2237 x86emu_intr_raise(0);
2242 s32 h_dvd
= M
.x86
.R_EDX
;
2243 u32 l_dvd
= M
.x86
.R_EAX
;
2251 x86emu_intr_raise(0);
2256 carry
= (l_dvd
>= l_s
) ? 0 : 1;
2258 if (h_dvd
< (h_s
+ carry
)) {
2260 l_s
= s
<< (--counter
);
2263 h_dvd
-= (h_s
+ carry
);
2264 l_dvd
= carry
? ((0xFFFFFFFF - l_s
) + l_dvd
+ 1)
2267 l_s
= s
<< (--counter
);
2272 } while (counter
> -1);
2274 if (h_dvd
|| (l_dvd
> s
)) {
2275 x86emu_intr_raise(0);
2284 set_parity_flag(mod
);
2286 M
.x86
.R_EAX
= (u32
)div
;
2287 M
.x86
.R_EDX
= (u32
)mod
;
2290 /****************************************************************************
2292 Implements the IN string instruction and side effects.
2293 ****************************************************************************/
2295 static void single_in(int size
)
2298 store_data_byte_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,(*sys_inb
)(M
.x86
.R_DX
));
2300 store_data_word_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,(*sys_inw
)(M
.x86
.R_DX
));
2302 store_data_long_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,(*sys_inl
)(M
.x86
.R_DX
));
2309 if (ACCESS_FLAG(F_DF
)) {
2312 if (M
.x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2313 /* don't care whether REPE or REPNE */
2314 /* in until (E)CX is ZERO. */
2315 u32 count
= ((M
.x86
.mode
& SYSMODE_32BIT_REP
) ?
2316 M
.x86
.R_ECX
: M
.x86
.R_CX
);
2322 if (M
.x86
.mode
& SYSMODE_32BIT_REP
) {
2325 M
.x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2332 /****************************************************************************
2334 Implements the OUT string instruction and side effects.
2335 ****************************************************************************/
2337 static void single_out(int size
)
2340 (*sys_outb
)(M
.x86
.R_DX
,fetch_data_byte_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2342 (*sys_outw
)(M
.x86
.R_DX
,fetch_data_word_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2344 (*sys_outl
)(M
.x86
.R_DX
,fetch_data_long_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2351 if (ACCESS_FLAG(F_DF
)) {
2354 if (M
.x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2355 /* don't care whether REPE or REPNE */
2356 /* out until (E)CX is ZERO. */
2357 u32 count
= ((M
.x86
.mode
& SYSMODE_32BIT_REP
) ?
2358 M
.x86
.R_ECX
: M
.x86
.R_CX
);
2364 if (M
.x86
.mode
& SYSMODE_32BIT_REP
) {
2367 M
.x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2374 /****************************************************************************
2376 addr - Address to fetch word from
2379 Fetches a word from emulator memory using an absolute address.
2380 ****************************************************************************/
2381 u16
mem_access_word(int addr
)
2383 DB( if (CHECK_MEM_ACCESS())
2384 x86emu_check_mem_access(addr
);)
2385 return (*sys_rdw
)(addr
);
2388 /****************************************************************************
2390 Pushes a word onto the stack.
2392 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2393 ****************************************************************************/
2394 void push_word(u16 w
)
2396 DB( if (CHECK_SP_ACCESS())
2397 x86emu_check_sp_access();)
2399 (*sys_wrw
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
, w
);
2402 /****************************************************************************
2404 Pushes a long onto the stack.
2406 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2407 ****************************************************************************/
2408 void push_long(u32 w
)
2410 DB( if (CHECK_SP_ACCESS())
2411 x86emu_check_sp_access();)
2413 (*sys_wrl
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
, w
);
2416 /****************************************************************************
2418 Pops a word from the stack.
2420 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2421 ****************************************************************************/
2426 DB( if (CHECK_SP_ACCESS())
2427 x86emu_check_sp_access();)
2428 res
= (*sys_rdw
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
);
2433 /****************************************************************************
2435 Pops a long from the stack.
2437 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2438 ****************************************************************************/
2443 DB( if (CHECK_SP_ACCESS())
2444 x86emu_check_sp_access();)
2445 res
= (*sys_rdl
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
);
2450 /****************************************************************************
2452 CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
2453 ****************************************************************************/
2454 void x86emu_cpuid(void)
2456 u32 feature
= M
.x86
.R_EAX
;
2460 /* Regardless if we have real data from the hardware, the emulator
2461 * will only support up to feature 1, which we set in register EAX.
2462 * Registers EBX:EDX:ECX contain a string identifying the CPU.
2465 /* EBX:EDX:ECX = "GenuineIntel" */
2466 M
.x86
.R_EBX
= 0x756e6547;
2467 M
.x86
.R_EDX
= 0x49656e69;
2468 M
.x86
.R_ECX
= 0x6c65746e;
2471 /* If we don't have x86 compatible hardware, we return values from an
2472 * Intel 486dx4; which was one of the first processors to have CPUID.
2474 M
.x86
.R_EAX
= 0x00000480;
2475 M
.x86
.R_EBX
= 0x00000000;
2476 M
.x86
.R_ECX
= 0x00000000;
2477 M
.x86
.R_EDX
= 0x00000002; /* VME */
2478 /* In the case that we have hardware CPUID instruction, we make sure
2479 * that the features reported are limited to TSC and VME.
2481 M
.x86
.R_EDX
&= 0x00000012;
2484 /* Finally, we don't support any additional features. Most CPUs
2485 * return all zeros when queried for invalid or unsupported feature