blob: 08a22bd35617700c4318e30c06be92cfa5e7120e [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/****************************************************************************
2*
3* Realmode X86 Emulator Library
4*
5* Copyright (C) 1991-2004 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
8*
9* ========================================================================
10*
11* Permission to use, copy, modify, distribute, and sell this software and
12* its documentation for any purpose is hereby granted without fee,
13* provided that the above copyright notice appear in all copies and that
14* both that copyright notice and this permission notice appear in
15* supporting documentation, and that the name of the authors not be used
16* in advertising or publicity pertaining to distribution of the software
17* without specific, written prior permission. The authors makes no
18* representations about the suitability of this software for any purpose.
19* It is provided "as is" without express or implied warranty.
20*
21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27* PERFORMANCE OF THIS SOFTWARE.
28*
29* ========================================================================
30*
31* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
34*
35* Description: This file contains the code to implement the primitive
36* machine operations used by the emulation code in ops.c
37*
38* Carry Chain Calculation
39*
40* This represents a somewhat expensive calculation which is
41* apparently required to emulate the setting of the 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.
47*
48* So, given the following table, which represents the addition of two
49* bits, we can derive a formula for the carry chain.
50*
51* a b cin r cout
52* 0 0 0 0 0
53* 0 0 1 1 0
54* 0 1 0 1 0
55* 0 1 1 0 1
56* 1 0 0 1 0
57* 1 0 1 0 1
58* 1 1 0 0 1
59* 1 1 1 1 1
60*
61* Construction of table for cout:
62*
63* ab
64* r \ 00 01 11 10
65* |------------------
66* 0 | 0 1 1 1
67* 1 | 0 0 1 0
68*
69* By inspection, one gets: cc = ab + r'(a + b)
70*
71* That represents alot of operations, but NO CHOICE....
72*
73* Borrow Chain Calculation.
74*
75* The following table represents the subtraction of two bits, from
76* which we can derive a formula for the borrow chain.
77*
78* a b bin r bout
79* 0 0 0 0 0
80* 0 0 1 1 1
81* 0 1 0 1 1
82* 0 1 1 0 1
83* 1 0 0 1 0
84* 1 0 1 0 0
85* 1 1 0 0 0
86* 1 1 1 1 1
87*
88* Construction of table for cout:
89*
90* ab
91* r \ 00 01 11 10
92* |------------------
93* 0 | 0 1 0 0
94* 1 | 1 1 1 0
95*
96* By inspection, one gets: bc = a'b + r(a' + b)
97*
98****************************************************************************/
99
100#define PRIM_OPS_NO_REDEFINE_ASM
101#include "x86emui.h"
102
103#define abs(x) ({ \
104 int __x = (x); \
105 (__x < 0) ? -__x : __x; \
106 })
107
108#define labs(x) ({ \
109 long __x = (x); \
110 (__x < 0) ? -__x : __x; \
111 })
112
113/*------------------------- Global Variables ------------------------------*/
114
115static u32 x86emu_parity_tab[8] =
116{
117 0x96696996,
118 0x69969669,
119 0x69969669,
120 0x96696996,
121 0x69969669,
122 0x96696996,
123 0x96696996,
124 0x69969669,
125};
126
127#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
128#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
129
130/*----------------------------- Implementation ----------------------------*/
131
132
133/*--------- Side effects helper functions -------*/
134
135/****************************************************************************
136REMARKS:
Martin Roth63373ed2013-07-08 16:24:19 -0600137implements side effects for byte operations that don't overflow
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000138****************************************************************************/
139
140static void set_parity_flag(u32 res)
141{
142 CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
143}
144
145static void set_szp_flags_8(u8 res)
146{
147 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
148 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
149 set_parity_flag(res);
150}
151
152static void set_szp_flags_16(u16 res)
153{
154 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
155 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
156 set_parity_flag(res);
157}
158
159static void set_szp_flags_32(u32 res)
160{
161 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
162 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
163 set_parity_flag(res);
164}
165
166static void no_carry_byte_side_eff(u8 res)
167{
168 CLEAR_FLAG(F_OF);
169 CLEAR_FLAG(F_CF);
170 CLEAR_FLAG(F_AF);
171 set_szp_flags_8(res);
172}
173
174static void no_carry_word_side_eff(u16 res)
175{
176 CLEAR_FLAG(F_OF);
177 CLEAR_FLAG(F_CF);
178 CLEAR_FLAG(F_AF);
179 set_szp_flags_16(res);
180}
181
182static void no_carry_long_side_eff(u32 res)
183{
184 CLEAR_FLAG(F_OF);
185 CLEAR_FLAG(F_CF);
186 CLEAR_FLAG(F_AF);
187 set_szp_flags_32(res);
188}
189
190static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
191{
192 u32 cc;
193
194 cc = (s & d) | ((~res) & (s | d));
195 CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
196 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
197 if (set_carry) {
198 CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
199 }
200}
201
202static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
203{
204 u32 bc;
205
206 bc = (res & (~d | s)) | (~d & s);
207 CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
208 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
209 if (set_carry) {
210 CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
211 }
212}
213
214/****************************************************************************
215REMARKS:
216Implements the AAA instruction and side effects.
217****************************************************************************/
218u16 aaa_word(u16 d)
219{
220 u16 res;
221 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
222 d += 0x6;
223 d += 0x100;
224 SET_FLAG(F_AF);
225 SET_FLAG(F_CF);
226 } else {
227 CLEAR_FLAG(F_CF);
228 CLEAR_FLAG(F_AF);
229 }
230 res = (u16)(d & 0xFF0F);
231 set_szp_flags_16(res);
232 return res;
233}
234
235/****************************************************************************
236REMARKS:
237Implements the AAA instruction and side effects.
238****************************************************************************/
239u16 aas_word(u16 d)
240{
241 u16 res;
242 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
243 d -= 0x6;
244 d -= 0x100;
245 SET_FLAG(F_AF);
246 SET_FLAG(F_CF);
247 } else {
248 CLEAR_FLAG(F_CF);
249 CLEAR_FLAG(F_AF);
250 }
251 res = (u16)(d & 0xFF0F);
252 set_szp_flags_16(res);
253 return res;
254}
255
256/****************************************************************************
257REMARKS:
258Implements the AAD instruction and side effects.
259****************************************************************************/
260u16 aad_word(u16 d)
261{
262 u16 l;
263 u8 hb, lb;
264
265 hb = (u8)((d >> 8) & 0xff);
266 lb = (u8)((d & 0xff));
267 l = (u16)((lb + 10 * hb) & 0xFF);
268
269 no_carry_byte_side_eff(l & 0xFF);
270 return l;
271}
272
273/****************************************************************************
274REMARKS:
275Implements the AAM instruction and side effects.
276****************************************************************************/
277u16 aam_word(u8 d)
278{
279 u16 h, l;
280
281 h = (u16)(d / 10);
282 l = (u16)(d % 10);
283 l |= (u16)(h << 8);
284
285 no_carry_byte_side_eff(l & 0xFF);
286 return l;
287}
288
289/****************************************************************************
290REMARKS:
291Implements the ADC instruction and side effects.
292****************************************************************************/
293u8 adc_byte(u8 d, u8 s)
294{
295 u32 res; /* all operands in native machine order */
296
297 res = d + s;
298 if (ACCESS_FLAG(F_CF)) res++;
299
300 set_szp_flags_8(res);
301 calc_carry_chain(8,s,d,res,1);
302
303 return (u8)res;
304}
305
306/****************************************************************************
307REMARKS:
308Implements the ADC instruction and side effects.
309****************************************************************************/
310u16 adc_word(u16 d, u16 s)
311{
312 u32 res; /* all operands in native machine order */
313
314 res = d + s;
315 if (ACCESS_FLAG(F_CF))
316 res++;
317
318 set_szp_flags_16((u16)res);
319 calc_carry_chain(16,s,d,res,1);
320
321 return (u16)res;
322}
323
324/****************************************************************************
325REMARKS:
326Implements the ADC instruction and side effects.
327****************************************************************************/
328u32 adc_long(u32 d, u32 s)
329{
330 u32 lo; /* all operands in native machine order */
331 u32 hi;
332 u32 res;
333
334 lo = (d & 0xFFFF) + (s & 0xFFFF);
335 res = d + s;
336
337 if (ACCESS_FLAG(F_CF)) {
338 lo++;
339 res++;
340 }
341
342 hi = (lo >> 16) + (d >> 16) + (s >> 16);
343
344 set_szp_flags_32(res);
345 calc_carry_chain(32,s,d,res,0);
346
347 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
348
349 return res;
350}
351
352/****************************************************************************
353REMARKS:
354Implements the ADD instruction and side effects.
355****************************************************************************/
356u8 add_byte(u8 d, u8 s)
357{
358 u32 res; /* all operands in native machine order */
359
360 res = d + s;
361 set_szp_flags_8((u8)res);
362 calc_carry_chain(8,s,d,res,1);
363
364 return (u8)res;
365}
366
367/****************************************************************************
368REMARKS:
369Implements the ADD instruction and side effects.
370****************************************************************************/
371u16 add_word(u16 d, u16 s)
372{
373 u32 res; /* all operands in native machine order */
374
375 res = d + s;
376 set_szp_flags_16((u16)res);
377 calc_carry_chain(16,s,d,res,1);
378
379 return (u16)res;
380}
381
382/****************************************************************************
383REMARKS:
384Implements the ADD instruction and side effects.
385****************************************************************************/
386u32 add_long(u32 d, u32 s)
387{
388 u32 res;
389
390 res = d + s;
391 set_szp_flags_32(res);
392 calc_carry_chain(32,s,d,res,0);
393
394 CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
395
396 return res;
397}
398
399/****************************************************************************
400REMARKS:
401Implements the AND instruction and side effects.
402****************************************************************************/
403u8 and_byte(u8 d, u8 s)
404{
405 u8 res; /* all operands in native machine order */
406
407 res = d & s;
408
409 no_carry_byte_side_eff(res);
410 return res;
411}
412
413/****************************************************************************
414REMARKS:
415Implements the AND instruction and side effects.
416****************************************************************************/
417u16 and_word(u16 d, u16 s)
418{
419 u16 res; /* all operands in native machine order */
420
421 res = d & s;
422
423 no_carry_word_side_eff(res);
424 return res;
425}
426
427/****************************************************************************
428REMARKS:
429Implements the AND instruction and side effects.
430****************************************************************************/
431u32 and_long(u32 d, u32 s)
432{
433 u32 res; /* all operands in native machine order */
434
435 res = d & s;
436 no_carry_long_side_eff(res);
437 return res;
438}
439
440/****************************************************************************
441REMARKS:
442Implements the CMP instruction and side effects.
443****************************************************************************/
444u8 cmp_byte(u8 d, u8 s)
445{
446 u32 res; /* all operands in native machine order */
447
448 res = d - s;
449 set_szp_flags_8((u8)res);
450 calc_borrow_chain(8, d, s, res, 1);
451
452 return d;
453}
454
455/****************************************************************************
456REMARKS:
457Implements the CMP instruction and side effects.
458****************************************************************************/
459u16 cmp_word(u16 d, u16 s)
460{
461 u32 res; /* all operands in native machine order */
462
463 res = d - s;
464 set_szp_flags_16((u16)res);
465 calc_borrow_chain(16, d, s, res, 1);
466
467 return d;
468}
469
470/****************************************************************************
471REMARKS:
472Implements the CMP instruction and side effects.
473****************************************************************************/
474u32 cmp_long(u32 d, u32 s)
475{
476 u32 res; /* all operands in native machine order */
477
478 res = d - s;
479 set_szp_flags_32(res);
480 calc_borrow_chain(32, d, s, res, 1);
481
482 return d;
483}
484
485/****************************************************************************
486REMARKS:
487Implements the DAA instruction and side effects.
488****************************************************************************/
489u8 daa_byte(u8 d)
490{
491 u32 res = d;
492 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
493 res += 6;
494 SET_FLAG(F_AF);
495 }
496 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
497 res += 0x60;
498 SET_FLAG(F_CF);
499 }
500 set_szp_flags_8((u8)res);
501 return (u8)res;
502}
503
504/****************************************************************************
505REMARKS:
506Implements the DAS instruction and side effects.
507****************************************************************************/
508u8 das_byte(u8 d)
509{
510 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
511 d -= 6;
512 SET_FLAG(F_AF);
513 }
514 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
515 d -= 0x60;
516 SET_FLAG(F_CF);
517 }
518 set_szp_flags_8(d);
519 return d;
520}
521
522/****************************************************************************
523REMARKS:
524Implements the DEC instruction and side effects.
525****************************************************************************/
526u8 dec_byte(u8 d)
527{
528 u32 res; /* all operands in native machine order */
529
530 res = d - 1;
531 set_szp_flags_8((u8)res);
532 calc_borrow_chain(8, d, 1, res, 0);
533
534 return (u8)res;
535}
536
537/****************************************************************************
538REMARKS:
539Implements the DEC instruction and side effects.
540****************************************************************************/
541u16 dec_word(u16 d)
542{
543 u32 res; /* all operands in native machine order */
544
545 res = d - 1;
546 set_szp_flags_16((u16)res);
547 calc_borrow_chain(16, d, 1, res, 0);
548
549 return (u16)res;
550}
551
552/****************************************************************************
553REMARKS:
554Implements the DEC instruction and side effects.
555****************************************************************************/
556u32 dec_long(u32 d)
557{
558 u32 res; /* all operands in native machine order */
559
560 res = d - 1;
561
562 set_szp_flags_32(res);
563 calc_borrow_chain(32, d, 1, res, 0);
564
565 return res;
566}
567
568/****************************************************************************
569REMARKS:
570Implements the INC instruction and side effects.
571****************************************************************************/
572u8 inc_byte(u8 d)
573{
574 u32 res; /* all operands in native machine order */
575
576 res = d + 1;
577 set_szp_flags_8((u8)res);
578 calc_carry_chain(8, d, 1, res, 0);
579
580 return (u8)res;
581}
582
583/****************************************************************************
584REMARKS:
585Implements the INC instruction and side effects.
586****************************************************************************/
587u16 inc_word(u16 d)
588{
589 u32 res; /* all operands in native machine order */
590
591 res = d + 1;
592 set_szp_flags_16((u16)res);
593 calc_carry_chain(16, d, 1, res, 0);
594
595 return (u16)res;
596}
597
598/****************************************************************************
599REMARKS:
600Implements the INC instruction and side effects.
601****************************************************************************/
602u32 inc_long(u32 d)
603{
604 u32 res; /* all operands in native machine order */
605
606 res = d + 1;
607 set_szp_flags_32(res);
608 calc_carry_chain(32, d, 1, res, 0);
609
610 return res;
611}
612
613/****************************************************************************
614REMARKS:
615Implements the OR instruction and side effects.
616****************************************************************************/
617u8 or_byte(u8 d, u8 s)
618{
619 u8 res; /* all operands in native machine order */
620
621 res = d | s;
622 no_carry_byte_side_eff(res);
623
624 return res;
625}
626
627/****************************************************************************
628REMARKS:
629Implements the OR instruction and side effects.
630****************************************************************************/
631u16 or_word(u16 d, u16 s)
632{
633 u16 res; /* all operands in native machine order */
634
635 res = d | s;
636 no_carry_word_side_eff(res);
637 return res;
638}
639
640/****************************************************************************
641REMARKS:
642Implements the OR instruction and side effects.
643****************************************************************************/
644u32 or_long(u32 d, u32 s)
645{
646 u32 res; /* all operands in native machine order */
647
648 res = d | s;
649 no_carry_long_side_eff(res);
650 return res;
651}
652
653/****************************************************************************
654REMARKS:
655Implements the OR instruction and side effects.
656****************************************************************************/
657u8 neg_byte(u8 s)
658{
659 u8 res;
660
661 CONDITIONAL_SET_FLAG(s != 0, F_CF);
662 res = (u8)-s;
663 set_szp_flags_8(res);
664 calc_borrow_chain(8, 0, s, res, 0);
665
666 return res;
667}
668
669/****************************************************************************
670REMARKS:
671Implements the OR instruction and side effects.
672****************************************************************************/
673u16 neg_word(u16 s)
674{
675 u16 res;
676
677 CONDITIONAL_SET_FLAG(s != 0, F_CF);
678 res = (u16)-s;
679 set_szp_flags_16((u16)res);
680 calc_borrow_chain(16, 0, s, res, 0);
681
682 return res;
683}
684
685/****************************************************************************
686REMARKS:
687Implements the OR instruction and side effects.
688****************************************************************************/
689u32 neg_long(u32 s)
690{
691 u32 res;
692
693 CONDITIONAL_SET_FLAG(s != 0, F_CF);
694 res = (u32)-s;
695 set_szp_flags_32(res);
696 calc_borrow_chain(32, 0, s, res, 0);
697
698 return res;
699}
700
701/****************************************************************************
702REMARKS:
703Implements the NOT instruction and side effects.
704****************************************************************************/
705u8 not_byte(u8 s)
706{
707 return ~s;
708}
709
710/****************************************************************************
711REMARKS:
712Implements the NOT instruction and side effects.
713****************************************************************************/
714u16 not_word(u16 s)
715{
716 return ~s;
717}
718
719/****************************************************************************
720REMARKS:
721Implements the NOT instruction and side effects.
722****************************************************************************/
723u32 not_long(u32 s)
724{
725 return ~s;
726}
727
728/****************************************************************************
729REMARKS:
730Implements the RCL instruction and side effects.
731****************************************************************************/
732u8 rcl_byte(u8 d, u8 s)
733{
734 unsigned int res, cnt, mask, cf;
735
736 /* s is the rotate distance. It varies from 0 - 8. */
737 /* have
738
739 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
740
741 want to rotate through the carry by "s" bits. We could
742 loop, but that's inefficient. So the width is 9,
743 and we split into three parts:
744
745 The new carry flag (was B_n)
746 the stuff in B_n-1 .. B_0
747 the stuff in B_7 .. B_n+1
748
749 The new rotate is done mod 9, and given this,
750 for a rotation of n bits (mod 9) the new carry flag is
751 then located n bits from the MSB. The low part is
752 then shifted up cnt bits, and the high part is or'd
753 in. Using CAPS for new values, and lowercase for the
754 original values, this can be expressed as:
755
756 IF n > 0
757 1) CF <- b_(8-n)
758 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
759 3) B_(n-1) <- cf
760 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
761 */
762 res = d;
763 if ((cnt = s % 9) != 0) {
764 /* extract the new CARRY FLAG. */
765 /* CF <- b_(8-n) */
766 cf = (d >> (8 - cnt)) & 0x1;
767
768 /* get the low stuff which rotated
769 into the range B_7 .. B_cnt */
770 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
771 /* note that the right hand side done by the mask */
772 res = (d << cnt) & 0xff;
773
774 /* now the high stuff which rotated around
775 into the positions B_cnt-2 .. B_0 */
776 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
777 /* shift it downward, 7-(n-2) = 9-n positions.
778 and mask off the result before or'ing in.
779 */
780 mask = (1 << (cnt - 1)) - 1;
781 res |= (d >> (9 - cnt)) & mask;
782
783 /* if the carry flag was set, or it in. */
784 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
785 /* B_(n-1) <- cf */
786 res |= 1 << (cnt - 1);
787 }
788 /* set the new carry flag, based on the variable "cf" */
789 CONDITIONAL_SET_FLAG(cf, F_CF);
790 /* OVERFLOW is set *IFF* cnt==1, then it is the
791 xor of CF and the most significant bit. Blecck. */
792 /* parenthesized this expression since it appears to
Martin Roth63373ed2013-07-08 16:24:19 -0600793 be causing OF to be missed */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000794 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
795 F_OF);
796
797 }
798 return (u8)res;
799}
800
801/****************************************************************************
802REMARKS:
803Implements the RCL instruction and side effects.
804****************************************************************************/
805u16 rcl_word(u16 d, u8 s)
806{
807 unsigned int res, cnt, mask, cf;
808
809 res = d;
810 if ((cnt = s % 17) != 0) {
811 cf = (d >> (16 - cnt)) & 0x1;
812 res = (d << cnt) & 0xffff;
813 mask = (1 << (cnt - 1)) - 1;
814 res |= (d >> (17 - cnt)) & mask;
815 if (ACCESS_FLAG(F_CF)) {
816 res |= 1 << (cnt - 1);
817 }
818 CONDITIONAL_SET_FLAG(cf, F_CF);
819 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
820 F_OF);
821 }
822 return (u16)res;
823}
824
825/****************************************************************************
826REMARKS:
827Implements the RCL instruction and side effects.
828****************************************************************************/
829u32 rcl_long(u32 d, u8 s)
830{
831 u32 res, cnt, mask, cf;
832
833 res = d;
834 if ((cnt = s % 33) != 0) {
835 cf = (d >> (32 - cnt)) & 0x1;
836 res = (d << cnt) & 0xffffffff;
837 mask = (1 << (cnt - 1)) - 1;
838 res |= (d >> (33 - cnt)) & mask;
839 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
840 res |= 1 << (cnt - 1);
841 }
842 CONDITIONAL_SET_FLAG(cf, F_CF);
843 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
844 F_OF);
845 }
846 return res;
847}
848
849/****************************************************************************
850REMARKS:
851Implements the RCR instruction and side effects.
852****************************************************************************/
853u8 rcr_byte(u8 d, u8 s)
854{
855 u32 res, cnt;
856 u32 mask, cf, ocf = 0;
857
858 /* rotate right through carry */
859 /*
860 s is the rotate distance. It varies from 0 - 8.
861 d is the byte object rotated.
862
863 have
864
865 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
866
867 The new rotate is done mod 9, and given this,
868 for a rotation of n bits (mod 9) the new carry flag is
869 then located n bits from the LSB. The low part is
870 then shifted up cnt bits, and the high part is or'd
871 in. Using CAPS for new values, and lowercase for the
872 original values, this can be expressed as:
873
874 IF n > 0
875 1) CF <- b_(n-1)
876 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
877 3) B_(8-n) <- cf
878 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
879 */
880 res = d;
881 if ((cnt = s % 9) != 0) {
882 /* extract the new CARRY FLAG. */
883 /* CF <- b_(n-1) */
884 if (cnt == 1) {
885 cf = d & 0x1;
886 /* note hackery here. Access_flag(..) evaluates to either
887 0 if flag not set
888 non-zero if flag is set.
889 doing access_flag(..) != 0 casts that into either
890 0..1 in any representation of the flags register
891 (i.e. packed bit array or unpacked.)
892 */
893 ocf = ACCESS_FLAG(F_CF) != 0;
894 } else
895 cf = (d >> (cnt - 1)) & 0x1;
896
897 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
898 /* note that the right hand side done by the mask
899 This is effectively done by shifting the
900 object to the right. The result must be masked,
901 in case the object came in and was treated
902 as a negative number. Needed??? */
903
904 mask = (1 << (8 - cnt)) - 1;
905 res = (d >> cnt) & mask;
906
907 /* now the high stuff which rotated around
908 into the positions B_cnt-2 .. B_0 */
909 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
910 /* shift it downward, 7-(n-2) = 9-n positions.
911 and mask off the result before or'ing in.
912 */
913 res |= (d << (9 - cnt));
914
915 /* if the carry flag was set, or it in. */
916 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
917 /* B_(8-n) <- cf */
918 res |= 1 << (8 - cnt);
919 }
920 /* set the new carry flag, based on the variable "cf" */
921 CONDITIONAL_SET_FLAG(cf, F_CF);
922 /* OVERFLOW is set *IFF* cnt==1, then it is the
923 xor of CF and the most significant bit. Blecck. */
924 /* parenthesized... */
925 if (cnt == 1) {
926 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
927 F_OF);
928 }
929 }
930 return (u8)res;
931}
932
933/****************************************************************************
934REMARKS:
935Implements the RCR instruction and side effects.
936****************************************************************************/
937u16 rcr_word(u16 d, u8 s)
938{
939 u32 res, cnt;
940 u32 mask, cf, ocf = 0;
941
942 /* rotate right through carry */
943 res = d;
944 if ((cnt = s % 17) != 0) {
945 if (cnt == 1) {
946 cf = d & 0x1;
947 ocf = ACCESS_FLAG(F_CF) != 0;
948 } else
949 cf = (d >> (cnt - 1)) & 0x1;
950 mask = (1 << (16 - cnt)) - 1;
951 res = (d >> cnt) & mask;
952 res |= (d << (17 - cnt));
953 if (ACCESS_FLAG(F_CF)) {
954 res |= 1 << (16 - cnt);
955 }
956 CONDITIONAL_SET_FLAG(cf, F_CF);
957 if (cnt == 1) {
958 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
959 F_OF);
960 }
961 }
962 return (u16)res;
963}
964
965/****************************************************************************
966REMARKS:
967Implements the RCR instruction and side effects.
968****************************************************************************/
969u32 rcr_long(u32 d, u8 s)
970{
971 u32 res, cnt;
972 u32 mask, cf, ocf = 0;
973
974 /* rotate right through carry */
975 res = d;
976 if ((cnt = s % 33) != 0) {
977 if (cnt == 1) {
978 cf = d & 0x1;
979 ocf = ACCESS_FLAG(F_CF) != 0;
980 } else
981 cf = (d >> (cnt - 1)) & 0x1;
982 mask = (1 << (32 - cnt)) - 1;
983 res = (d >> cnt) & mask;
984 if (cnt != 1)
985 res |= (d << (33 - cnt));
986 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
987 res |= 1 << (32 - cnt);
988 }
989 CONDITIONAL_SET_FLAG(cf, F_CF);
990 if (cnt == 1) {
991 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
992 F_OF);
993 }
994 }
995 return res;
996}
997
998/****************************************************************************
999REMARKS:
1000Implements the ROL instruction and side effects.
1001****************************************************************************/
1002u8 rol_byte(u8 d, u8 s)
1003{
1004 unsigned int res, cnt, mask;
1005
1006 /* rotate left */
1007 /*
1008 s is the rotate distance. It varies from 0 - 8.
1009 d is the byte object rotated.
1010
1011 have
1012
1013 CF B_7 ... B_0
1014
1015 The new rotate is done mod 8.
1016 Much simpler than the "rcl" or "rcr" operations.
1017
1018 IF n > 0
1019 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1020 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1021 */
1022 res = d;
1023 if ((cnt = s % 8) != 0) {
1024 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1025 res = (d << cnt);
1026
1027 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1028 mask = (1 << cnt) - 1;
1029 res |= (d >> (8 - cnt)) & mask;
1030
1031 /* set the new carry flag, Note that it is the low order
1032 bit of the result!!! */
1033 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1034 /* OVERFLOW is set *IFF* s==1, then it is the
1035 xor of CF and the most significant bit. Blecck. */
1036 CONDITIONAL_SET_FLAG(s == 1 &&
1037 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1038 F_OF);
1039 } if (s != 0) {
1040 /* set the new carry flag, Note that it is the low order
1041 bit of the result!!! */
1042 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1043 }
1044 return (u8)res;
1045}
1046
1047/****************************************************************************
1048REMARKS:
1049Implements the ROL instruction and side effects.
1050****************************************************************************/
1051u16 rol_word(u16 d, u8 s)
1052{
1053 unsigned int res, cnt, mask;
1054
1055 res = d;
1056 if ((cnt = s % 16) != 0) {
1057 res = (d << cnt);
1058 mask = (1 << cnt) - 1;
1059 res |= (d >> (16 - cnt)) & mask;
1060 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1061 CONDITIONAL_SET_FLAG(s == 1 &&
1062 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1063 F_OF);
1064 } if (s != 0) {
1065 /* set the new carry flag, Note that it is the low order
1066 bit of the result!!! */
1067 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1068 }
1069 return (u16)res;
1070}
1071
1072/****************************************************************************
1073REMARKS:
1074Implements the ROL instruction and side effects.
1075****************************************************************************/
1076u32 rol_long(u32 d, u8 s)
1077{
1078 u32 res, cnt, mask;
1079
1080 res = d;
1081 if ((cnt = s % 32) != 0) {
1082 res = (d << cnt);
1083 mask = (1 << cnt) - 1;
1084 res |= (d >> (32 - cnt)) & mask;
1085 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1086 CONDITIONAL_SET_FLAG(s == 1 &&
1087 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1088 F_OF);
1089 } if (s != 0) {
1090 /* set the new carry flag, Note that it is the low order
1091 bit of the result!!! */
1092 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1093 }
1094 return res;
1095}
1096
1097/****************************************************************************
1098REMARKS:
1099Implements the ROR instruction and side effects.
1100****************************************************************************/
1101u8 ror_byte(u8 d, u8 s)
1102{
1103 unsigned int res, cnt, mask;
1104
1105 /* rotate right */
1106 /*
1107 s is the rotate distance. It varies from 0 - 8.
1108 d is the byte object rotated.
1109
1110 have
1111
1112 B_7 ... B_0
1113
1114 The rotate is done mod 8.
1115
1116 IF n > 0
1117 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1118 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1119 */
1120 res = d;
1121 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
1122 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1123 res = (d << (8 - cnt));
1124
1125 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1126 mask = (1 << (8 - cnt)) - 1;
1127 res |= (d >> (cnt)) & mask;
1128
1129 /* set the new carry flag, Note that it is the low order
1130 bit of the result!!! */
1131 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1132 /* OVERFLOW is set *IFF* s==1, then it is the
1133 xor of the two most significant bits. Blecck. */
1134 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1135 } else if (s != 0) {
1136 /* set the new carry flag, Note that it is the low order
1137 bit of the result!!! */
1138 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1139 }
1140 return (u8)res;
1141}
1142
1143/****************************************************************************
1144REMARKS:
1145Implements the ROR instruction and side effects.
1146****************************************************************************/
1147u16 ror_word(u16 d, u8 s)
1148{
1149 unsigned int res, cnt, mask;
1150
1151 res = d;
1152 if ((cnt = s % 16) != 0) {
1153 res = (d << (16 - cnt));
1154 mask = (1 << (16 - cnt)) - 1;
1155 res |= (d >> (cnt)) & mask;
1156 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1157 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1158 } else if (s != 0) {
1159 /* set the new carry flag, Note that it is the low order
1160 bit of the result!!! */
1161 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1162 }
1163 return (u16)res;
1164}
1165
1166/****************************************************************************
1167REMARKS:
1168Implements the ROR instruction and side effects.
1169****************************************************************************/
1170u32 ror_long(u32 d, u8 s)
1171{
1172 u32 res, cnt, mask;
1173
1174 res = d;
1175 if ((cnt = s % 32) != 0) {
1176 res = (d << (32 - cnt));
1177 mask = (1 << (32 - cnt)) - 1;
1178 res |= (d >> (cnt)) & mask;
1179 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1180 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1181 } else if (s != 0) {
1182 /* set the new carry flag, Note that it is the low order
1183 bit of the result!!! */
1184 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1185 }
1186 return res;
1187}
1188
1189/****************************************************************************
1190REMARKS:
1191Implements the SHL instruction and side effects.
1192****************************************************************************/
1193u8 shl_byte(u8 d, u8 s)
1194{
1195 unsigned int cnt, res, cf;
1196
1197 if (s < 8) {
1198 cnt = s % 8;
1199
1200 /* last bit shifted out goes into carry flag */
1201 if (cnt > 0) {
1202 res = d << cnt;
1203 cf = d & (1 << (8 - cnt));
1204 CONDITIONAL_SET_FLAG(cf, F_CF);
1205 set_szp_flags_8((u8)res);
1206 } else {
1207 res = (u8) d;
1208 }
1209
1210 if (cnt == 1) {
1211 /* Needs simplification. */
1212 CONDITIONAL_SET_FLAG(
1213 (((res & 0x80) == 0x80) ^
1214 (ACCESS_FLAG(F_CF) != 0)),
1215 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1216 F_OF);
1217 } else {
1218 CLEAR_FLAG(F_OF);
1219 }
1220 } else {
1221 res = 0;
1222 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1223 CLEAR_FLAG(F_OF);
1224 CLEAR_FLAG(F_SF);
1225 SET_FLAG(F_PF);
1226 SET_FLAG(F_ZF);
1227 }
1228 return (u8)res;
1229}
1230
1231/****************************************************************************
1232REMARKS:
1233Implements the SHL instruction and side effects.
1234****************************************************************************/
1235u16 shl_word(u16 d, u8 s)
1236{
1237 unsigned int cnt, res, cf;
1238
1239 if (s < 16) {
1240 cnt = s % 16;
1241 if (cnt > 0) {
1242 res = d << cnt;
1243 cf = d & (1 << (16 - cnt));
1244 CONDITIONAL_SET_FLAG(cf, F_CF);
1245 set_szp_flags_16((u16)res);
1246 } else {
1247 res = (u16) d;
1248 }
1249
1250 if (cnt == 1) {
1251 CONDITIONAL_SET_FLAG(
1252 (((res & 0x8000) == 0x8000) ^
1253 (ACCESS_FLAG(F_CF) != 0)),
1254 F_OF);
1255 } else {
1256 CLEAR_FLAG(F_OF);
1257 }
1258 } else {
1259 res = 0;
1260 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1261 CLEAR_FLAG(F_OF);
1262 CLEAR_FLAG(F_SF);
1263 SET_FLAG(F_PF);
1264 SET_FLAG(F_ZF);
1265 }
1266 return (u16)res;
1267}
1268
1269/****************************************************************************
1270REMARKS:
1271Implements the SHL instruction and side effects.
1272****************************************************************************/
1273u32 shl_long(u32 d, u8 s)
1274{
1275 unsigned int cnt, res, cf;
1276
1277 if (s < 32) {
1278 cnt = s % 32;
1279 if (cnt > 0) {
1280 res = d << cnt;
1281 cf = d & (1 << (32 - cnt));
1282 CONDITIONAL_SET_FLAG(cf, F_CF);
1283 set_szp_flags_32((u32)res);
1284 } else {
1285 res = d;
1286 }
1287 if (cnt == 1) {
1288 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1289 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1290 } else {
1291 CLEAR_FLAG(F_OF);
1292 }
1293 } else {
1294 res = 0;
1295 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1296 CLEAR_FLAG(F_OF);
1297 CLEAR_FLAG(F_SF);
1298 SET_FLAG(F_PF);
1299 SET_FLAG(F_ZF);
1300 }
1301 return res;
1302}
1303
1304/****************************************************************************
1305REMARKS:
1306Implements the SHR instruction and side effects.
1307****************************************************************************/
1308u8 shr_byte(u8 d, u8 s)
1309{
1310 unsigned int cnt, res, cf;
1311
1312 if (s < 8) {
1313 cnt = s % 8;
1314 if (cnt > 0) {
1315 cf = d & (1 << (cnt - 1));
1316 res = d >> cnt;
1317 CONDITIONAL_SET_FLAG(cf, F_CF);
1318 set_szp_flags_8((u8)res);
1319 } else {
1320 res = (u8) d;
1321 }
1322
1323 if (cnt == 1) {
1324 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1325 } else {
1326 CLEAR_FLAG(F_OF);
1327 }
1328 } else {
1329 res = 0;
1330 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1331 CLEAR_FLAG(F_OF);
1332 CLEAR_FLAG(F_SF);
1333 SET_FLAG(F_PF);
1334 SET_FLAG(F_ZF);
1335 }
1336 return (u8)res;
1337}
1338
1339/****************************************************************************
1340REMARKS:
1341Implements the SHR instruction and side effects.
1342****************************************************************************/
1343u16 shr_word(u16 d, u8 s)
1344{
1345 unsigned int cnt, res, cf;
1346
1347 if (s < 16) {
1348 cnt = s % 16;
1349 if (cnt > 0) {
1350 cf = d & (1 << (cnt - 1));
1351 res = d >> cnt;
1352 CONDITIONAL_SET_FLAG(cf, F_CF);
1353 set_szp_flags_16((u16)res);
1354 } else {
1355 res = d;
1356 }
1357
1358 if (cnt == 1) {
1359 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1360 } else {
1361 CLEAR_FLAG(F_OF);
1362 }
1363 } else {
1364 res = 0;
1365 CLEAR_FLAG(F_CF);
1366 CLEAR_FLAG(F_OF);
1367 SET_FLAG(F_ZF);
1368 CLEAR_FLAG(F_SF);
1369 CLEAR_FLAG(F_PF);
1370 }
1371 return (u16)res;
1372}
1373
1374/****************************************************************************
1375REMARKS:
1376Implements the SHR instruction and side effects.
1377****************************************************************************/
1378u32 shr_long(u32 d, u8 s)
1379{
1380 unsigned int cnt, res, cf;
1381
1382 if (s < 32) {
1383 cnt = s % 32;
1384 if (cnt > 0) {
1385 cf = d & (1 << (cnt - 1));
1386 res = d >> cnt;
1387 CONDITIONAL_SET_FLAG(cf, F_CF);
1388 set_szp_flags_32((u32)res);
1389 } else {
1390 res = d;
1391 }
1392 if (cnt == 1) {
1393 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1394 } else {
1395 CLEAR_FLAG(F_OF);
1396 }
1397 } else {
1398 res = 0;
1399 CLEAR_FLAG(F_CF);
1400 CLEAR_FLAG(F_OF);
1401 SET_FLAG(F_ZF);
1402 CLEAR_FLAG(F_SF);
1403 CLEAR_FLAG(F_PF);
1404 }
1405 return res;
1406}
1407
1408/****************************************************************************
1409REMARKS:
1410Implements the SAR instruction and side effects.
1411****************************************************************************/
1412u8 sar_byte(u8 d, u8 s)
1413{
1414 unsigned int cnt, res, cf, mask, sf;
1415
1416 res = d;
1417 sf = d & 0x80;
1418 cnt = s % 8;
1419 if (cnt > 0 && cnt < 8) {
1420 mask = (1 << (8 - cnt)) - 1;
1421 cf = d & (1 << (cnt - 1));
1422 res = (d >> cnt) & mask;
1423 CONDITIONAL_SET_FLAG(cf, F_CF);
1424 if (sf) {
1425 res |= ~mask;
1426 }
1427 set_szp_flags_8((u8)res);
1428 } else if (cnt >= 8) {
1429 if (sf) {
1430 res = 0xff;
1431 SET_FLAG(F_CF);
1432 CLEAR_FLAG(F_ZF);
1433 SET_FLAG(F_SF);
1434 SET_FLAG(F_PF);
1435 } else {
1436 res = 0;
1437 CLEAR_FLAG(F_CF);
1438 SET_FLAG(F_ZF);
1439 CLEAR_FLAG(F_SF);
1440 CLEAR_FLAG(F_PF);
1441 }
1442 }
1443 return (u8)res;
1444}
1445
1446/****************************************************************************
1447REMARKS:
1448Implements the SAR instruction and side effects.
1449****************************************************************************/
1450u16 sar_word(u16 d, u8 s)
1451{
1452 unsigned int cnt, res, cf, mask, sf;
1453
1454 sf = d & 0x8000;
1455 cnt = s % 16;
1456 res = d;
1457 if (cnt > 0 && cnt < 16) {
1458 mask = (1 << (16 - cnt)) - 1;
1459 cf = d & (1 << (cnt - 1));
1460 res = (d >> cnt) & mask;
1461 CONDITIONAL_SET_FLAG(cf, F_CF);
1462 if (sf) {
1463 res |= ~mask;
1464 }
1465 set_szp_flags_16((u16)res);
1466 } else if (cnt >= 16) {
1467 if (sf) {
1468 res = 0xffff;
1469 SET_FLAG(F_CF);
1470 CLEAR_FLAG(F_ZF);
1471 SET_FLAG(F_SF);
1472 SET_FLAG(F_PF);
1473 } else {
1474 res = 0;
1475 CLEAR_FLAG(F_CF);
1476 SET_FLAG(F_ZF);
1477 CLEAR_FLAG(F_SF);
1478 CLEAR_FLAG(F_PF);
1479 }
1480 }
1481 return (u16)res;
1482}
1483
1484/****************************************************************************
1485REMARKS:
1486Implements the SAR instruction and side effects.
1487****************************************************************************/
1488u32 sar_long(u32 d, u8 s)
1489{
1490 u32 cnt, res, cf, mask, sf;
1491
1492 sf = d & 0x80000000;
1493 cnt = s % 32;
1494 res = d;
1495 if (cnt > 0 && cnt < 32) {
1496 mask = (1 << (32 - cnt)) - 1;
1497 cf = d & (1 << (cnt - 1));
1498 res = (d >> cnt) & mask;
1499 CONDITIONAL_SET_FLAG(cf, F_CF);
1500 if (sf) {
1501 res |= ~mask;
1502 }
1503 set_szp_flags_32(res);
1504 } else if (cnt >= 32) {
1505 if (sf) {
1506 res = 0xffffffff;
1507 SET_FLAG(F_CF);
1508 CLEAR_FLAG(F_ZF);
1509 SET_FLAG(F_SF);
1510 SET_FLAG(F_PF);
1511 } else {
1512 res = 0;
1513 CLEAR_FLAG(F_CF);
1514 SET_FLAG(F_ZF);
1515 CLEAR_FLAG(F_SF);
1516 CLEAR_FLAG(F_PF);
1517 }
1518 }
1519 return res;
1520}
1521
1522/****************************************************************************
1523REMARKS:
1524Implements the SHLD instruction and side effects.
1525****************************************************************************/
1526u16 shld_word (u16 d, u16 fill, u8 s)
1527{
1528 unsigned int cnt, res, cf;
1529
1530 if (s < 16) {
1531 cnt = s % 16;
1532 if (cnt > 0) {
1533 res = (d << cnt) | (fill >> (16-cnt));
1534 cf = d & (1 << (16 - cnt));
1535 CONDITIONAL_SET_FLAG(cf, F_CF);
1536 set_szp_flags_16((u16)res);
1537 } else {
1538 res = d;
1539 }
1540 if (cnt == 1) {
1541 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1542 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1543 } else {
1544 CLEAR_FLAG(F_OF);
1545 }
1546 } else {
1547 res = 0;
1548 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1549 CLEAR_FLAG(F_OF);
1550 CLEAR_FLAG(F_SF);
1551 SET_FLAG(F_PF);
1552 SET_FLAG(F_ZF);
1553 }
1554 return (u16)res;
1555}
1556
1557/****************************************************************************
1558REMARKS:
1559Implements the SHLD instruction and side effects.
1560****************************************************************************/
1561u32 shld_long (u32 d, u32 fill, u8 s)
1562{
1563 unsigned int cnt, res, cf;
1564
1565 if (s < 32) {
1566 cnt = s % 32;
1567 if (cnt > 0) {
1568 res = (d << cnt) | (fill >> (32-cnt));
1569 cf = d & (1 << (32 - cnt));
1570 CONDITIONAL_SET_FLAG(cf, F_CF);
1571 set_szp_flags_32((u32)res);
1572 } else {
1573 res = d;
1574 }
1575 if (cnt == 1) {
1576 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1577 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1578 } else {
1579 CLEAR_FLAG(F_OF);
1580 }
1581 } else {
1582 res = 0;
1583 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1584 CLEAR_FLAG(F_OF);
1585 CLEAR_FLAG(F_SF);
1586 SET_FLAG(F_PF);
1587 SET_FLAG(F_ZF);
1588 }
1589 return res;
1590}
1591
1592/****************************************************************************
1593REMARKS:
1594Implements the SHRD instruction and side effects.
1595****************************************************************************/
1596u16 shrd_word (u16 d, u16 fill, u8 s)
1597{
1598 unsigned int cnt, res, cf;
1599
1600 if (s < 16) {
1601 cnt = s % 16;
1602 if (cnt > 0) {
1603 cf = d & (1 << (cnt - 1));
1604 res = (d >> cnt) | (fill << (16 - cnt));
1605 CONDITIONAL_SET_FLAG(cf, F_CF);
1606 set_szp_flags_16((u16)res);
1607 } else {
1608 res = d;
1609 }
1610
1611 if (cnt == 1) {
1612 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1613 } else {
1614 CLEAR_FLAG(F_OF);
1615 }
1616 } else {
1617 res = 0;
1618 CLEAR_FLAG(F_CF);
1619 CLEAR_FLAG(F_OF);
1620 SET_FLAG(F_ZF);
1621 CLEAR_FLAG(F_SF);
1622 CLEAR_FLAG(F_PF);
1623 }
1624 return (u16)res;
1625}
1626
1627/****************************************************************************
1628REMARKS:
1629Implements the SHRD instruction and side effects.
1630****************************************************************************/
1631u32 shrd_long (u32 d, u32 fill, u8 s)
1632{
1633 unsigned int cnt, res, cf;
1634
1635 if (s < 32) {
1636 cnt = s % 32;
1637 if (cnt > 0) {
1638 cf = d & (1 << (cnt - 1));
1639 res = (d >> cnt) | (fill << (32 - cnt));
1640 CONDITIONAL_SET_FLAG(cf, F_CF);
1641 set_szp_flags_32((u32)res);
1642 } else {
1643 res = d;
1644 }
1645 if (cnt == 1) {
1646 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1647 } else {
1648 CLEAR_FLAG(F_OF);
1649 }
1650 } else {
1651 res = 0;
1652 CLEAR_FLAG(F_CF);
1653 CLEAR_FLAG(F_OF);
1654 SET_FLAG(F_ZF);
1655 CLEAR_FLAG(F_SF);
1656 CLEAR_FLAG(F_PF);
1657 }
1658 return res;
1659}
1660
1661/****************************************************************************
1662REMARKS:
1663Implements the SBB instruction and side effects.
1664****************************************************************************/
1665u8 sbb_byte(u8 d, u8 s)
1666{
1667 u32 res; /* all operands in native machine order */
1668 u32 bc;
1669
1670 if (ACCESS_FLAG(F_CF))
1671 res = d - s - 1;
1672 else
1673 res = d - s;
1674 set_szp_flags_8((u8)res);
1675
1676 /* calculate the borrow chain. See note at top */
1677 bc = (res & (~d | s)) | (~d & s);
1678 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1679 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1680 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1681 return (u8)res;
1682}
1683
1684/****************************************************************************
1685REMARKS:
1686Implements the SBB instruction and side effects.
1687****************************************************************************/
1688u16 sbb_word(u16 d, u16 s)
1689{
1690 u32 res; /* all operands in native machine order */
1691 u32 bc;
1692
1693 if (ACCESS_FLAG(F_CF))
1694 res = d - s - 1;
1695 else
1696 res = d - s;
1697 set_szp_flags_16((u16)res);
1698
1699 /* calculate the borrow chain. See note at top */
1700 bc = (res & (~d | s)) | (~d & s);
1701 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1702 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1703 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1704 return (u16)res;
1705}
1706
1707/****************************************************************************
1708REMARKS:
1709Implements the SBB instruction and side effects.
1710****************************************************************************/
1711u32 sbb_long(u32 d, u32 s)
1712{
1713 u32 res; /* all operands in native machine order */
1714 u32 bc;
1715
1716 if (ACCESS_FLAG(F_CF))
1717 res = d - s - 1;
1718 else
1719 res = d - s;
1720
1721 set_szp_flags_32(res);
1722
1723 /* calculate the borrow chain. See note at top */
1724 bc = (res & (~d | s)) | (~d & s);
1725 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1726 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1727 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1728 return res;
1729}
1730
1731/****************************************************************************
1732REMARKS:
1733Implements the SUB instruction and side effects.
1734****************************************************************************/
1735u8 sub_byte(u8 d, u8 s)
1736{
1737 u32 res; /* all operands in native machine order */
1738 u32 bc;
1739
1740 res = d - s;
1741 set_szp_flags_8((u8)res);
1742
1743 /* calculate the borrow chain. See note at top */
1744 bc = (res & (~d | s)) | (~d & s);
1745 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1746 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1747 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1748 return (u8)res;
1749}
1750
1751/****************************************************************************
1752REMARKS:
1753Implements the SUB instruction and side effects.
1754****************************************************************************/
1755u16 sub_word(u16 d, u16 s)
1756{
1757 u32 res; /* all operands in native machine order */
1758 u32 bc;
1759
1760 res = d - s;
1761 set_szp_flags_16((u16)res);
1762
1763 /* calculate the borrow chain. See note at top */
1764 bc = (res & (~d | s)) | (~d & s);
1765 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1766 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1767 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1768 return (u16)res;
1769}
1770
1771/****************************************************************************
1772REMARKS:
1773Implements the SUB instruction and side effects.
1774****************************************************************************/
1775u32 sub_long(u32 d, u32 s)
1776{
1777 u32 res; /* all operands in native machine order */
1778 u32 bc;
1779
1780 res = d - s;
1781 set_szp_flags_32(res);
1782
1783 /* calculate the borrow chain. See note at top */
1784 bc = (res & (~d | s)) | (~d & s);
1785 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1786 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1787 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1788 return res;
1789}
1790
1791/****************************************************************************
1792REMARKS:
1793Implements the TEST instruction and side effects.
1794****************************************************************************/
1795void test_byte(u8 d, u8 s)
1796{
1797 u32 res; /* all operands in native machine order */
1798
1799 res = d & s;
1800
1801 CLEAR_FLAG(F_OF);
1802 set_szp_flags_8((u8)res);
Martin Roth63373ed2013-07-08 16:24:19 -06001803 /* AF == don't care */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001804 CLEAR_FLAG(F_CF);
1805}
1806
1807/****************************************************************************
1808REMARKS:
1809Implements the TEST instruction and side effects.
1810****************************************************************************/
1811void test_word(u16 d, u16 s)
1812{
1813 u32 res; /* all operands in native machine order */
1814
1815 res = d & s;
1816
1817 CLEAR_FLAG(F_OF);
1818 set_szp_flags_16((u16)res);
Martin Roth63373ed2013-07-08 16:24:19 -06001819 /* AF == don't care */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001820 CLEAR_FLAG(F_CF);
1821}
1822
1823/****************************************************************************
1824REMARKS:
1825Implements the TEST instruction and side effects.
1826****************************************************************************/
1827void test_long(u32 d, u32 s)
1828{
1829 u32 res; /* all operands in native machine order */
1830
1831 res = d & s;
1832
1833 CLEAR_FLAG(F_OF);
1834 set_szp_flags_32(res);
Martin Roth63373ed2013-07-08 16:24:19 -06001835 /* AF == don't care */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001836 CLEAR_FLAG(F_CF);
1837}
1838
1839/****************************************************************************
1840REMARKS:
1841Implements the XOR instruction and side effects.
1842****************************************************************************/
1843u8 xor_byte(u8 d, u8 s)
1844{
1845 u8 res; /* all operands in native machine order */
1846
1847 res = d ^ s;
1848 no_carry_byte_side_eff(res);
1849 return res;
1850}
1851
1852/****************************************************************************
1853REMARKS:
1854Implements the XOR instruction and side effects.
1855****************************************************************************/
1856u16 xor_word(u16 d, u16 s)
1857{
1858 u16 res; /* all operands in native machine order */
1859
1860 res = d ^ s;
1861 no_carry_word_side_eff(res);
1862 return res;
1863}
1864
1865/****************************************************************************
1866REMARKS:
1867Implements the XOR instruction and side effects.
1868****************************************************************************/
1869u32 xor_long(u32 d, u32 s)
1870{
1871 u32 res; /* all operands in native machine order */
1872
1873 res = d ^ s;
1874 no_carry_long_side_eff(res);
1875 return res;
1876}
1877
1878/****************************************************************************
1879REMARKS:
1880Implements the IMUL instruction and side effects.
1881****************************************************************************/
1882void imul_byte(u8 s)
1883{
1884 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1885
1886 M.x86.R_AX = res;
1887 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
1888 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
1889 CLEAR_FLAG(F_CF);
1890 CLEAR_FLAG(F_OF);
1891 } else {
1892 SET_FLAG(F_CF);
1893 SET_FLAG(F_OF);
1894 }
1895}
1896
1897/****************************************************************************
1898REMARKS:
1899Implements the IMUL instruction and side effects.
1900****************************************************************************/
1901void imul_word(u16 s)
1902{
1903 s32 res = (s16)M.x86.R_AX * (s16)s;
1904
1905 M.x86.R_AX = (u16)res;
1906 M.x86.R_DX = (u16)(res >> 16);
1907 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
1908 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
1909 CLEAR_FLAG(F_CF);
1910 CLEAR_FLAG(F_OF);
1911 } else {
1912 SET_FLAG(F_CF);
1913 SET_FLAG(F_OF);
1914 }
1915}
1916
1917/****************************************************************************
1918REMARKS:
1919Implements the IMUL instruction and side effects.
1920****************************************************************************/
1921void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1922{
1923#ifdef __HAS_LONG_LONG__
1924 s64 res = (s64)(s32)d * (s64)(s32)s;
1925
1926 *res_lo = (u32)res;
1927 *res_hi = (u32)(res >> 32);
1928#else
1929 u32 d_lo,d_hi,d_sign;
1930 u32 s_lo,s_hi,s_sign;
1931 u32 rlo_lo,rlo_hi,rhi_lo;
1932
1933 if ((d_sign = d & 0x80000000) != 0)
1934 d = -d;
1935 d_lo = d & 0xFFFF;
1936 d_hi = d >> 16;
1937 if ((s_sign = s & 0x80000000) != 0)
1938 s = -s;
1939 s_lo = s & 0xFFFF;
1940 s_hi = s >> 16;
1941 rlo_lo = d_lo * s_lo;
1942 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
1943 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
1944 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
1945 *res_hi = rhi_lo;
1946 if (d_sign != s_sign) {
1947 d = ~*res_lo;
1948 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1949 *res_lo = ~*res_lo+1;
1950 *res_hi = ~*res_hi+(s >> 16);
1951 }
1952#endif
1953}
1954
1955/****************************************************************************
1956REMARKS:
1957Implements the IMUL instruction and side effects.
1958****************************************************************************/
1959void imul_long(u32 s)
1960{
1961 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
1962 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
1963 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
1964 CLEAR_FLAG(F_CF);
1965 CLEAR_FLAG(F_OF);
1966 } else {
1967 SET_FLAG(F_CF);
1968 SET_FLAG(F_OF);
1969 }
1970}
1971
1972/****************************************************************************
1973REMARKS:
1974Implements the MUL instruction and side effects.
1975****************************************************************************/
1976void mul_byte(u8 s)
1977{
1978 u16 res = (u16)(M.x86.R_AL * s);
1979
1980 M.x86.R_AX = res;
1981 if (M.x86.R_AH == 0) {
1982 CLEAR_FLAG(F_CF);
1983 CLEAR_FLAG(F_OF);
1984 } else {
1985 SET_FLAG(F_CF);
1986 SET_FLAG(F_OF);
1987 }
1988}
1989
1990/****************************************************************************
1991REMARKS:
1992Implements the MUL instruction and side effects.
1993****************************************************************************/
1994void mul_word(u16 s)
1995{
1996 u32 res = M.x86.R_AX * s;
1997
1998 M.x86.R_AX = (u16)res;
1999 M.x86.R_DX = (u16)(res >> 16);
2000 if (M.x86.R_DX == 0) {
2001 CLEAR_FLAG(F_CF);
2002 CLEAR_FLAG(F_OF);
2003 } else {
2004 SET_FLAG(F_CF);
2005 SET_FLAG(F_OF);
2006 }
2007}
2008
2009/****************************************************************************
2010REMARKS:
2011Implements the MUL instruction and side effects.
2012****************************************************************************/
2013void mul_long(u32 s)
2014{
2015#ifdef __HAS_LONG_LONG__
2016 u64 res = (u64)M.x86.R_EAX * s;
2017
2018 M.x86.R_EAX = (u32)res;
2019 M.x86.R_EDX = (u32)(res >> 32);
2020#else
2021 u32 a,a_lo,a_hi;
2022 u32 s_lo,s_hi;
2023 u32 rlo_lo,rlo_hi,rhi_lo;
2024
2025 a = M.x86.R_EAX;
2026 a_lo = a & 0xFFFF;
2027 a_hi = a >> 16;
2028 s_lo = s & 0xFFFF;
2029 s_hi = s >> 16;
2030 rlo_lo = a_lo * s_lo;
2031 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2032 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2033 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2034 M.x86.R_EDX = rhi_lo;
2035#endif
2036 if (M.x86.R_EDX == 0) {
2037 CLEAR_FLAG(F_CF);
2038 CLEAR_FLAG(F_OF);
2039 } else {
2040 SET_FLAG(F_CF);
2041 SET_FLAG(F_OF);
2042 }
2043}
2044
2045/****************************************************************************
2046REMARKS:
2047Implements the IDIV instruction and side effects.
2048****************************************************************************/
2049void idiv_byte(u8 s)
2050{
2051 s32 dvd, div, mod;
2052
2053 dvd = (s16)M.x86.R_AX;
2054 if (s == 0) {
2055 x86emu_intr_raise(0);
2056 return;
2057 }
2058 div = dvd / (s8)s;
2059 mod = dvd % (s8)s;
2060 if (abs(div) > 0x7f) {
2061 x86emu_intr_raise(0);
2062 return;
2063 }
2064 M.x86.R_AL = (s8) div;
2065 M.x86.R_AH = (s8) mod;
2066}
2067
2068/****************************************************************************
2069REMARKS:
2070Implements the IDIV instruction and side effects.
2071****************************************************************************/
2072void idiv_word(u16 s)
2073{
2074 s32 dvd, div, mod;
2075
2076 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2077 if (s == 0) {
2078 x86emu_intr_raise(0);
2079 return;
2080 }
2081 div = dvd / (s16)s;
2082 mod = dvd % (s16)s;
2083 if (abs(div) > 0x7fff) {
2084 x86emu_intr_raise(0);
2085 return;
2086 }
2087 CLEAR_FLAG(F_CF);
2088 CLEAR_FLAG(F_SF);
2089 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2090 set_parity_flag(mod);
2091
2092 M.x86.R_AX = (u16)div;
2093 M.x86.R_DX = (u16)mod;
2094}
2095
2096/****************************************************************************
2097REMARKS:
2098Implements the IDIV instruction and side effects.
2099****************************************************************************/
2100void idiv_long(u32 s)
2101{
2102#ifdef __HAS_LONG_LONG__
2103 s64 dvd, div, mod;
2104
2105 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2106 if (s == 0) {
2107 x86emu_intr_raise(0);
2108 return;
2109 }
2110 div = dvd / (s32)s;
2111 mod = dvd % (s32)s;
2112 if (abs(div) > 0x7fffffff) {
2113 x86emu_intr_raise(0);
2114 return;
2115 }
2116#else
2117 s32 div = 0, mod;
2118 s32 h_dvd = M.x86.R_EDX;
2119 u32 l_dvd = M.x86.R_EAX;
2120 u32 abs_s = s & 0x7FFFFFFF;
2121 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2122 u32 h_s = abs_s >> 1;
2123 u32 l_s = abs_s << 31;
2124 int counter = 31;
2125 int carry;
2126
2127 if (s == 0) {
2128 x86emu_intr_raise(0);
2129 return;
2130 }
2131 do {
2132 div <<= 1;
2133 carry = (l_dvd >= l_s) ? 0 : 1;
2134
2135 if (abs_h_dvd < (h_s + carry)) {
2136 h_s >>= 1;
2137 l_s = abs_s << (--counter);
2138 continue;
2139 } else {
2140 abs_h_dvd -= (h_s + carry);
2141 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2142 : (l_dvd - l_s);
2143 h_s >>= 1;
2144 l_s = abs_s << (--counter);
2145 div |= 1;
2146 continue;
2147 }
2148
2149 } while (counter > -1);
2150 /* overflow */
2151 if (abs_h_dvd || (l_dvd > abs_s)) {
2152 x86emu_intr_raise(0);
2153 return;
2154 }
2155 /* sign */
2156 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2157 mod = l_dvd;
2158
2159#endif
2160 CLEAR_FLAG(F_CF);
2161 CLEAR_FLAG(F_AF);
2162 CLEAR_FLAG(F_SF);
2163 SET_FLAG(F_ZF);
2164 set_parity_flag(mod);
2165
2166 M.x86.R_EAX = (u32)div;
2167 M.x86.R_EDX = (u32)mod;
2168}
2169
2170/****************************************************************************
2171REMARKS:
2172Implements the DIV instruction and side effects.
2173****************************************************************************/
2174void div_byte(u8 s)
2175{
2176 u32 dvd, div, mod;
2177
2178 dvd = M.x86.R_AX;
2179 if (s == 0) {
2180 x86emu_intr_raise(0);
2181 return;
2182 }
2183 div = dvd / (u8)s;
2184 mod = dvd % (u8)s;
2185 if (abs(div) > 0xff) {
2186 x86emu_intr_raise(0);
2187 return;
2188 }
2189 M.x86.R_AL = (u8)div;
2190 M.x86.R_AH = (u8)mod;
2191}
2192
2193/****************************************************************************
2194REMARKS:
2195Implements the DIV instruction and side effects.
2196****************************************************************************/
2197void div_word(u16 s)
2198{
2199 u32 dvd, div, mod;
2200
2201 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2202 if (s == 0) {
2203 x86emu_intr_raise(0);
2204 return;
2205 }
2206 div = dvd / (u16)s;
2207 mod = dvd % (u16)s;
2208 if (abs(div) > 0xffff) {
2209 x86emu_intr_raise(0);
2210 return;
2211 }
2212 CLEAR_FLAG(F_CF);
2213 CLEAR_FLAG(F_SF);
2214 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2215 set_parity_flag(mod);
2216
2217 M.x86.R_AX = (u16)div;
2218 M.x86.R_DX = (u16)mod;
2219}
2220
2221/****************************************************************************
2222REMARKS:
2223Implements the DIV instruction and side effects.
2224****************************************************************************/
2225void div_long(u32 s)
2226{
2227#ifdef __HAS_LONG_LONG__
2228 u64 dvd, div, mod;
2229
2230 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2231 if (s == 0) {
2232 x86emu_intr_raise(0);
2233 return;
2234 }
2235 div = dvd / (u32)s;
2236 mod = dvd % (u32)s;
2237 if (abs(div) > 0xffffffff) {
2238 x86emu_intr_raise(0);
2239 return;
2240 }
2241#else
2242 s32 div = 0, mod;
2243 s32 h_dvd = M.x86.R_EDX;
2244 u32 l_dvd = M.x86.R_EAX;
2245
2246 u32 h_s = s;
2247 u32 l_s = 0;
2248 int counter = 32;
2249 int carry;
2250
2251 if (s == 0) {
2252 x86emu_intr_raise(0);
2253 return;
2254 }
2255 do {
2256 div <<= 1;
2257 carry = (l_dvd >= l_s) ? 0 : 1;
2258
2259 if (h_dvd < (h_s + carry)) {
2260 h_s >>= 1;
2261 l_s = s << (--counter);
2262 continue;
2263 } else {
2264 h_dvd -= (h_s + carry);
2265 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2266 : (l_dvd - l_s);
2267 h_s >>= 1;
2268 l_s = s << (--counter);
2269 div |= 1;
2270 continue;
2271 }
2272
2273 } while (counter > -1);
2274 /* overflow */
2275 if (h_dvd || (l_dvd > s)) {
2276 x86emu_intr_raise(0);
2277 return;
2278 }
2279 mod = l_dvd;
2280#endif
2281 CLEAR_FLAG(F_CF);
2282 CLEAR_FLAG(F_AF);
2283 CLEAR_FLAG(F_SF);
2284 SET_FLAG(F_ZF);
2285 set_parity_flag(mod);
2286
2287 M.x86.R_EAX = (u32)div;
2288 M.x86.R_EDX = (u32)mod;
2289}
2290
2291/****************************************************************************
2292REMARKS:
2293Implements the IN string instruction and side effects.
2294****************************************************************************/
2295
2296static void single_in(int size)
2297{
2298 if(size == 1)
2299 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
2300 else if (size == 2)
2301 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
2302 else
2303 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
2304}
2305
2306void ins(int size)
2307{
2308 int inc = size;
2309
2310 if (ACCESS_FLAG(F_DF)) {
2311 inc = -size;
2312 }
2313 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Martin Roth63373ed2013-07-08 16:24:19 -06002314 /* don't care whether REPE or REPNE */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002315 /* in until (E)CX is ZERO. */
2316 u32 count = ((M.x86.mode & SYSMODE_32BIT_REP) ?
2317 M.x86.R_ECX : M.x86.R_CX);
2318 while (count--) {
2319 single_in(size);
2320 M.x86.R_DI += inc;
2321 }
2322 M.x86.R_CX = 0;
2323 if (M.x86.mode & SYSMODE_32BIT_REP) {
2324 M.x86.R_ECX = 0;
2325 }
2326 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2327 } else {
2328 single_in(size);
2329 M.x86.R_DI += inc;
2330 }
2331}
2332
2333/****************************************************************************
2334REMARKS:
2335Implements the OUT string instruction and side effects.
2336****************************************************************************/
2337
2338static void single_out(int size)
2339{
2340 if(size == 1)
2341 (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2342 else if (size == 2)
2343 (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2344 else
2345 (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2346}
2347
2348void outs(int size)
2349{
2350 int inc = size;
2351
2352 if (ACCESS_FLAG(F_DF)) {
2353 inc = -size;
2354 }
2355 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Martin Roth63373ed2013-07-08 16:24:19 -06002356 /* don't care whether REPE or REPNE */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002357 /* out until (E)CX is ZERO. */
2358 u32 count = ((M.x86.mode & SYSMODE_32BIT_REP) ?
2359 M.x86.R_ECX : M.x86.R_CX);
2360 while (count--) {
2361 single_out(size);
2362 M.x86.R_SI += inc;
2363 }
2364 M.x86.R_CX = 0;
2365 if (M.x86.mode & SYSMODE_32BIT_REP) {
2366 M.x86.R_ECX = 0;
2367 }
2368 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2369 } else {
2370 single_out(size);
2371 M.x86.R_SI += inc;
2372 }
2373}
2374
2375/****************************************************************************
2376PARAMETERS:
2377addr - Address to fetch word from
2378
2379REMARKS:
2380Fetches a word from emulator memory using an absolute address.
2381****************************************************************************/
2382u16 mem_access_word(int addr)
2383{
2384DB( if (CHECK_MEM_ACCESS())
2385 x86emu_check_mem_access(addr);)
2386 return (*sys_rdw)(addr);
2387}
2388
2389/****************************************************************************
2390REMARKS:
2391Pushes a word onto the stack.
2392
2393NOTE: Do not inline this, as (*sys_wrX) is already inline!
2394****************************************************************************/
2395void push_word(u16 w)
2396{
2397DB( if (CHECK_SP_ACCESS())
2398 x86emu_check_sp_access();)
2399 M.x86.R_SP -= 2;
2400 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2401}
2402
2403/****************************************************************************
2404REMARKS:
2405Pushes a long onto the stack.
2406
2407NOTE: Do not inline this, as (*sys_wrX) is already inline!
2408****************************************************************************/
2409void push_long(u32 w)
2410{
2411DB( if (CHECK_SP_ACCESS())
2412 x86emu_check_sp_access();)
2413 M.x86.R_SP -= 4;
2414 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2415}
2416
2417/****************************************************************************
2418REMARKS:
2419Pops a word from the stack.
2420
2421NOTE: Do not inline this, as (*sys_rdX) is already inline!
2422****************************************************************************/
2423u16 pop_word(void)
2424{
2425 u16 res;
2426
2427DB( if (CHECK_SP_ACCESS())
2428 x86emu_check_sp_access();)
2429 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2430 M.x86.R_SP += 2;
2431 return res;
2432}
2433
2434/****************************************************************************
2435REMARKS:
2436Pops a long from the stack.
2437
2438NOTE: Do not inline this, as (*sys_rdX) is already inline!
2439****************************************************************************/
2440u32 pop_long(void)
2441{
2442 u32 res;
2443
2444DB( if (CHECK_SP_ACCESS())
2445 x86emu_check_sp_access();)
2446 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2447 M.x86.R_SP += 4;
2448 return res;
2449}
2450
Stefan Reinauer7110d402009-11-03 14:59:43 +00002451/****************************************************************************
2452REMARKS:
2453CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
2454****************************************************************************/
2455void x86emu_cpuid(void)
2456{
2457 u32 feature = M.x86.R_EAX;
2458
2459 switch (feature) {
2460 case 0:
2461 /* Regardless if we have real data from the hardware, the emulator
2462 * will only support upto feature 1, which we set in register EAX.
2463 * Registers EBX:EDX:ECX contain a string identifying the CPU.
2464 */
2465 M.x86.R_EAX = 1;
2466 /* EBX:EDX:ECX = "GenuineIntel" */
2467 M.x86.R_EBX = 0x756e6547;
2468 M.x86.R_EDX = 0x49656e69;
2469 M.x86.R_ECX = 0x6c65746e;
2470 break;
2471 case 1:
2472 /* If we don't have x86 compatible hardware, we return values from an
2473 * Intel 486dx4; which was one of the first processors to have CPUID.
2474 */
2475 M.x86.R_EAX = 0x00000480;
2476 M.x86.R_EBX = 0x00000000;
2477 M.x86.R_ECX = 0x00000000;
2478 M.x86.R_EDX = 0x00000002; /* VME */
2479 /* In the case that we have hardware CPUID instruction, we make sure
2480 * that the features reported are limited to TSC and VME.
2481 */
2482 M.x86.R_EDX &= 0x00000012;
2483 break;
2484 default:
2485 /* Finally, we don't support any additional features. Most CPUs
2486 * return all zeros when queried for invalid or unsupported feature
2487 * numbers.
2488 */
2489 M.x86.R_EAX = 0;
2490 M.x86.R_EBX = 0;
2491 M.x86.R_ECX = 0;
2492 M.x86.R_EDX = 0;
2493 break;
2494 }
2495}