soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / device / oprom / x86emu / prim_ops.c
blob2350ac1490909a9755fc2af9376c85e15f9919c2
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 * ========================================================================
31 * Language: ANSI C
32 * Environment: Any
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.
51 * a b cin r cout
52 * 0 0 0 0 0
53 * 0 0 1 1 0
54 * 0 1 0 1 0
55 * 0 1 1 0 1
56 * 1 0 0 1 0
57 * 1 0 1 0 1
58 * 1 1 0 0 1
59 * 1 1 1 1 1
61 * Construction of table for cout:
63 * ab
64 * r \ 00 01 11 10
65 * |------------------
66 * 0 | 0 1 1 1
67 * 1 | 0 0 1 0
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.
78 * a b bin r bout
79 * 0 0 0 0 0
80 * 0 0 1 1 1
81 * 0 1 0 1 1
82 * 0 1 1 0 1
83 * 1 0 0 1 0
84 * 1 0 1 0 0
85 * 1 1 0 0 0
86 * 1 1 1 1 1
88 * Construction of table for cout:
90 * ab
91 * r \ 00 01 11 10
92 * |------------------
93 * 0 | 0 1 0 0
94 * 1 | 1 1 1 0
96 * By inspection, one gets: bc = a'b + r(a' + b)
98 ****************************************************************************/
100 #define PRIM_OPS_NO_REDEFINE_ASM
101 #include "x86emui.h"
103 #define abs(x) ({ \
104 int __x = (x); \
105 (__x < 0) ? -__x : __x; \
108 #define labs(x) ({ \
109 long __x = (x); \
110 (__x < 0) ? -__x : __x; \
113 /*------------------------- Global Variables ------------------------------*/
115 static u32 x86emu_parity_tab[8] =
117 0x96696996,
118 0x69969669,
119 0x69969669,
120 0x96696996,
121 0x69969669,
122 0x96696996,
123 0x96696996,
124 0x69969669,
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 /****************************************************************************
135 REMARKS:
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)
167 CLEAR_FLAG(F_OF);
168 CLEAR_FLAG(F_CF);
169 CLEAR_FLAG(F_AF);
170 set_szp_flags_8(res);
173 static void no_carry_word_side_eff(u16 res)
175 CLEAR_FLAG(F_OF);
176 CLEAR_FLAG(F_CF);
177 CLEAR_FLAG(F_AF);
178 set_szp_flags_16(res);
181 static void no_carry_long_side_eff(u32 res)
183 CLEAR_FLAG(F_OF);
184 CLEAR_FLAG(F_CF);
185 CLEAR_FLAG(F_AF);
186 set_szp_flags_32(res);
189 static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
191 u32 cc;
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);
196 if (set_carry) {
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)
203 u32 bc;
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);
208 if (set_carry) {
209 CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
213 /****************************************************************************
214 REMARKS:
215 Implements the AAA instruction and side effects.
216 ****************************************************************************/
217 u16 aaa_word(u16 d)
219 u16 res;
220 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
221 d += 0x6;
222 d += 0x100;
223 SET_FLAG(F_AF);
224 SET_FLAG(F_CF);
225 } else {
226 CLEAR_FLAG(F_CF);
227 CLEAR_FLAG(F_AF);
229 res = (u16)(d & 0xFF0F);
230 set_szp_flags_16(res);
231 return res;
234 /****************************************************************************
235 REMARKS:
236 Implements the AAA instruction and side effects.
237 ****************************************************************************/
238 u16 aas_word(u16 d)
240 u16 res;
241 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
242 d -= 0x6;
243 d -= 0x100;
244 SET_FLAG(F_AF);
245 SET_FLAG(F_CF);
246 } else {
247 CLEAR_FLAG(F_CF);
248 CLEAR_FLAG(F_AF);
250 res = (u16)(d & 0xFF0F);
251 set_szp_flags_16(res);
252 return res;
255 /****************************************************************************
256 REMARKS:
257 Implements the AAD instruction and side effects.
258 ****************************************************************************/
259 u16 aad_word(u16 d)
261 u16 l;
262 u8 hb, lb;
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);
269 return l;
272 /****************************************************************************
273 REMARKS:
274 Implements the AAM instruction and side effects.
275 ****************************************************************************/
276 u16 aam_word(u8 d)
278 u16 h, l;
280 h = (u16)(d / 10);
281 l = (u16)(d % 10);
282 l |= (u16)(h << 8);
284 no_carry_byte_side_eff(l & 0xFF);
285 return l;
288 /****************************************************************************
289 REMARKS:
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 */
296 res = d + s;
297 if (ACCESS_FLAG(F_CF)) res++;
299 set_szp_flags_8(res);
300 calc_carry_chain(8,s,d,res,1);
302 return (u8)res;
305 /****************************************************************************
306 REMARKS:
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 */
313 res = d + s;
314 if (ACCESS_FLAG(F_CF))
315 res++;
317 set_szp_flags_16((u16)res);
318 calc_carry_chain(16,s,d,res,1);
320 return (u16)res;
323 /****************************************************************************
324 REMARKS:
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 */
330 u32 hi;
331 u32 res;
333 lo = (d & 0xFFFF) + (s & 0xFFFF);
334 res = d + s;
336 if (ACCESS_FLAG(F_CF)) {
337 lo++;
338 res++;
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);
348 return res;
351 /****************************************************************************
352 REMARKS:
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 */
359 res = d + s;
360 set_szp_flags_8((u8)res);
361 calc_carry_chain(8,s,d,res,1);
363 return (u8)res;
366 /****************************************************************************
367 REMARKS:
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 */
374 res = d + s;
375 set_szp_flags_16((u16)res);
376 calc_carry_chain(16,s,d,res,1);
378 return (u16)res;
381 /****************************************************************************
382 REMARKS:
383 Implements the ADD instruction and side effects.
384 ****************************************************************************/
385 u32 add_long(u32 d, u32 s)
387 u32 res;
389 res = d + 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);
395 return res;
398 /****************************************************************************
399 REMARKS:
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 */
406 res = d & s;
408 no_carry_byte_side_eff(res);
409 return res;
412 /****************************************************************************
413 REMARKS:
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 */
420 res = d & s;
422 no_carry_word_side_eff(res);
423 return res;
426 /****************************************************************************
427 REMARKS:
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 */
434 res = d & s;
435 no_carry_long_side_eff(res);
436 return res;
439 /****************************************************************************
440 REMARKS:
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 */
447 res = d - s;
448 set_szp_flags_8((u8)res);
449 calc_borrow_chain(8, d, s, res, 1);
451 return d;
454 /****************************************************************************
455 REMARKS:
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 */
462 res = d - s;
463 set_szp_flags_16((u16)res);
464 calc_borrow_chain(16, d, s, res, 1);
466 return d;
469 /****************************************************************************
470 REMARKS:
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 */
477 res = d - s;
478 set_szp_flags_32(res);
479 calc_borrow_chain(32, d, s, res, 1);
481 return d;
484 /****************************************************************************
485 REMARKS:
486 Implements the DAA instruction and side effects.
487 ****************************************************************************/
488 u8 daa_byte(u8 d)
490 u32 res = d;
491 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
492 res += 6;
493 SET_FLAG(F_AF);
495 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
496 res += 0x60;
497 SET_FLAG(F_CF);
499 set_szp_flags_8((u8)res);
500 return (u8)res;
503 /****************************************************************************
504 REMARKS:
505 Implements the DAS instruction and side effects.
506 ****************************************************************************/
507 u8 das_byte(u8 d)
509 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
510 d -= 6;
511 SET_FLAG(F_AF);
513 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
514 d -= 0x60;
515 SET_FLAG(F_CF);
517 set_szp_flags_8(d);
518 return d;
521 /****************************************************************************
522 REMARKS:
523 Implements the DEC instruction and side effects.
524 ****************************************************************************/
525 u8 dec_byte(u8 d)
527 u32 res; /* all operands in native machine order */
529 res = d - 1;
530 set_szp_flags_8((u8)res);
531 calc_borrow_chain(8, d, 1, res, 0);
533 return (u8)res;
536 /****************************************************************************
537 REMARKS:
538 Implements the DEC instruction and side effects.
539 ****************************************************************************/
540 u16 dec_word(u16 d)
542 u32 res; /* all operands in native machine order */
544 res = d - 1;
545 set_szp_flags_16((u16)res);
546 calc_borrow_chain(16, d, 1, res, 0);
548 return (u16)res;
551 /****************************************************************************
552 REMARKS:
553 Implements the DEC instruction and side effects.
554 ****************************************************************************/
555 u32 dec_long(u32 d)
557 u32 res; /* all operands in native machine order */
559 res = d - 1;
561 set_szp_flags_32(res);
562 calc_borrow_chain(32, d, 1, res, 0);
564 return res;
567 /****************************************************************************
568 REMARKS:
569 Implements the INC instruction and side effects.
570 ****************************************************************************/
571 u8 inc_byte(u8 d)
573 u32 res; /* all operands in native machine order */
575 res = d + 1;
576 set_szp_flags_8((u8)res);
577 calc_carry_chain(8, d, 1, res, 0);
579 return (u8)res;
582 /****************************************************************************
583 REMARKS:
584 Implements the INC instruction and side effects.
585 ****************************************************************************/
586 u16 inc_word(u16 d)
588 u32 res; /* all operands in native machine order */
590 res = d + 1;
591 set_szp_flags_16((u16)res);
592 calc_carry_chain(16, d, 1, res, 0);
594 return (u16)res;
597 /****************************************************************************
598 REMARKS:
599 Implements the INC instruction and side effects.
600 ****************************************************************************/
601 u32 inc_long(u32 d)
603 u32 res; /* all operands in native machine order */
605 res = d + 1;
606 set_szp_flags_32(res);
607 calc_carry_chain(32, d, 1, res, 0);
609 return res;
612 /****************************************************************************
613 REMARKS:
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 */
620 res = d | s;
621 no_carry_byte_side_eff(res);
623 return res;
626 /****************************************************************************
627 REMARKS:
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 */
634 res = d | s;
635 no_carry_word_side_eff(res);
636 return res;
639 /****************************************************************************
640 REMARKS:
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 */
647 res = d | s;
648 no_carry_long_side_eff(res);
649 return res;
652 /****************************************************************************
653 REMARKS:
654 Implements the OR instruction and side effects.
655 ****************************************************************************/
656 u8 neg_byte(u8 s)
658 u8 res;
660 CONDITIONAL_SET_FLAG(s != 0, F_CF);
661 res = (u8)-s;
662 set_szp_flags_8(res);
663 calc_borrow_chain(8, 0, s, res, 0);
665 return res;
668 /****************************************************************************
669 REMARKS:
670 Implements the OR instruction and side effects.
671 ****************************************************************************/
672 u16 neg_word(u16 s)
674 u16 res;
676 CONDITIONAL_SET_FLAG(s != 0, F_CF);
677 res = (u16)-s;
678 set_szp_flags_16((u16)res);
679 calc_borrow_chain(16, 0, s, res, 0);
681 return res;
684 /****************************************************************************
685 REMARKS:
686 Implements the OR instruction and side effects.
687 ****************************************************************************/
688 u32 neg_long(u32 s)
690 u32 res;
692 CONDITIONAL_SET_FLAG(s != 0, F_CF);
693 res = (u32)-s;
694 set_szp_flags_32(res);
695 calc_borrow_chain(32, 0, s, res, 0);
697 return res;
700 /****************************************************************************
701 REMARKS:
702 Implements the NOT instruction and side effects.
703 ****************************************************************************/
704 u8 not_byte(u8 s)
706 return ~s;
709 /****************************************************************************
710 REMARKS:
711 Implements the NOT instruction and side effects.
712 ****************************************************************************/
713 u16 not_word(u16 s)
715 return ~s;
718 /****************************************************************************
719 REMARKS:
720 Implements the NOT instruction and side effects.
721 ****************************************************************************/
722 u32 not_long(u32 s)
724 return ~s;
727 /****************************************************************************
728 REMARKS:
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. */
736 /* have
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:
755 IF n > 0
756 1) CF <- b_(8-n)
757 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
758 3) B_(n-1) <- cf
759 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
761 res = d;
762 if ((cnt = s % 9) != 0) {
763 /* extract the new CARRY FLAG. */
764 /* CF <- b_(8-n) */
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 */
784 /* B_(n-1) <- cf */
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)),
794 F_OF);
797 return (u8)res;
800 /****************************************************************************
801 REMARKS:
802 Implements the RCL instruction and side effects.
803 ****************************************************************************/
804 u16 rcl_word(u16 d, u8 s)
806 unsigned int res, cnt, mask, cf;
808 res = d;
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)),
819 F_OF);
821 return (u16)res;
824 /****************************************************************************
825 REMARKS:
826 Implements the RCL instruction and side effects.
827 ****************************************************************************/
828 u32 rcl_long(u32 d, u8 s)
830 u32 res, cnt, mask, cf;
832 res = d;
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)),
843 F_OF);
845 return res;
848 /****************************************************************************
849 REMARKS:
850 Implements the RCR instruction and side effects.
851 ****************************************************************************/
852 u8 rcr_byte(u8 d, u8 s)
854 u32 res, cnt;
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.
862 have
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:
873 IF n > 0
874 1) CF <- b_(n-1)
875 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
876 3) B_(8-n) <- cf
877 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
879 res = d;
880 if ((cnt = s % 9) != 0) {
881 /* extract the new CARRY FLAG. */
882 /* CF <- b_(n-1) */
883 if (cnt == 1) {
884 cf = d & 0x1;
885 /* note hackery here. Access_flag(..) evaluates to either
886 0 if flag not set
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;
893 } else
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 */
916 /* B_(8-n) <- cf */
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... */
924 if (cnt == 1) {
925 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
926 F_OF);
929 return (u8)res;
932 /****************************************************************************
933 REMARKS:
934 Implements the RCR instruction and side effects.
935 ****************************************************************************/
936 u16 rcr_word(u16 d, u8 s)
938 u32 res, cnt;
939 u32 mask, cf, ocf = 0;
941 /* rotate right through carry */
942 res = d;
943 if ((cnt = s % 17) != 0) {
944 if (cnt == 1) {
945 cf = d & 0x1;
946 ocf = ACCESS_FLAG(F_CF) != 0;
947 } else
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);
956 if (cnt == 1) {
957 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
958 F_OF);
961 return (u16)res;
964 /****************************************************************************
965 REMARKS:
966 Implements the RCR instruction and side effects.
967 ****************************************************************************/
968 u32 rcr_long(u32 d, u8 s)
970 u32 res, cnt;
971 u32 mask, cf, ocf = 0;
973 /* rotate right through carry */
974 res = d;
975 if ((cnt = s % 33) != 0) {
976 if (cnt == 1) {
977 cf = d & 0x1;
978 ocf = ACCESS_FLAG(F_CF) != 0;
979 } else
980 cf = (d >> (cnt - 1)) & 0x1;
981 mask = (1 << (32 - cnt)) - 1;
982 res = (d >> cnt) & mask;
983 if (cnt != 1)
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);
989 if (cnt == 1) {
990 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
991 F_OF);
994 return res;
997 /****************************************************************************
998 REMARKS:
999 Implements the ROL instruction and side effects.
1000 ****************************************************************************/
1001 u8 rol_byte(u8 d, u8 s)
1003 unsigned int res, cnt, mask;
1005 /* rotate left */
1007 s is the rotate distance. It varies from 0 - 8.
1008 d is the byte object rotated.
1010 have
1012 CF B_7 ... B_0
1014 The new rotate is done mod 8.
1015 Much simpler than the "rcl" or "rcr" operations.
1017 IF n > 0
1018 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1019 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1021 res = d;
1022 if ((cnt = s % 8) != 0) {
1023 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1024 res = (d << cnt);
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)),
1037 F_OF);
1038 } if (s != 0) {
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);
1043 return (u8)res;
1046 /****************************************************************************
1047 REMARKS:
1048 Implements the ROL instruction and side effects.
1049 ****************************************************************************/
1050 u16 rol_word(u16 d, u8 s)
1052 unsigned int res, cnt, mask;
1054 res = d;
1055 if ((cnt = s % 16) != 0) {
1056 res = (d << cnt);
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)),
1062 F_OF);
1063 } if (s != 0) {
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);
1068 return (u16)res;
1071 /****************************************************************************
1072 REMARKS:
1073 Implements the ROL instruction and side effects.
1074 ****************************************************************************/
1075 u32 rol_long(u32 d, u8 s)
1077 u32 res, cnt, mask;
1079 res = d;
1080 if ((cnt = s % 32) != 0) {
1081 res = (d << cnt);
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)),
1087 F_OF);
1088 } if (s != 0) {
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);
1093 return res;
1096 /****************************************************************************
1097 REMARKS:
1098 Implements the ROR instruction and side effects.
1099 ****************************************************************************/
1100 u8 ror_byte(u8 d, u8 s)
1102 unsigned int res, cnt, mask;
1104 /* rotate right */
1106 s is the rotate distance. It varies from 0 - 8.
1107 d is the byte object rotated.
1109 have
1111 B_7 ... B_0
1113 The rotate is done mod 8.
1115 IF n > 0
1116 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1117 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1119 res = d;
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);
1139 return (u8)res;
1142 /****************************************************************************
1143 REMARKS:
1144 Implements the ROR instruction and side effects.
1145 ****************************************************************************/
1146 u16 ror_word(u16 d, u8 s)
1148 unsigned int res, cnt, mask;
1150 res = d;
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);
1162 return (u16)res;
1165 /****************************************************************************
1166 REMARKS:
1167 Implements the ROR instruction and side effects.
1168 ****************************************************************************/
1169 u32 ror_long(u32 d, u8 s)
1171 u32 res, cnt, mask;
1173 res = d;
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);
1185 return res;
1188 /****************************************************************************
1189 REMARKS:
1190 Implements the SHL instruction and side effects.
1191 ****************************************************************************/
1192 u8 shl_byte(u8 d, u8 s)
1194 unsigned int cnt, res, cf;
1196 if (s < 8) {
1197 cnt = s % 8;
1199 /* last bit shifted out goes into carry flag */
1200 if (cnt > 0) {
1201 res = d << cnt;
1202 cf = d & (1 << (8 - cnt));
1203 CONDITIONAL_SET_FLAG(cf, F_CF);
1204 set_szp_flags_8((u8)res);
1205 } else {
1206 res = (u8) d;
1209 if (cnt == 1) {
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)), */
1215 F_OF);
1216 } else {
1217 CLEAR_FLAG(F_OF);
1219 } else {
1220 res = 0;
1221 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1222 CLEAR_FLAG(F_OF);
1223 CLEAR_FLAG(F_SF);
1224 SET_FLAG(F_PF);
1225 SET_FLAG(F_ZF);
1227 return (u8)res;
1230 /****************************************************************************
1231 REMARKS:
1232 Implements the SHL instruction and side effects.
1233 ****************************************************************************/
1234 u16 shl_word(u16 d, u8 s)
1236 unsigned int cnt, res, cf;
1238 if (s < 16) {
1239 cnt = s % 16;
1240 if (cnt > 0) {
1241 res = d << cnt;
1242 cf = d & (1 << (16 - cnt));
1243 CONDITIONAL_SET_FLAG(cf, F_CF);
1244 set_szp_flags_16((u16)res);
1245 } else {
1246 res = (u16) d;
1249 if (cnt == 1) {
1250 CONDITIONAL_SET_FLAG(
1251 (((res & 0x8000) == 0x8000) ^
1252 (ACCESS_FLAG(F_CF) != 0)),
1253 F_OF);
1254 } else {
1255 CLEAR_FLAG(F_OF);
1257 } else {
1258 res = 0;
1259 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1260 CLEAR_FLAG(F_OF);
1261 CLEAR_FLAG(F_SF);
1262 SET_FLAG(F_PF);
1263 SET_FLAG(F_ZF);
1265 return (u16)res;
1268 /****************************************************************************
1269 REMARKS:
1270 Implements the SHL instruction and side effects.
1271 ****************************************************************************/
1272 u32 shl_long(u32 d, u8 s)
1274 unsigned int cnt, res, cf;
1276 if (s < 32) {
1277 cnt = s % 32;
1278 if (cnt > 0) {
1279 res = d << cnt;
1280 cf = d & (1 << (32 - cnt));
1281 CONDITIONAL_SET_FLAG(cf, F_CF);
1282 set_szp_flags_32((u32)res);
1283 } else {
1284 res = d;
1286 if (cnt == 1) {
1287 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1288 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1289 } else {
1290 CLEAR_FLAG(F_OF);
1292 } else {
1293 res = 0;
1294 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1295 CLEAR_FLAG(F_OF);
1296 CLEAR_FLAG(F_SF);
1297 SET_FLAG(F_PF);
1298 SET_FLAG(F_ZF);
1300 return res;
1303 /****************************************************************************
1304 REMARKS:
1305 Implements the SHR instruction and side effects.
1306 ****************************************************************************/
1307 u8 shr_byte(u8 d, u8 s)
1309 unsigned int cnt, res, cf;
1311 if (s < 8) {
1312 cnt = s % 8;
1313 if (cnt > 0) {
1314 cf = d & (1 << (cnt - 1));
1315 res = d >> cnt;
1316 CONDITIONAL_SET_FLAG(cf, F_CF);
1317 set_szp_flags_8((u8)res);
1318 } else {
1319 res = (u8) d;
1322 if (cnt == 1) {
1323 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1324 } else {
1325 CLEAR_FLAG(F_OF);
1327 } else {
1328 res = 0;
1329 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1330 CLEAR_FLAG(F_OF);
1331 CLEAR_FLAG(F_SF);
1332 SET_FLAG(F_PF);
1333 SET_FLAG(F_ZF);
1335 return (u8)res;
1338 /****************************************************************************
1339 REMARKS:
1340 Implements the SHR instruction and side effects.
1341 ****************************************************************************/
1342 u16 shr_word(u16 d, u8 s)
1344 unsigned int cnt, res, cf;
1346 if (s < 16) {
1347 cnt = s % 16;
1348 if (cnt > 0) {
1349 cf = d & (1 << (cnt - 1));
1350 res = d >> cnt;
1351 CONDITIONAL_SET_FLAG(cf, F_CF);
1352 set_szp_flags_16((u16)res);
1353 } else {
1354 res = d;
1357 if (cnt == 1) {
1358 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1359 } else {
1360 CLEAR_FLAG(F_OF);
1362 } else {
1363 res = 0;
1364 CLEAR_FLAG(F_CF);
1365 CLEAR_FLAG(F_OF);
1366 SET_FLAG(F_ZF);
1367 CLEAR_FLAG(F_SF);
1368 CLEAR_FLAG(F_PF);
1370 return (u16)res;
1373 /****************************************************************************
1374 REMARKS:
1375 Implements the SHR instruction and side effects.
1376 ****************************************************************************/
1377 u32 shr_long(u32 d, u8 s)
1379 unsigned int cnt, res, cf;
1381 if (s < 32) {
1382 cnt = s % 32;
1383 if (cnt > 0) {
1384 cf = d & (1 << (cnt - 1));
1385 res = d >> cnt;
1386 CONDITIONAL_SET_FLAG(cf, F_CF);
1387 set_szp_flags_32((u32)res);
1388 } else {
1389 res = d;
1391 if (cnt == 1) {
1392 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1393 } else {
1394 CLEAR_FLAG(F_OF);
1396 } else {
1397 res = 0;
1398 CLEAR_FLAG(F_CF);
1399 CLEAR_FLAG(F_OF);
1400 SET_FLAG(F_ZF);
1401 CLEAR_FLAG(F_SF);
1402 CLEAR_FLAG(F_PF);
1404 return res;
1407 /****************************************************************************
1408 REMARKS:
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;
1415 res = d;
1416 sf = d & 0x80;
1417 cnt = s % 8;
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);
1423 if (sf) {
1424 res |= ~mask;
1426 set_szp_flags_8((u8)res);
1427 } else if (cnt >= 8) {
1428 if (sf) {
1429 res = 0xff;
1430 SET_FLAG(F_CF);
1431 CLEAR_FLAG(F_ZF);
1432 SET_FLAG(F_SF);
1433 SET_FLAG(F_PF);
1434 } else {
1435 res = 0;
1436 CLEAR_FLAG(F_CF);
1437 SET_FLAG(F_ZF);
1438 CLEAR_FLAG(F_SF);
1439 CLEAR_FLAG(F_PF);
1442 return (u8)res;
1445 /****************************************************************************
1446 REMARKS:
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;
1453 sf = d & 0x8000;
1454 cnt = s % 16;
1455 res = d;
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);
1461 if (sf) {
1462 res |= ~mask;
1464 set_szp_flags_16((u16)res);
1465 } else if (cnt >= 16) {
1466 if (sf) {
1467 res = 0xffff;
1468 SET_FLAG(F_CF);
1469 CLEAR_FLAG(F_ZF);
1470 SET_FLAG(F_SF);
1471 SET_FLAG(F_PF);
1472 } else {
1473 res = 0;
1474 CLEAR_FLAG(F_CF);
1475 SET_FLAG(F_ZF);
1476 CLEAR_FLAG(F_SF);
1477 CLEAR_FLAG(F_PF);
1480 return (u16)res;
1483 /****************************************************************************
1484 REMARKS:
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;
1492 cnt = s % 32;
1493 res = d;
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);
1499 if (sf) {
1500 res |= ~mask;
1502 set_szp_flags_32(res);
1503 } else if (cnt >= 32) {
1504 if (sf) {
1505 res = 0xffffffff;
1506 SET_FLAG(F_CF);
1507 CLEAR_FLAG(F_ZF);
1508 SET_FLAG(F_SF);
1509 SET_FLAG(F_PF);
1510 } else {
1511 res = 0;
1512 CLEAR_FLAG(F_CF);
1513 SET_FLAG(F_ZF);
1514 CLEAR_FLAG(F_SF);
1515 CLEAR_FLAG(F_PF);
1518 return res;
1521 /****************************************************************************
1522 REMARKS:
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;
1529 if (s < 16) {
1530 cnt = s % 16;
1531 if (cnt > 0) {
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);
1536 } else {
1537 res = d;
1539 if (cnt == 1) {
1540 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1541 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1542 } else {
1543 CLEAR_FLAG(F_OF);
1545 } else {
1546 res = 0;
1547 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1548 CLEAR_FLAG(F_OF);
1549 CLEAR_FLAG(F_SF);
1550 SET_FLAG(F_PF);
1551 SET_FLAG(F_ZF);
1553 return (u16)res;
1556 /****************************************************************************
1557 REMARKS:
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;
1564 if (s < 32) {
1565 cnt = s % 32;
1566 if (cnt > 0) {
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);
1571 } else {
1572 res = d;
1574 if (cnt == 1) {
1575 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1576 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1577 } else {
1578 CLEAR_FLAG(F_OF);
1580 } else {
1581 res = 0;
1582 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1583 CLEAR_FLAG(F_OF);
1584 CLEAR_FLAG(F_SF);
1585 SET_FLAG(F_PF);
1586 SET_FLAG(F_ZF);
1588 return res;
1591 /****************************************************************************
1592 REMARKS:
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;
1599 if (s < 16) {
1600 cnt = s % 16;
1601 if (cnt > 0) {
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);
1606 } else {
1607 res = d;
1610 if (cnt == 1) {
1611 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1612 } else {
1613 CLEAR_FLAG(F_OF);
1615 } else {
1616 res = 0;
1617 CLEAR_FLAG(F_CF);
1618 CLEAR_FLAG(F_OF);
1619 SET_FLAG(F_ZF);
1620 CLEAR_FLAG(F_SF);
1621 CLEAR_FLAG(F_PF);
1623 return (u16)res;
1626 /****************************************************************************
1627 REMARKS:
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;
1634 if (s < 32) {
1635 cnt = s % 32;
1636 if (cnt > 0) {
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);
1641 } else {
1642 res = d;
1644 if (cnt == 1) {
1645 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1646 } else {
1647 CLEAR_FLAG(F_OF);
1649 } else {
1650 res = 0;
1651 CLEAR_FLAG(F_CF);
1652 CLEAR_FLAG(F_OF);
1653 SET_FLAG(F_ZF);
1654 CLEAR_FLAG(F_SF);
1655 CLEAR_FLAG(F_PF);
1657 return res;
1660 /****************************************************************************
1661 REMARKS:
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 */
1667 u32 bc;
1669 if (ACCESS_FLAG(F_CF))
1670 res = d - s - 1;
1671 else
1672 res = d - s;
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);
1680 return (u8)res;
1683 /****************************************************************************
1684 REMARKS:
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 */
1690 u32 bc;
1692 if (ACCESS_FLAG(F_CF))
1693 res = d - s - 1;
1694 else
1695 res = d - s;
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);
1703 return (u16)res;
1706 /****************************************************************************
1707 REMARKS:
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 */
1713 u32 bc;
1715 if (ACCESS_FLAG(F_CF))
1716 res = d - s - 1;
1717 else
1718 res = d - s;
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);
1727 return res;
1730 /****************************************************************************
1731 REMARKS:
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 */
1737 u32 bc;
1739 res = d - s;
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);
1747 return (u8)res;
1750 /****************************************************************************
1751 REMARKS:
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 */
1757 u32 bc;
1759 res = d - s;
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);
1767 return (u16)res;
1770 /****************************************************************************
1771 REMARKS:
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 */
1777 u32 bc;
1779 res = d - s;
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);
1787 return res;
1790 /****************************************************************************
1791 REMARKS:
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 */
1798 res = d & s;
1800 CLEAR_FLAG(F_OF);
1801 set_szp_flags_8((u8)res);
1802 /* AF == don't care */
1803 CLEAR_FLAG(F_CF);
1806 /****************************************************************************
1807 REMARKS:
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 */
1814 res = d & s;
1816 CLEAR_FLAG(F_OF);
1817 set_szp_flags_16((u16)res);
1818 /* AF == don't care */
1819 CLEAR_FLAG(F_CF);
1822 /****************************************************************************
1823 REMARKS:
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 */
1830 res = d & s;
1832 CLEAR_FLAG(F_OF);
1833 set_szp_flags_32(res);
1834 /* AF == don't care */
1835 CLEAR_FLAG(F_CF);
1838 /****************************************************************************
1839 REMARKS:
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 */
1846 res = d ^ s;
1847 no_carry_byte_side_eff(res);
1848 return res;
1851 /****************************************************************************
1852 REMARKS:
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 */
1859 res = d ^ s;
1860 no_carry_word_side_eff(res);
1861 return res;
1864 /****************************************************************************
1865 REMARKS:
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 */
1872 res = d ^ s;
1873 no_carry_long_side_eff(res);
1874 return res;
1877 /****************************************************************************
1878 REMARKS:
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);
1885 M.x86.R_AX = res;
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)) {
1888 CLEAR_FLAG(F_CF);
1889 CLEAR_FLAG(F_OF);
1890 } else {
1891 SET_FLAG(F_CF);
1892 SET_FLAG(F_OF);
1896 /****************************************************************************
1897 REMARKS:
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)) {
1908 CLEAR_FLAG(F_CF);
1909 CLEAR_FLAG(F_OF);
1910 } else {
1911 SET_FLAG(F_CF);
1912 SET_FLAG(F_OF);
1916 /****************************************************************************
1917 REMARKS:
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;
1925 *res_lo = (u32)res;
1926 *res_hi = (u32)(res >> 32);
1927 #else
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)
1933 d = -d;
1934 d_lo = d & 0xFFFF;
1935 d_hi = d >> 16;
1936 if ((s_sign = s & 0x80000000) != 0)
1937 s = -s;
1938 s_lo = s & 0xFFFF;
1939 s_hi = s >> 16;
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);
1944 *res_hi = rhi_lo;
1945 if (d_sign != s_sign) {
1946 d = ~*res_lo;
1947 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1948 *res_lo = ~*res_lo+1;
1949 *res_hi = ~*res_hi+(s >> 16);
1951 #endif
1954 /****************************************************************************
1955 REMARKS:
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)) {
1963 CLEAR_FLAG(F_CF);
1964 CLEAR_FLAG(F_OF);
1965 } else {
1966 SET_FLAG(F_CF);
1967 SET_FLAG(F_OF);
1971 /****************************************************************************
1972 REMARKS:
1973 Implements the MUL instruction and side effects.
1974 ****************************************************************************/
1975 void mul_byte(u8 s)
1977 u16 res = (u16)(M.x86.R_AL * s);
1979 M.x86.R_AX = res;
1980 if (M.x86.R_AH == 0) {
1981 CLEAR_FLAG(F_CF);
1982 CLEAR_FLAG(F_OF);
1983 } else {
1984 SET_FLAG(F_CF);
1985 SET_FLAG(F_OF);
1989 /****************************************************************************
1990 REMARKS:
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) {
2000 CLEAR_FLAG(F_CF);
2001 CLEAR_FLAG(F_OF);
2002 } else {
2003 SET_FLAG(F_CF);
2004 SET_FLAG(F_OF);
2008 /****************************************************************************
2009 REMARKS:
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);
2019 #else
2020 u32 a,a_lo,a_hi;
2021 u32 s_lo,s_hi;
2022 u32 rlo_lo,rlo_hi,rhi_lo;
2024 a = M.x86.R_EAX;
2025 a_lo = a & 0xFFFF;
2026 a_hi = a >> 16;
2027 s_lo = s & 0xFFFF;
2028 s_hi = s >> 16;
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;
2034 #endif
2035 if (M.x86.R_EDX == 0) {
2036 CLEAR_FLAG(F_CF);
2037 CLEAR_FLAG(F_OF);
2038 } else {
2039 SET_FLAG(F_CF);
2040 SET_FLAG(F_OF);
2044 /****************************************************************************
2045 REMARKS:
2046 Implements the IDIV instruction and side effects.
2047 ****************************************************************************/
2048 void idiv_byte(u8 s)
2050 s32 dvd, div, mod;
2052 dvd = (s16)M.x86.R_AX;
2053 if (s == 0) {
2054 x86emu_intr_raise(0);
2055 return;
2057 div = dvd / (s8)s;
2058 mod = dvd % (s8)s;
2059 if (abs(div) > 0x7f) {
2060 x86emu_intr_raise(0);
2061 return;
2063 M.x86.R_AL = (s8) div;
2064 M.x86.R_AH = (s8) mod;
2067 /****************************************************************************
2068 REMARKS:
2069 Implements the IDIV instruction and side effects.
2070 ****************************************************************************/
2071 void idiv_word(u16 s)
2073 s32 dvd, div, mod;
2075 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2076 if (s == 0) {
2077 x86emu_intr_raise(0);
2078 return;
2080 div = dvd / (s16)s;
2081 mod = dvd % (s16)s;
2082 if (abs(div) > 0x7fff) {
2083 x86emu_intr_raise(0);
2084 return;
2086 CLEAR_FLAG(F_CF);
2087 CLEAR_FLAG(F_SF);
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 /****************************************************************************
2096 REMARKS:
2097 Implements the IDIV instruction and side effects.
2098 ****************************************************************************/
2099 void idiv_long(u32 s)
2101 #ifdef __HAS_LONG_LONG__
2102 s64 dvd, div, mod;
2104 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2105 if (s == 0) {
2106 x86emu_intr_raise(0);
2107 return;
2109 div = dvd / (s32)s;
2110 mod = dvd % (s32)s;
2111 if (abs(div) > 0x7fffffff) {
2112 x86emu_intr_raise(0);
2113 return;
2115 #else
2116 s32 div = 0, mod;
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;
2123 int counter = 31;
2124 int carry;
2126 if (s == 0) {
2127 x86emu_intr_raise(0);
2128 return;
2130 do {
2131 div <<= 1;
2132 carry = (l_dvd >= l_s) ? 0 : 1;
2134 if (abs_h_dvd < (h_s + carry)) {
2135 h_s >>= 1;
2136 l_s = abs_s << (--counter);
2137 continue;
2138 } else {
2139 abs_h_dvd -= (h_s + carry);
2140 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2141 : (l_dvd - l_s);
2142 h_s >>= 1;
2143 l_s = abs_s << (--counter);
2144 div |= 1;
2145 continue;
2148 } while (counter > -1);
2149 /* overflow */
2150 if (abs_h_dvd || (l_dvd > abs_s)) {
2151 x86emu_intr_raise(0);
2152 return;
2154 /* sign */
2155 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2156 mod = l_dvd;
2158 #endif
2159 CLEAR_FLAG(F_CF);
2160 CLEAR_FLAG(F_AF);
2161 CLEAR_FLAG(F_SF);
2162 SET_FLAG(F_ZF);
2163 set_parity_flag(mod);
2165 M.x86.R_EAX = (u32)div;
2166 M.x86.R_EDX = (u32)mod;
2169 /****************************************************************************
2170 REMARKS:
2171 Implements the DIV instruction and side effects.
2172 ****************************************************************************/
2173 void div_byte(u8 s)
2175 u32 dvd, div, mod;
2177 dvd = M.x86.R_AX;
2178 if (s == 0) {
2179 x86emu_intr_raise(0);
2180 return;
2182 div = dvd / (u8)s;
2183 mod = dvd % (u8)s;
2184 if (abs(div) > 0xff) {
2185 x86emu_intr_raise(0);
2186 return;
2188 M.x86.R_AL = (u8)div;
2189 M.x86.R_AH = (u8)mod;
2192 /****************************************************************************
2193 REMARKS:
2194 Implements the DIV instruction and side effects.
2195 ****************************************************************************/
2196 void div_word(u16 s)
2198 u32 dvd, div, mod;
2200 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2201 if (s == 0) {
2202 x86emu_intr_raise(0);
2203 return;
2205 div = dvd / (u16)s;
2206 mod = dvd % (u16)s;
2207 if (abs(div) > 0xffff) {
2208 x86emu_intr_raise(0);
2209 return;
2211 CLEAR_FLAG(F_CF);
2212 CLEAR_FLAG(F_SF);
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 /****************************************************************************
2221 REMARKS:
2222 Implements the DIV instruction and side effects.
2223 ****************************************************************************/
2224 void div_long(u32 s)
2226 #ifdef __HAS_LONG_LONG__
2227 u64 dvd, div, mod;
2229 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2230 if (s == 0) {
2231 x86emu_intr_raise(0);
2232 return;
2234 div = dvd / (u32)s;
2235 mod = dvd % (u32)s;
2236 if (abs(div) > 0xffffffff) {
2237 x86emu_intr_raise(0);
2238 return;
2240 #else
2241 s32 div = 0, mod;
2242 s32 h_dvd = M.x86.R_EDX;
2243 u32 l_dvd = M.x86.R_EAX;
2245 u32 h_s = s;
2246 u32 l_s = 0;
2247 int counter = 32;
2248 int carry;
2250 if (s == 0) {
2251 x86emu_intr_raise(0);
2252 return;
2254 do {
2255 div <<= 1;
2256 carry = (l_dvd >= l_s) ? 0 : 1;
2258 if (h_dvd < (h_s + carry)) {
2259 h_s >>= 1;
2260 l_s = s << (--counter);
2261 continue;
2262 } else {
2263 h_dvd -= (h_s + carry);
2264 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2265 : (l_dvd - l_s);
2266 h_s >>= 1;
2267 l_s = s << (--counter);
2268 div |= 1;
2269 continue;
2272 } while (counter > -1);
2273 /* overflow */
2274 if (h_dvd || (l_dvd > s)) {
2275 x86emu_intr_raise(0);
2276 return;
2278 mod = l_dvd;
2279 #endif
2280 CLEAR_FLAG(F_CF);
2281 CLEAR_FLAG(F_AF);
2282 CLEAR_FLAG(F_SF);
2283 SET_FLAG(F_ZF);
2284 set_parity_flag(mod);
2286 M.x86.R_EAX = (u32)div;
2287 M.x86.R_EDX = (u32)mod;
2290 /****************************************************************************
2291 REMARKS:
2292 Implements the IN string instruction and side effects.
2293 ****************************************************************************/
2295 static void single_in(int size)
2297 if (size == 1)
2298 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
2299 else if (size == 2)
2300 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
2301 else
2302 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
2305 void ins(int size)
2307 int inc = size;
2309 if (ACCESS_FLAG(F_DF)) {
2310 inc = -size;
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);
2317 while (count--) {
2318 single_in(size);
2319 M.x86.R_DI += inc;
2321 M.x86.R_CX = 0;
2322 if (M.x86.mode & SYSMODE_32BIT_REP) {
2323 M.x86.R_ECX = 0;
2325 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2326 } else {
2327 single_in(size);
2328 M.x86.R_DI += inc;
2332 /****************************************************************************
2333 REMARKS:
2334 Implements the OUT string instruction and side effects.
2335 ****************************************************************************/
2337 static void single_out(int size)
2339 if (size == 1)
2340 (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2341 else if (size == 2)
2342 (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2343 else
2344 (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2347 void outs(int size)
2349 int inc = size;
2351 if (ACCESS_FLAG(F_DF)) {
2352 inc = -size;
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);
2359 while (count--) {
2360 single_out(size);
2361 M.x86.R_SI += inc;
2363 M.x86.R_CX = 0;
2364 if (M.x86.mode & SYSMODE_32BIT_REP) {
2365 M.x86.R_ECX = 0;
2367 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2368 } else {
2369 single_out(size);
2370 M.x86.R_SI += inc;
2374 /****************************************************************************
2375 PARAMETERS:
2376 addr - Address to fetch word from
2378 REMARKS:
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 /****************************************************************************
2389 REMARKS:
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();)
2398 M.x86.R_SP -= 2;
2399 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2402 /****************************************************************************
2403 REMARKS:
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();)
2412 M.x86.R_SP -= 4;
2413 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2416 /****************************************************************************
2417 REMARKS:
2418 Pops a word from the stack.
2420 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2421 ****************************************************************************/
2422 u16 pop_word(void)
2424 u16 res;
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);
2429 M.x86.R_SP += 2;
2430 return res;
2433 /****************************************************************************
2434 REMARKS:
2435 Pops a long from the stack.
2437 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2438 ****************************************************************************/
2439 u32 pop_long(void)
2441 u32 res;
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);
2446 M.x86.R_SP += 4;
2447 return res;
2450 /****************************************************************************
2451 REMARKS:
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;
2458 switch (feature) {
2459 case 0:
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.
2464 M.x86.R_EAX = 1;
2465 /* EBX:EDX:ECX = "GenuineIntel" */
2466 M.x86.R_EBX = 0x756e6547;
2467 M.x86.R_EDX = 0x49656e69;
2468 M.x86.R_ECX = 0x6c65746e;
2469 break;
2470 case 1:
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;
2482 break;
2483 default:
2484 /* Finally, we don't support any additional features. Most CPUs
2485 * return all zeros when queried for invalid or unsupported feature
2486 * numbers.
2488 M.x86.R_EAX = 0;
2489 M.x86.R_EBX = 0;
2490 M.x86.R_ECX = 0;
2491 M.x86.R_EDX = 0;
2492 break;