1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1996-1999 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 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 ****************************************************************************/
102 #define PRIM_OPS_NO_REDEFINE_ASM
103 #include "x86emu/x86emui.h"
105 /*------------------------- Global Variables ------------------------------*/
107 static u32 x86emu_parity_tab
[8] =
119 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
120 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
122 /*----------------------------- Implementation ----------------------------*/
124 /****************************************************************************
126 Implements the AAA instruction and side effects.
127 ****************************************************************************/
131 if ((d
& 0xf) > 0x9 || ACCESS_FLAG(F_AF
)) {
140 res
= (u16
)(d
& 0xFF0F);
142 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
143 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
147 /****************************************************************************
149 Implements the AAA instruction and side effects.
150 ****************************************************************************/
154 if ((d
& 0xf) > 0x9 || ACCESS_FLAG(F_AF
)) {
163 res
= (u16
)(d
& 0xFF0F);
165 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
166 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
170 /****************************************************************************
172 Implements the AAD instruction and side effects.
173 ****************************************************************************/
179 hb
= (u8
)((d
>> 8) & 0xff);
180 lb
= (u8
)((d
& 0xff));
181 l
= (u16
)((lb
+ 10 * hb
) & 0xFF);
186 CONDITIONAL_SET_FLAG(l
& 0x80, F_SF
);
187 CONDITIONAL_SET_FLAG(l
== 0, F_ZF
);
188 CONDITIONAL_SET_FLAG(PARITY(l
& 0xff), F_PF
);
192 /****************************************************************************
194 Implements the AAM instruction and side effects.
195 ****************************************************************************/
207 CONDITIONAL_SET_FLAG(l
& 0x80, F_SF
);
208 CONDITIONAL_SET_FLAG(l
== 0, F_ZF
);
209 CONDITIONAL_SET_FLAG(PARITY(l
& 0xff), F_PF
);
213 /****************************************************************************
215 Implements the ADC instruction and side effects.
216 ****************************************************************************/
217 u8
adc_byte(u8 d
, u8 s
)
219 register u32 res
; /* all operands in native machine order */
222 if (ACCESS_FLAG(F_CF
))
227 CONDITIONAL_SET_FLAG(res
& 0x100, F_CF
);
228 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
229 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
230 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
232 /* calculate the carry chain SEE NOTE AT TOP. */
233 cc
= (s
& d
) | ((~res
) & (s
| d
));
234 CONDITIONAL_SET_FLAG(XOR2(cc
>> 6), F_OF
);
235 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
239 /****************************************************************************
241 Implements the ADC instruction and side effects.
242 ****************************************************************************/
243 u16
adc_word(u16 d
, u16 s
)
245 register u32 res
; /* all operands in native machine order */
248 if (ACCESS_FLAG(F_CF
))
253 CONDITIONAL_SET_FLAG(res
& 0x10000, F_CF
);
254 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
255 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
256 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
258 /* calculate the carry chain SEE NOTE AT TOP. */
259 cc
= (s
& d
) | ((~res
) & (s
| d
));
260 CONDITIONAL_SET_FLAG(XOR2(cc
>> 14), F_OF
);
261 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
265 /****************************************************************************
267 Implements the ADC instruction and side effects.
268 ****************************************************************************/
269 u32
adc_long(u32 d
, u32 s
)
271 register u32 lo
; /* all operands in native machine order */
276 if (ACCESS_FLAG(F_CF
)) {
277 lo
= 1 + (d
& 0xFFFF) + (s
& 0xFFFF);
281 lo
= (d
& 0xFFFF) + (s
& 0xFFFF);
284 hi
= (lo
>> 16) + (d
>> 16) + (s
>> 16);
286 CONDITIONAL_SET_FLAG(hi
& 0x10000, F_CF
);
287 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
288 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
289 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
291 /* calculate the carry chain SEE NOTE AT TOP. */
292 cc
= (s
& d
) | ((~res
) & (s
| d
));
293 CONDITIONAL_SET_FLAG(XOR2(cc
>> 30), F_OF
);
294 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
298 /****************************************************************************
300 Implements the ADD instruction and side effects.
301 ****************************************************************************/
302 u8
add_byte(u8 d
, u8 s
)
304 register u32 res
; /* all operands in native machine order */
308 CONDITIONAL_SET_FLAG(res
& 0x100, F_CF
);
309 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
310 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
311 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
313 /* calculate the carry chain SEE NOTE AT TOP. */
314 cc
= (s
& d
) | ((~res
) & (s
| d
));
315 CONDITIONAL_SET_FLAG(XOR2(cc
>> 6), F_OF
);
316 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
320 /****************************************************************************
322 Implements the ADD instruction and side effects.
323 ****************************************************************************/
324 u16
add_word(u16 d
, u16 s
)
326 register u32 res
; /* all operands in native machine order */
330 CONDITIONAL_SET_FLAG(res
& 0x10000, F_CF
);
331 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
332 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
333 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
335 /* calculate the carry chain SEE NOTE AT TOP. */
336 cc
= (s
& d
) | ((~res
) & (s
| d
));
337 CONDITIONAL_SET_FLAG(XOR2(cc
>> 14), F_OF
);
338 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
342 /****************************************************************************
344 Implements the ADD instruction and side effects.
345 ****************************************************************************/
346 u32
add_long(u32 d
, u32 s
)
348 register u32 lo
; /* all operands in native machine order */
353 lo
= (d
& 0xFFFF) + (s
& 0xFFFF);
355 hi
= (lo
>> 16) + (d
>> 16) + (s
>> 16);
357 CONDITIONAL_SET_FLAG(hi
& 0x10000, F_CF
);
358 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
359 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
360 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
362 /* calculate the carry chain SEE NOTE AT TOP. */
363 cc
= (s
& d
) | ((~res
) & (s
| d
));
364 CONDITIONAL_SET_FLAG(XOR2(cc
>> 30), F_OF
);
365 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
370 /****************************************************************************
372 Implements the AND instruction and side effects.
373 ****************************************************************************/
374 u8
and_byte(u8 d
, u8 s
)
376 register u8 res
; /* all operands in native machine order */
384 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
385 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
386 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
390 /****************************************************************************
392 Implements the AND instruction and side effects.
393 ****************************************************************************/
394 u16
and_word(u16 d
, u16 s
)
396 register u16 res
; /* all operands in native machine order */
404 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
405 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
406 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
410 /****************************************************************************
412 Implements the AND instruction and side effects.
413 ****************************************************************************/
414 u32
and_long(u32 d
, u32 s
)
416 register u32 res
; /* all operands in native machine order */
424 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
425 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
426 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
430 /****************************************************************************
432 Implements the CMP instruction and side effects.
433 ****************************************************************************/
434 u8
cmp_byte(u8 d
, u8 s
)
436 register u32 res
; /* all operands in native machine order */
441 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
442 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
443 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
445 /* calculate the borrow chain. See note at top */
446 bc
= (res
& (~d
| s
)) | (~d
& s
);
447 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
448 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
449 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
453 /****************************************************************************
455 Implements the CMP instruction and side effects.
456 ****************************************************************************/
457 u16
cmp_word(u16 d
, u16 s
)
459 register u32 res
; /* all operands in native machine order */
463 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
464 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
465 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
467 /* calculate the borrow chain. See note at top */
468 bc
= (res
& (~d
| s
)) | (~d
& s
);
469 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
470 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
471 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
475 /****************************************************************************
477 Implements the CMP instruction and side effects.
478 ****************************************************************************/
479 u32
cmp_long(u32 d
, u32 s
)
481 register u32 res
; /* all operands in native machine order */
485 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
486 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
487 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
489 /* calculate the borrow chain. See note at top */
490 bc
= (res
& (~d
| s
)) | (~d
& s
);
491 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
492 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
493 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
497 /****************************************************************************
499 Implements the DAA instruction and side effects.
500 ****************************************************************************/
504 if ((d
& 0xf) > 9 || ACCESS_FLAG(F_AF
)) {
508 if (res
> 0x9F || ACCESS_FLAG(F_CF
)) {
512 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
513 CONDITIONAL_SET_FLAG((res
& 0xFF) == 0, F_ZF
);
514 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
518 /****************************************************************************
520 Implements the DAS instruction and side effects.
521 ****************************************************************************/
524 if ((d
& 0xf) > 9 || ACCESS_FLAG(F_AF
)) {
528 if (d
> 0x9F || ACCESS_FLAG(F_CF
)) {
532 CONDITIONAL_SET_FLAG(d
& 0x80, F_SF
);
533 CONDITIONAL_SET_FLAG(d
== 0, F_ZF
);
534 CONDITIONAL_SET_FLAG(PARITY(d
& 0xff), F_PF
);
538 /****************************************************************************
540 Implements the DEC instruction and side effects.
541 ****************************************************************************/
544 register u32 res
; /* all operands in native machine order */
548 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
549 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
550 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
552 /* calculate the borrow chain. See note at top */
553 /* based on sub_byte, uses s==1. */
554 bc
= (res
& (~d
| 1)) | (~d
& 1);
555 /* carry flag unchanged */
556 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
557 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
561 /****************************************************************************
563 Implements the DEC instruction and side effects.
564 ****************************************************************************/
567 register u32 res
; /* all operands in native machine order */
571 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
572 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
573 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
575 /* calculate the borrow chain. See note at top */
576 /* based on the sub_byte routine, with s==1 */
577 bc
= (res
& (~d
| 1)) | (~d
& 1);
578 /* carry flag unchanged */
579 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
580 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
584 /****************************************************************************
586 Implements the DEC instruction and side effects.
587 ****************************************************************************/
590 register u32 res
; /* all operands in native machine order */
595 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
596 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
597 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
599 /* calculate the borrow chain. See note at top */
600 bc
= (res
& (~d
| 1)) | (~d
& 1);
601 /* carry flag unchanged */
602 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
603 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
607 /****************************************************************************
609 Implements the INC instruction and side effects.
610 ****************************************************************************/
613 register u32 res
; /* all operands in native machine order */
617 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
618 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
619 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
621 /* calculate the carry chain SEE NOTE AT TOP. */
622 cc
= ((1 & d
) | (~res
)) & (1 | d
);
623 CONDITIONAL_SET_FLAG(XOR2(cc
>> 6), F_OF
);
624 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
628 /****************************************************************************
630 Implements the INC instruction and side effects.
631 ****************************************************************************/
634 register u32 res
; /* all operands in native machine order */
638 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
639 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
640 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
642 /* calculate the carry chain SEE NOTE AT TOP. */
643 cc
= (1 & d
) | ((~res
) & (1 | d
));
644 CONDITIONAL_SET_FLAG(XOR2(cc
>> 14), F_OF
);
645 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
649 /****************************************************************************
651 Implements the INC instruction and side effects.
652 ****************************************************************************/
655 register u32 res
; /* all operands in native machine order */
659 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
660 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
661 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
663 /* calculate the carry chain SEE NOTE AT TOP. */
664 cc
= (1 & d
) | ((~res
) & (1 | d
));
665 CONDITIONAL_SET_FLAG(XOR2(cc
>> 30), F_OF
);
666 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
670 /****************************************************************************
672 Implements the OR instruction and side effects.
673 ****************************************************************************/
674 u8
or_byte(u8 d
, u8 s
)
676 register u8 res
; /* all operands in native machine order */
682 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
683 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
684 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
688 /****************************************************************************
690 Implements the OR instruction and side effects.
691 ****************************************************************************/
692 u16
or_word(u16 d
, u16 s
)
694 register u16 res
; /* all operands in native machine order */
697 /* set the carry flag to be bit 8 */
701 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
702 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
703 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
707 /****************************************************************************
709 Implements the OR instruction and side effects.
710 ****************************************************************************/
711 u32
or_long(u32 d
, u32 s
)
713 register u32 res
; /* all operands in native machine order */
717 /* set the carry flag to be bit 8 */
721 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
722 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
723 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
727 /****************************************************************************
729 Implements the OR instruction and side effects.
730 ****************************************************************************/
736 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
738 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
739 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
740 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
741 /* calculate the borrow chain --- modified such that d=0.
742 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
743 (the one used for sub) and simplifying, since ~d=0xff...,
744 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
745 ~d&s == s. So the simplified result is: */
747 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
748 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
752 /****************************************************************************
754 Implements the OR instruction and side effects.
755 ****************************************************************************/
761 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
763 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
764 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
765 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
767 /* calculate the borrow chain --- modified such that d=0.
768 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
769 (the one used for sub) and simplifying, since ~d=0xff...,
770 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
771 ~d&s == s. So the simplified result is: */
773 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
774 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
778 /****************************************************************************
780 Implements the OR instruction and side effects.
781 ****************************************************************************/
787 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
789 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
790 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
791 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
793 /* calculate the borrow chain --- modified such that d=0.
794 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
795 (the one used for sub) and simplifying, since ~d=0xff...,
796 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
797 ~d&s == s. So the simplified result is: */
799 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
800 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
804 /****************************************************************************
806 Implements the NOT instruction and side effects.
807 ****************************************************************************/
813 /****************************************************************************
815 Implements the NOT instruction and side effects.
816 ****************************************************************************/
822 /****************************************************************************
824 Implements the NOT instruction and side effects.
825 ****************************************************************************/
831 /****************************************************************************
833 Implements the RCL instruction and side effects.
834 ****************************************************************************/
835 u8
rcl_byte(u8 d
, u8 s
)
837 register unsigned int res
, cnt
, mask
, cf
;
839 /* s is the rotate distance. It varies from 0 - 8. */
842 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
844 want to rotate through the carry by "s" bits. We could
845 loop, but that's inefficient. So the width is 9,
846 and we split into three parts:
848 The new carry flag (was B_n)
849 the stuff in B_n-1 .. B_0
850 the stuff in B_7 .. B_n+1
852 The new rotate is done mod 9, and given this,
853 for a rotation of n bits (mod 9) the new carry flag is
854 then located n bits from the MSB. The low part is
855 then shifted up cnt bits, and the high part is or'd
856 in. Using CAPS for new values, and lowercase for the
857 original values, this can be expressed as:
861 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
863 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
866 if ((cnt
= s
% 9) != 0) {
867 /* extract the new CARRY FLAG. */
869 cf
= (d
>> (8 - cnt
)) & 0x1;
871 /* get the low stuff which rotated
872 into the range B_7 .. B_cnt */
873 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
874 /* note that the right hand side done by the mask */
875 res
= (d
<< cnt
) & 0xff;
877 /* now the high stuff which rotated around
878 into the positions B_cnt-2 .. B_0 */
879 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
880 /* shift it downward, 7-(n-2) = 9-n positions.
881 and mask off the result before or'ing in.
883 mask
= (1 << (cnt
- 1)) - 1;
884 res
|= (d
>> (9 - cnt
)) & mask
;
886 /* if the carry flag was set, or it in. */
887 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
889 res
|= 1 << (cnt
- 1);
891 /* set the new carry flag, based on the variable "cf" */
892 CONDITIONAL_SET_FLAG(cf
, F_CF
);
893 /* OVERFLOW is set *IFF* cnt==1, then it is the
894 xor of CF and the most significant bit. Blecck. */
895 /* parenthesized this expression since it appears to
896 be causing OF to be misset */
897 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 6) & 0x2)),
904 /****************************************************************************
906 Implements the RCL instruction and side effects.
907 ****************************************************************************/
908 u16
rcl_word(u16 d
, u8 s
)
910 register unsigned int res
, cnt
, mask
, cf
;
913 if ((cnt
= s
% 17) != 0) {
914 cf
= (d
>> (16 - cnt
)) & 0x1;
915 res
= (d
<< cnt
) & 0xffff;
916 mask
= (1 << (cnt
- 1)) - 1;
917 res
|= (d
>> (17 - cnt
)) & mask
;
918 if (ACCESS_FLAG(F_CF
)) {
919 res
|= 1 << (cnt
- 1);
921 CONDITIONAL_SET_FLAG(cf
, F_CF
);
922 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 14) & 0x2)),
928 /****************************************************************************
930 Implements the RCL instruction and side effects.
931 ****************************************************************************/
932 u32
rcl_long(u32 d
, u8 s
)
934 register u32 res
, cnt
, mask
, cf
;
937 if ((cnt
= s
% 33) != 0) {
938 cf
= (d
>> (32 - cnt
)) & 0x1;
939 res
= (d
<< cnt
) & 0xffffffff;
940 mask
= (1 << (cnt
- 1)) - 1;
941 res
|= (d
>> (33 - cnt
)) & mask
;
942 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
943 res
|= 1 << (cnt
- 1);
945 CONDITIONAL_SET_FLAG(cf
, F_CF
);
946 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 30) & 0x2)),
952 /****************************************************************************
954 Implements the RCR instruction and side effects.
955 ****************************************************************************/
956 u8
rcr_byte(u8 d
, u8 s
)
959 u32 mask
, cf
, ocf
= 0;
961 /* rotate right through carry */
963 s is the rotate distance. It varies from 0 - 8.
964 d is the byte object rotated.
968 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
970 The new rotate is done mod 9, and given this,
971 for a rotation of n bits (mod 9) the new carry flag is
972 then located n bits from the LSB. The low part is
973 then shifted up cnt bits, and the high part is or'd
974 in. Using CAPS for new values, and lowercase for the
975 original values, this can be expressed as:
979 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
981 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
984 if ((cnt
= s
% 9) != 0) {
985 /* extract the new CARRY FLAG. */
989 /* note hackery here. Access_flag(..) evaluates to either
991 non-zero if flag is set.
992 doing access_flag(..) != 0 casts that into either
993 0..1 in any representation of the flags register
994 (i.e. packed bit array or unpacked.)
996 ocf
= ACCESS_FLAG(F_CF
) != 0;
998 cf
= (d
>> (cnt
- 1)) & 0x1;
1000 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
1001 /* note that the right hand side done by the mask
1002 This is effectively done by shifting the
1003 object to the right. The result must be masked,
1004 in case the object came in and was treated
1005 as a negative number. Needed??? */
1007 mask
= (1 << (8 - cnt
)) - 1;
1008 res
= (d
>> cnt
) & mask
;
1010 /* now the high stuff which rotated around
1011 into the positions B_cnt-2 .. B_0 */
1012 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
1013 /* shift it downward, 7-(n-2) = 9-n positions.
1014 and mask off the result before or'ing in.
1016 res
|= (d
<< (9 - cnt
));
1018 /* if the carry flag was set, or it in. */
1019 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
1021 res
|= 1 << (8 - cnt
);
1023 /* set the new carry flag, based on the variable "cf" */
1024 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1025 /* OVERFLOW is set *IFF* cnt==1, then it is the
1026 xor of CF and the most significant bit. Blecck. */
1027 /* parenthesized... */
1029 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 6) & 0x2)),
1036 /****************************************************************************
1038 Implements the RCR instruction and side effects.
1039 ****************************************************************************/
1040 u16
rcr_word(u16 d
, u8 s
)
1043 u32 mask
, cf
, ocf
= 0;
1045 /* rotate right through carry */
1047 if ((cnt
= s
% 17) != 0) {
1050 ocf
= ACCESS_FLAG(F_CF
) != 0;
1052 cf
= (d
>> (cnt
- 1)) & 0x1;
1053 mask
= (1 << (16 - cnt
)) - 1;
1054 res
= (d
>> cnt
) & mask
;
1055 res
|= (d
<< (17 - cnt
));
1056 if (ACCESS_FLAG(F_CF
)) {
1057 res
|= 1 << (16 - cnt
);
1059 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1061 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 14) & 0x2)),
1068 /****************************************************************************
1070 Implements the RCR instruction and side effects.
1071 ****************************************************************************/
1072 u32
rcr_long(u32 d
, u8 s
)
1075 u32 mask
, cf
, ocf
= 0;
1077 /* rotate right through carry */
1079 if ((cnt
= s
% 33) != 0) {
1082 ocf
= ACCESS_FLAG(F_CF
) != 0;
1084 cf
= (d
>> (cnt
- 1)) & 0x1;
1085 mask
= (1 << (32 - cnt
)) - 1;
1086 res
= (d
>> cnt
) & mask
;
1088 res
|= (d
<< (33 - cnt
));
1089 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
1090 res
|= 1 << (32 - cnt
);
1092 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1094 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 30) & 0x2)),
1101 /****************************************************************************
1103 Implements the ROL instruction and side effects.
1104 ****************************************************************************/
1105 u8
rol_byte(u8 d
, u8 s
)
1107 register unsigned int res
, cnt
, mask
;
1111 s is the rotate distance. It varies from 0 - 8.
1112 d is the byte object rotated.
1118 The new rotate is done mod 8.
1119 Much simpler than the "rcl" or "rcr" operations.
1122 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1123 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1126 if ((cnt
= s
% 8) != 0) {
1127 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1130 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1131 mask
= (1 << cnt
) - 1;
1132 res
|= (d
>> (8 - cnt
)) & mask
;
1134 /* set the new carry flag, Note that it is the low order
1135 bit of the result!!! */
1136 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1137 /* OVERFLOW is set *IFF* s==1, then it is the
1138 xor of CF and the most significant bit. Blecck. */
1139 CONDITIONAL_SET_FLAG(s
== 1 &&
1140 XOR2((res
& 0x1) + ((res
>> 6) & 0x2)),
1143 /* set the new carry flag, Note that it is the low order
1144 bit of the result!!! */
1145 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1150 /****************************************************************************
1152 Implements the ROL instruction and side effects.
1153 ****************************************************************************/
1154 u16
rol_word(u16 d
, u8 s
)
1156 register unsigned int res
, cnt
, mask
;
1159 if ((cnt
= s
% 16) != 0) {
1161 mask
= (1 << cnt
) - 1;
1162 res
|= (d
>> (16 - cnt
)) & mask
;
1163 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1164 CONDITIONAL_SET_FLAG(s
== 1 &&
1165 XOR2((res
& 0x1) + ((res
>> 14) & 0x2)),
1168 /* set the new carry flag, Note that it is the low order
1169 bit of the result!!! */
1170 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1175 /****************************************************************************
1177 Implements the ROL instruction and side effects.
1178 ****************************************************************************/
1179 u32
rol_long(u32 d
, u8 s
)
1181 register u32 res
, cnt
, mask
;
1184 if ((cnt
= s
% 32) != 0) {
1186 mask
= (1 << cnt
) - 1;
1187 res
|= (d
>> (32 - cnt
)) & mask
;
1188 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1189 CONDITIONAL_SET_FLAG(s
== 1 &&
1190 XOR2((res
& 0x1) + ((res
>> 30) & 0x2)),
1193 /* set the new carry flag, Note that it is the low order
1194 bit of the result!!! */
1195 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
1200 /****************************************************************************
1202 Implements the ROR instruction and side effects.
1203 ****************************************************************************/
1204 u8
ror_byte(u8 d
, u8 s
)
1206 register unsigned int res
, cnt
, mask
;
1210 s is the rotate distance. It varies from 0 - 8.
1211 d is the byte object rotated.
1217 The rotate is done mod 8.
1220 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1221 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1224 if ((cnt
= s
% 8) != 0) { /* not a typo, do nada if cnt==0 */
1225 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1226 res
= (d
<< (8 - cnt
));
1228 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1229 mask
= (1 << (8 - cnt
)) - 1;
1230 res
|= (d
>> (cnt
)) & mask
;
1232 /* set the new carry flag, Note that it is the low order
1233 bit of the result!!! */
1234 CONDITIONAL_SET_FLAG(res
& 0x80, F_CF
);
1235 /* OVERFLOW is set *IFF* s==1, then it is the
1236 xor of the two most significant bits. Blecck. */
1237 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 6), F_OF
);
1238 } else if (s
!= 0) {
1239 /* set the new carry flag, Note that it is the low order
1240 bit of the result!!! */
1241 CONDITIONAL_SET_FLAG(res
& 0x80, F_CF
);
1246 /****************************************************************************
1248 Implements the ROR instruction and side effects.
1249 ****************************************************************************/
1250 u16
ror_word(u16 d
, u8 s
)
1252 register unsigned int res
, cnt
, mask
;
1255 if ((cnt
= s
% 16) != 0) {
1256 res
= (d
<< (16 - cnt
));
1257 mask
= (1 << (16 - cnt
)) - 1;
1258 res
|= (d
>> (cnt
)) & mask
;
1259 CONDITIONAL_SET_FLAG(res
& 0x8000, F_CF
);
1260 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 14), F_OF
);
1261 } else if (s
!= 0) {
1262 /* set the new carry flag, Note that it is the low order
1263 bit of the result!!! */
1264 CONDITIONAL_SET_FLAG(res
& 0x8000, F_CF
);
1269 /****************************************************************************
1271 Implements the ROR instruction and side effects.
1272 ****************************************************************************/
1273 u32
ror_long(u32 d
, u8 s
)
1275 register u32 res
, cnt
, mask
;
1278 if ((cnt
= s
% 32) != 0) {
1279 res
= (d
<< (32 - cnt
));
1280 mask
= (1 << (32 - cnt
)) - 1;
1281 res
|= (d
>> (cnt
)) & mask
;
1282 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_CF
);
1283 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 30), F_OF
);
1284 } else if (s
!= 0) {
1285 /* set the new carry flag, Note that it is the low order
1286 bit of the result!!! */
1287 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_CF
);
1292 /****************************************************************************
1294 Implements the SHL instruction and side effects.
1295 ****************************************************************************/
1296 u8
shl_byte(u8 d
, u8 s
)
1298 unsigned int cnt
, res
, cf
;
1303 /* last bit shifted out goes into carry flag */
1306 cf
= d
& (1 << (8 - cnt
));
1307 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1308 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
1309 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1310 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1316 /* Needs simplification. */
1317 CONDITIONAL_SET_FLAG(
1318 (((res
& 0x80) == 0x80) ^
1319 (ACCESS_FLAG(F_CF
) != 0)),
1320 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1327 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x80, F_CF
);
1336 /****************************************************************************
1338 Implements the SHL instruction and side effects.
1339 ****************************************************************************/
1340 u16
shl_word(u16 d
, u8 s
)
1342 unsigned int cnt
, res
, cf
;
1348 cf
= d
& (1 << (16 - cnt
));
1349 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1350 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1351 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1352 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1358 CONDITIONAL_SET_FLAG(
1359 (((res
& 0x8000) == 0x8000) ^
1360 (ACCESS_FLAG(F_CF
) != 0)),
1367 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x8000, F_CF
);
1376 /****************************************************************************
1378 Implements the SHL instruction and side effects.
1379 ****************************************************************************/
1380 u32
shl_long(u32 d
, u8 s
)
1382 unsigned int cnt
, res
, cf
;
1388 cf
= d
& (1 << (32 - cnt
));
1389 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1390 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1391 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1392 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1397 CONDITIONAL_SET_FLAG((((res
& 0x80000000) == 0x80000000) ^
1398 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
1404 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x80000000, F_CF
);
1413 /****************************************************************************
1415 Implements the SHR instruction and side effects.
1416 ****************************************************************************/
1417 u8
shr_byte(u8 d
, u8 s
)
1419 unsigned int cnt
, res
, cf
;
1424 cf
= d
& (1 << (cnt
- 1));
1426 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1427 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
1428 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1429 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1435 CONDITIONAL_SET_FLAG(XOR2(res
>> 6), F_OF
);
1441 CONDITIONAL_SET_FLAG((d
>> (s
-1)) & 0x1, F_CF
);
1450 /****************************************************************************
1452 Implements the SHR instruction and side effects.
1453 ****************************************************************************/
1454 u16
shr_word(u16 d
, u8 s
)
1456 unsigned int cnt
, res
, cf
;
1461 cf
= d
& (1 << (cnt
- 1));
1463 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1464 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1465 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1466 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1472 CONDITIONAL_SET_FLAG(XOR2(res
>> 14), F_OF
);
1487 /****************************************************************************
1489 Implements the SHR instruction and side effects.
1490 ****************************************************************************/
1491 u32
shr_long(u32 d
, u8 s
)
1493 unsigned int cnt
, res
, cf
;
1498 cf
= d
& (1 << (cnt
- 1));
1500 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1501 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1502 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1503 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1508 CONDITIONAL_SET_FLAG(XOR2(res
>> 30), F_OF
);
1523 /****************************************************************************
1525 Implements the SAR instruction and side effects.
1526 ****************************************************************************/
1527 u8
sar_byte(u8 d
, u8 s
)
1529 unsigned int cnt
, res
, cf
, mask
, sf
;
1534 if (cnt
> 0 && cnt
< 8) {
1535 mask
= (1 << (8 - cnt
)) - 1;
1536 cf
= d
& (1 << (cnt
- 1));
1537 res
= (d
>> cnt
) & mask
;
1538 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1542 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
1543 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1544 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1545 } else if (cnt
>= 8) {
1563 /****************************************************************************
1565 Implements the SAR instruction and side effects.
1566 ****************************************************************************/
1567 u16
sar_word(u16 d
, u8 s
)
1569 unsigned int cnt
, res
, cf
, mask
, sf
;
1574 if (cnt
> 0 && cnt
< 16) {
1575 mask
= (1 << (16 - cnt
)) - 1;
1576 cf
= d
& (1 << (cnt
- 1));
1577 res
= (d
>> cnt
) & mask
;
1578 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1582 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1583 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1584 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1585 } else if (cnt
>= 16) {
1603 /****************************************************************************
1605 Implements the SAR instruction and side effects.
1606 ****************************************************************************/
1607 u32
sar_long(u32 d
, u8 s
)
1609 u32 cnt
, res
, cf
, mask
, sf
;
1611 sf
= d
& 0x80000000;
1614 if (cnt
> 0 && cnt
< 32) {
1615 mask
= (1 << (32 - cnt
)) - 1;
1616 cf
= d
& (1 << (cnt
- 1));
1617 res
= (d
>> cnt
) & mask
;
1618 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1622 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1623 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1624 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1625 } else if (cnt
>= 32) {
1643 /****************************************************************************
1645 Implements the SHLD instruction and side effects.
1646 ****************************************************************************/
1647 u16
shld_word (u16 d
, u16 fill
, u8 s
)
1649 unsigned int cnt
, res
, cf
;
1654 res
= (d
<< cnt
) | (fill
>> (16-cnt
));
1655 cf
= d
& (1 << (16 - cnt
));
1656 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1657 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1658 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1659 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1664 CONDITIONAL_SET_FLAG((((res
& 0x8000) == 0x8000) ^
1665 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
1671 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x8000, F_CF
);
1680 /****************************************************************************
1682 Implements the SHLD instruction and side effects.
1683 ****************************************************************************/
1684 u32
shld_long (u32 d
, u32 fill
, u8 s
)
1686 unsigned int cnt
, res
, cf
;
1691 res
= (d
<< cnt
) | (fill
>> (32-cnt
));
1692 cf
= d
& (1 << (32 - cnt
));
1693 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1694 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1695 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1696 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1701 CONDITIONAL_SET_FLAG((((res
& 0x80000000) == 0x80000000) ^
1702 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
1708 CONDITIONAL_SET_FLAG((d
<< (s
-1)) & 0x80000000, F_CF
);
1717 /****************************************************************************
1719 Implements the SHRD instruction and side effects.
1720 ****************************************************************************/
1721 u16
shrd_word (u16 d
, u16 fill
, u8 s
)
1723 unsigned int cnt
, res
, cf
;
1728 cf
= d
& (1 << (cnt
- 1));
1729 res
= (d
>> cnt
) | (fill
<< (16 - cnt
));
1730 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1731 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1732 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1733 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1739 CONDITIONAL_SET_FLAG(XOR2(res
>> 14), F_OF
);
1754 /****************************************************************************
1756 Implements the SHRD instruction and side effects.
1757 ****************************************************************************/
1758 u32
shrd_long (u32 d
, u32 fill
, u8 s
)
1760 unsigned int cnt
, res
, cf
;
1765 cf
= d
& (1 << (cnt
- 1));
1766 res
= (d
>> cnt
) | (fill
<< (32 - cnt
));
1767 CONDITIONAL_SET_FLAG(cf
, F_CF
);
1768 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1769 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1770 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1775 CONDITIONAL_SET_FLAG(XOR2(res
>> 30), F_OF
);
1790 /****************************************************************************
1792 Implements the SBB instruction and side effects.
1793 ****************************************************************************/
1794 u8
sbb_byte(u8 d
, u8 s
)
1796 register u32 res
; /* all operands in native machine order */
1799 if (ACCESS_FLAG(F_CF
))
1803 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1804 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
1805 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1807 /* calculate the borrow chain. See note at top */
1808 bc
= (res
& (~d
| s
)) | (~d
& s
);
1809 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
1810 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
1811 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1815 /****************************************************************************
1817 Implements the SBB instruction and side effects.
1818 ****************************************************************************/
1819 u16
sbb_word(u16 d
, u16 s
)
1821 register u32 res
; /* all operands in native machine order */
1824 if (ACCESS_FLAG(F_CF
))
1828 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1829 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1830 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1832 /* calculate the borrow chain. See note at top */
1833 bc
= (res
& (~d
| s
)) | (~d
& s
);
1834 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
1835 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
1836 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1840 /****************************************************************************
1842 Implements the SBB instruction and side effects.
1843 ****************************************************************************/
1844 u32
sbb_long(u32 d
, u32 s
)
1846 register u32 res
; /* all operands in native machine order */
1849 if (ACCESS_FLAG(F_CF
))
1853 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1854 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1855 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1857 /* calculate the borrow chain. See note at top */
1858 bc
= (res
& (~d
| s
)) | (~d
& s
);
1859 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
1860 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
1861 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1865 /****************************************************************************
1867 Implements the SUB instruction and side effects.
1868 ****************************************************************************/
1869 u8
sub_byte(u8 d
, u8 s
)
1871 register u32 res
; /* all operands in native machine order */
1875 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1876 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
1877 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1879 /* calculate the borrow chain. See note at top */
1880 bc
= (res
& (~d
| s
)) | (~d
& s
);
1881 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
1882 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
1883 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1887 /****************************************************************************
1889 Implements the SUB instruction and side effects.
1890 ****************************************************************************/
1891 u16
sub_word(u16 d
, u16 s
)
1893 register u32 res
; /* all operands in native machine order */
1897 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1898 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
1899 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1901 /* calculate the borrow chain. See note at top */
1902 bc
= (res
& (~d
| s
)) | (~d
& s
);
1903 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
1904 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
1905 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1909 /****************************************************************************
1911 Implements the SUB instruction and side effects.
1912 ****************************************************************************/
1913 u32
sub_long(u32 d
, u32 s
)
1915 register u32 res
; /* all operands in native machine order */
1919 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1920 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
1921 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1923 /* calculate the borrow chain. See note at top */
1924 bc
= (res
& (~d
| s
)) | (~d
& s
);
1925 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
1926 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
1927 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
1931 /****************************************************************************
1933 Implements the TEST instruction and side effects.
1934 ****************************************************************************/
1935 void test_byte(u8 d
, u8 s
)
1937 register u32 res
; /* all operands in native machine order */
1942 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1943 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
1944 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1945 /* AF == dont care */
1949 /****************************************************************************
1951 Implements the TEST instruction and side effects.
1952 ****************************************************************************/
1953 void test_word(u16 d
, u16 s
)
1955 register u32 res
; /* all operands in native machine order */
1960 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
1961 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
1962 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1963 /* AF == dont care */
1967 /****************************************************************************
1969 Implements the TEST instruction and side effects.
1970 ****************************************************************************/
1971 void test_long(u32 d
, u32 s
)
1973 register u32 res
; /* all operands in native machine order */
1978 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
1979 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
1980 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
1981 /* AF == dont care */
1985 /****************************************************************************
1987 Implements the XOR instruction and side effects.
1988 ****************************************************************************/
1989 u8
xor_byte(u8 d
, u8 s
)
1991 register u8 res
; /* all operands in native machine order */
1995 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
1996 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
1997 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
2003 /****************************************************************************
2005 Implements the XOR instruction and side effects.
2006 ****************************************************************************/
2007 u16
xor_word(u16 d
, u16 s
)
2009 register u16 res
; /* all operands in native machine order */
2013 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
2014 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
2015 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
2021 /****************************************************************************
2023 Implements the XOR instruction and side effects.
2024 ****************************************************************************/
2025 u32
xor_long(u32 d
, u32 s
)
2027 register u32 res
; /* all operands in native machine order */
2031 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
2032 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
2033 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
2039 /****************************************************************************
2041 Implements the IMUL instruction and side effects.
2042 ****************************************************************************/
2043 void imul_byte(u8 s
)
2045 s16 res
= (s16
)((s8
)M
.x86
.R_AL
* (s8
)s
);
2048 if (((M
.x86
.R_AL
& 0x80) == 0 && M
.x86
.R_AH
== 0x00) ||
2049 ((M
.x86
.R_AL
& 0x80) != 0 && M
.x86
.R_AH
== 0xFF)) {
2058 /****************************************************************************
2060 Implements the IMUL instruction and side effects.
2061 ****************************************************************************/
2062 void imul_word(u16 s
)
2064 s32 res
= (s16
)M
.x86
.R_AX
* (s16
)s
;
2066 M
.x86
.R_AX
= (u16
)res
;
2067 M
.x86
.R_DX
= (u16
)(res
>> 16);
2068 if (((M
.x86
.R_AX
& 0x8000) == 0 && M
.x86
.R_DX
== 0x00) ||
2069 ((M
.x86
.R_AX
& 0x8000) != 0 && M
.x86
.R_DX
== 0xFF)) {
2078 /****************************************************************************
2080 Implements the IMUL instruction and side effects.
2081 ****************************************************************************/
2082 void imul_long_direct(u32
*res_lo
, u32
* res_hi
,u32 d
, u32 s
)
2084 #ifdef __HAS_LONG_LONG__
2085 s64 res
= (s64
)(s32
)d
* (s32
)s
;
2088 *res_hi
= (u32
)(res
>> 32);
2090 u32 d_lo
,d_hi
,d_sign
;
2091 u32 s_lo
,s_hi
,s_sign
;
2092 u32 rlo_lo
,rlo_hi
,rhi_lo
;
2094 if ((d_sign
= d
& 0x80000000) != 0)
2098 if ((s_sign
= s
& 0x80000000) != 0)
2102 rlo_lo
= d_lo
* s_lo
;
2103 rlo_hi
= (d_hi
* s_lo
+ d_lo
* s_hi
) + (rlo_lo
>> 16);
2104 rhi_lo
= d_hi
* s_hi
+ (rlo_hi
>> 16);
2105 *res_lo
= (rlo_hi
<< 16) | (rlo_lo
& 0xFFFF);
2107 if (d_sign
!= s_sign
) {
2109 s
= (((d
& 0xFFFF) + 1) >> 16) + (d
>> 16);
2110 *res_lo
= ~*res_lo
+1;
2111 *res_hi
= ~*res_hi
+(s
>> 16);
2116 /****************************************************************************
2118 Implements the IMUL instruction and side effects.
2119 ****************************************************************************/
2120 void imul_long(u32 s
)
2122 imul_long_direct(&M
.x86
.R_EAX
,&M
.x86
.R_EDX
,M
.x86
.R_EAX
,s
);
2123 if (((M
.x86
.R_EAX
& 0x80000000) == 0 && M
.x86
.R_EDX
== 0x00) ||
2124 ((M
.x86
.R_EAX
& 0x80000000) != 0 && M
.x86
.R_EDX
== 0xFF)) {
2133 /****************************************************************************
2135 Implements the MUL instruction and side effects.
2136 ****************************************************************************/
2139 u16 res
= (u16
)(M
.x86
.R_AL
* s
);
2142 if (M
.x86
.R_AH
== 0) {
2151 /****************************************************************************
2153 Implements the MUL instruction and side effects.
2154 ****************************************************************************/
2155 void mul_word(u16 s
)
2157 u32 res
= M
.x86
.R_AX
* s
;
2159 M
.x86
.R_AX
= (u16
)res
;
2160 M
.x86
.R_DX
= (u16
)(res
>> 16);
2161 if (M
.x86
.R_DX
== 0) {
2170 /****************************************************************************
2172 Implements the MUL instruction and side effects.
2173 ****************************************************************************/
2174 void mul_long(u32 s
)
2176 #ifdef __HAS_LONG_LONG__
2177 u64 res
= (u64
)M
.x86
.R_EAX
* s
;
2179 M
.x86
.R_EAX
= (u32
)res
;
2180 M
.x86
.R_EDX
= (u32
)(res
>> 32);
2184 u32 rlo_lo
,rlo_hi
,rhi_lo
;
2191 rlo_lo
= a_lo
* s_lo
;
2192 rlo_hi
= (a_hi
* s_lo
+ a_lo
* s_hi
) + (rlo_lo
>> 16);
2193 rhi_lo
= a_hi
* s_hi
+ (rlo_hi
>> 16);
2194 M
.x86
.R_EAX
= (rlo_hi
<< 16) | (rlo_lo
& 0xFFFF);
2195 M
.x86
.R_EDX
= rhi_lo
;
2198 if (M
.x86
.R_EDX
== 0) {
2207 /****************************************************************************
2209 Implements the IDIV instruction and side effects.
2210 ****************************************************************************/
2211 void idiv_byte(u8 s
)
2215 dvd
= (s16
)M
.x86
.R_AX
;
2217 x86emu_intr_raise(0);
2222 if (abs(div
) > 0x7f) {
2223 x86emu_intr_raise(0);
2226 M
.x86
.R_AL
= (s8
) div
;
2227 M
.x86
.R_AH
= (s8
) mod
;
2230 /****************************************************************************
2232 Implements the IDIV instruction and side effects.
2233 ****************************************************************************/
2234 void idiv_word(u16 s
)
2238 dvd
= (((s32
)M
.x86
.R_DX
) << 16) | M
.x86
.R_AX
;
2240 x86emu_intr_raise(0);
2245 if (abs(div
) > 0x7fff) {
2246 x86emu_intr_raise(0);
2251 CONDITIONAL_SET_FLAG(div
== 0, F_ZF
);
2252 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
2254 M
.x86
.R_AX
= (u16
)div
;
2255 M
.x86
.R_DX
= (u16
)mod
;
2258 /****************************************************************************
2260 Implements the IDIV instruction and side effects.
2261 ****************************************************************************/
2262 void idiv_long(u32 s
)
2264 #ifdef __HAS_LONG_LONG__
2267 dvd
= (((s64
)M
.x86
.R_EDX
) << 32) | M
.x86
.R_EAX
;
2269 x86emu_intr_raise(0);
2274 if (abs(div
) > 0x7fffffff) {
2275 x86emu_intr_raise(0);
2280 s32 h_dvd
= M
.x86
.R_EDX
;
2281 u32 l_dvd
= M
.x86
.R_EAX
;
2282 u32 abs_s
= s
& 0x7FFFFFFF;
2283 u32 abs_h_dvd
= h_dvd
& 0x7FFFFFFF;
2284 u32 h_s
= abs_s
>> 1;
2285 u32 l_s
= abs_s
<< 31;
2290 x86emu_intr_raise(0);
2295 carry
= (l_dvd
>= l_s
) ? 0 : 1;
2297 if (abs_h_dvd
< (h_s
+ carry
)) {
2299 l_s
= abs_s
<< (--counter
);
2302 abs_h_dvd
-= (h_s
+ carry
);
2303 l_dvd
= carry
? ((0xFFFFFFFF - l_s
) + l_dvd
+ 1)
2306 l_s
= abs_s
<< (--counter
);
2311 } while (counter
> -1);
2313 if (abs_h_dvd
|| (l_dvd
> abs_s
)) {
2314 x86emu_intr_raise(0);
2318 div
|= ((h_dvd
& 0x10000000) ^ (s
& 0x10000000));
2326 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
2328 M
.x86
.R_EAX
= (u32
)div
;
2329 M
.x86
.R_EDX
= (u32
)mod
;
2332 /****************************************************************************
2334 Implements the DIV instruction and side effects.
2335 ****************************************************************************/
2342 x86emu_intr_raise(0);
2347 if (abs(div
) > 0xff) {
2348 x86emu_intr_raise(0);
2351 M
.x86
.R_AL
= (u8
)div
;
2352 M
.x86
.R_AH
= (u8
)mod
;
2355 /****************************************************************************
2357 Implements the DIV instruction and side effects.
2358 ****************************************************************************/
2359 void div_word(u16 s
)
2363 dvd
= (((u32
)M
.x86
.R_DX
) << 16) | M
.x86
.R_AX
;
2365 x86emu_intr_raise(0);
2370 if (abs(div
) > 0xffff) {
2371 x86emu_intr_raise(0);
2376 CONDITIONAL_SET_FLAG(div
== 0, F_ZF
);
2377 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
2379 M
.x86
.R_AX
= (u16
)div
;
2380 M
.x86
.R_DX
= (u16
)mod
;
2383 /****************************************************************************
2385 Implements the DIV instruction and side effects.
2386 ****************************************************************************/
2387 void div_long(u32 s
)
2389 #ifdef __HAS_LONG_LONG__
2392 dvd
= (((u64
)M
.x86
.R_EDX
) << 32) | M
.x86
.R_EAX
;
2394 x86emu_intr_raise(0);
2399 if (abs(div
) > 0xffffffff) {
2400 x86emu_intr_raise(0);
2405 s32 h_dvd
= M
.x86
.R_EDX
;
2406 u32 l_dvd
= M
.x86
.R_EAX
;
2414 x86emu_intr_raise(0);
2419 carry
= (l_dvd
>= l_s
) ? 0 : 1;
2421 if (h_dvd
< (h_s
+ carry
)) {
2423 l_s
= s
<< (--counter
);
2426 h_dvd
-= (h_s
+ carry
);
2427 l_dvd
= carry
? ((0xFFFFFFFF - l_s
) + l_dvd
+ 1)
2430 l_s
= s
<< (--counter
);
2435 } while (counter
> -1);
2437 if (h_dvd
|| (l_dvd
> s
)) {
2438 x86emu_intr_raise(0);
2447 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
2449 M
.x86
.R_EAX
= (u32
)div
;
2450 M
.x86
.R_EDX
= (u32
)mod
;
2453 /****************************************************************************
2455 Implements the IN string instruction and side effects.
2456 ****************************************************************************/
2461 if (ACCESS_FLAG(F_DF
)) {
2464 if (M
.x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2465 /* dont care whether REPE or REPNE */
2466 /* in until CX is ZERO. */
2467 u32 count
= ((M
.x86
.mode
& SYSMODE_PREFIX_DATA
) ?
2468 M
.x86
.R_ECX
: M
.x86
.R_CX
);
2472 store_data_byte_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,
2473 (*sys_inb
)(M
.x86
.R_DX
));
2480 store_data_word_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,
2481 (*sys_inw
)(M
.x86
.R_DX
));
2487 store_data_long_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,
2488 (*sys_inl
)(M
.x86
.R_DX
));
2494 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
2497 M
.x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2501 store_data_byte_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,
2502 (*sys_inb
)(M
.x86
.R_DX
));
2505 store_data_word_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,
2506 (*sys_inw
)(M
.x86
.R_DX
));
2509 store_data_long_abs(M
.x86
.R_ES
, M
.x86
.R_DI
,
2510 (*sys_inl
)(M
.x86
.R_DX
));
2517 /****************************************************************************
2519 Implements the OUT string instruction and side effects.
2520 ****************************************************************************/
2525 if (ACCESS_FLAG(F_DF
)) {
2528 if (M
.x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2529 /* dont care whether REPE or REPNE */
2530 /* out until CX is ZERO. */
2531 u32 count
= ((M
.x86
.mode
& SYSMODE_PREFIX_DATA
) ?
2532 M
.x86
.R_ECX
: M
.x86
.R_CX
);
2536 (*sys_outb
)(M
.x86
.R_DX
,
2537 fetch_data_byte_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2544 (*sys_outw
)(M
.x86
.R_DX
,
2545 fetch_data_word_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2551 (*sys_outl
)(M
.x86
.R_DX
,
2552 fetch_data_long_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2558 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
2561 M
.x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2565 (*sys_outb
)(M
.x86
.R_DX
,
2566 fetch_data_byte_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2569 (*sys_outw
)(M
.x86
.R_DX
,
2570 fetch_data_word_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2573 (*sys_outl
)(M
.x86
.R_DX
,
2574 fetch_data_long_abs(M
.x86
.R_ES
, M
.x86
.R_SI
));
2581 /****************************************************************************
2583 addr - Address to fetch word from
2586 Fetches a word from emulator memory using an absolute address.
2587 ****************************************************************************/
2588 u16
mem_access_word(int addr
)
2590 DB( if (CHECK_MEM_ACCESS())
2591 x86emu_check_mem_access(addr
);)
2592 return (*sys_rdw
)(addr
);
2595 /****************************************************************************
2597 Pushes a word onto the stack.
2599 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2600 ****************************************************************************/
2601 void push_word(u16 w
)
2603 DB( if (CHECK_SP_ACCESS())
2604 x86emu_check_sp_access();)
2606 (*sys_wrw
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
, w
);
2609 /****************************************************************************
2611 Pushes a long onto the stack.
2613 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2614 ****************************************************************************/
2615 void push_long(u32 w
)
2617 DB( if (CHECK_SP_ACCESS())
2618 x86emu_check_sp_access();)
2620 (*sys_wrl
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
, w
);
2623 /****************************************************************************
2625 Pops a word from the stack.
2627 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2628 ****************************************************************************/
2633 DB( if (CHECK_SP_ACCESS())
2634 x86emu_check_sp_access();)
2635 res
= (*sys_rdw
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
);
2640 /****************************************************************************
2642 Pops a long from the stack.
2644 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2645 ****************************************************************************/
2650 DB( if (CHECK_SP_ACCESS())
2651 x86emu_check_sp_access();)
2652 res
= (*sys_rdl
)(((u32
)M
.x86
.R_SS
<< 4) + M
.x86
.R_SP
);