xref: /aosp_15_r20/external/coreboot/src/device/oprom/x86emu/prim_ops.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /****************************************************************************
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 a lot 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 
115 static 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 /*--------- Side effects helper functions -------*/
133 
134 /****************************************************************************
135 REMARKS:
136 implements side effects for byte operations that don't overflow
137 ****************************************************************************/
138 
set_parity_flag(u32 res)139 static void set_parity_flag(u32 res)
140 {
141     CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
142 }
143 
set_szp_flags_8(u8 res)144 static void set_szp_flags_8(u8 res)
145 {
146     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
147     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
148     set_parity_flag(res);
149 }
150 
set_szp_flags_16(u16 res)151 static void set_szp_flags_16(u16 res)
152 {
153     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
154     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
155     set_parity_flag(res);
156 }
157 
set_szp_flags_32(u32 res)158 static void set_szp_flags_32(u32 res)
159 {
160     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
161     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
162     set_parity_flag(res);
163 }
164 
no_carry_byte_side_eff(u8 res)165 static void no_carry_byte_side_eff(u8 res)
166 {
167     CLEAR_FLAG(F_OF);
168     CLEAR_FLAG(F_CF);
169     CLEAR_FLAG(F_AF);
170     set_szp_flags_8(res);
171 }
172 
no_carry_word_side_eff(u16 res)173 static void no_carry_word_side_eff(u16 res)
174 {
175     CLEAR_FLAG(F_OF);
176     CLEAR_FLAG(F_CF);
177     CLEAR_FLAG(F_AF);
178     set_szp_flags_16(res);
179 }
180 
no_carry_long_side_eff(u32 res)181 static void no_carry_long_side_eff(u32 res)
182 {
183     CLEAR_FLAG(F_OF);
184     CLEAR_FLAG(F_CF);
185     CLEAR_FLAG(F_AF);
186     set_szp_flags_32(res);
187 }
188 
calc_carry_chain(int bits,u32 d,u32 s,u32 res,int set_carry)189 static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
190 {
191     u32 cc;
192 
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);
198     }
199 }
200 
calc_borrow_chain(int bits,u32 d,u32 s,u32 res,int set_carry)201 static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
202 {
203     u32 bc;
204 
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);
210     }
211 }
212 
213 /****************************************************************************
214 REMARKS:
215 Implements the AAA instruction and side effects.
216 ****************************************************************************/
aaa_word(u16 d)217 u16 aaa_word(u16 d)
218 {
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);
228     }
229     res = (u16)(d & 0xFF0F);
230     set_szp_flags_16(res);
231     return res;
232 }
233 
234 /****************************************************************************
235 REMARKS:
236 Implements the AAA instruction and side effects.
237 ****************************************************************************/
aas_word(u16 d)238 u16 aas_word(u16 d)
239 {
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);
249     }
250     res = (u16)(d & 0xFF0F);
251     set_szp_flags_16(res);
252     return res;
253 }
254 
255 /****************************************************************************
256 REMARKS:
257 Implements the AAD instruction and side effects.
258 ****************************************************************************/
aad_word(u16 d)259 u16 aad_word(u16 d)
260 {
261     u16 l;
262     u8 hb, lb;
263 
264     hb = (u8)((d >> 8) & 0xff);
265     lb = (u8)((d & 0xff));
266     l = (u16)((lb + 10 * hb) & 0xFF);
267 
268     no_carry_byte_side_eff(l & 0xFF);
269     return l;
270 }
271 
272 /****************************************************************************
273 REMARKS:
274 Implements the AAM instruction and side effects.
275 ****************************************************************************/
aam_word(u8 d)276 u16 aam_word(u8 d)
277 {
278     u16 h, l;
279 
280     h = (u16)(d / 10);
281     l = (u16)(d % 10);
282     l |= (u16)(h << 8);
283 
284     no_carry_byte_side_eff(l & 0xFF);
285     return l;
286 }
287 
288 /****************************************************************************
289 REMARKS:
290 Implements the ADC instruction and side effects.
291 ****************************************************************************/
adc_byte(u8 d,u8 s)292 u8 adc_byte(u8 d, u8 s)
293 {
294     u32 res;   /* all operands in native machine order */
295 
296     res = d + s;
297     if (ACCESS_FLAG(F_CF)) res++;
298 
299     set_szp_flags_8(res);
300     calc_carry_chain(8,s,d,res,1);
301 
302     return (u8)res;
303 }
304 
305 /****************************************************************************
306 REMARKS:
307 Implements the ADC instruction and side effects.
308 ****************************************************************************/
adc_word(u16 d,u16 s)309 u16 adc_word(u16 d, u16 s)
310 {
311     u32 res;   /* all operands in native machine order */
312 
313     res = d + s;
314     if (ACCESS_FLAG(F_CF))
315         res++;
316 
317     set_szp_flags_16((u16)res);
318     calc_carry_chain(16,s,d,res,1);
319 
320     return (u16)res;
321 }
322 
323 /****************************************************************************
324 REMARKS:
325 Implements the ADC instruction and side effects.
326 ****************************************************************************/
adc_long(u32 d,u32 s)327 u32 adc_long(u32 d, u32 s)
328 {
329     u32 lo;    /* all operands in native machine order */
330     u32 hi;
331     u32 res;
332 
333     lo = (d & 0xFFFF) + (s & 0xFFFF);
334     res = d + s;
335 
336     if (ACCESS_FLAG(F_CF)) {
337         lo++;
338         res++;
339     }
340 
341     hi = (lo >> 16) + (d >> 16) + (s >> 16);
342 
343     set_szp_flags_32(res);
344     calc_carry_chain(32,s,d,res,0);
345 
346     CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
347 
348     return res;
349 }
350 
351 /****************************************************************************
352 REMARKS:
353 Implements the ADD instruction and side effects.
354 ****************************************************************************/
add_byte(u8 d,u8 s)355 u8 add_byte(u8 d, u8 s)
356 {
357     u32 res;   /* all operands in native machine order */
358 
359     res = d + s;
360     set_szp_flags_8((u8)res);
361     calc_carry_chain(8,s,d,res,1);
362 
363     return (u8)res;
364 }
365 
366 /****************************************************************************
367 REMARKS:
368 Implements the ADD instruction and side effects.
369 ****************************************************************************/
add_word(u16 d,u16 s)370 u16 add_word(u16 d, u16 s)
371 {
372     u32 res;   /* all operands in native machine order */
373 
374     res = d + s;
375     set_szp_flags_16((u16)res);
376     calc_carry_chain(16,s,d,res,1);
377 
378     return (u16)res;
379 }
380 
381 /****************************************************************************
382 REMARKS:
383 Implements the ADD instruction and side effects.
384 ****************************************************************************/
add_long(u32 d,u32 s)385 u32 add_long(u32 d, u32 s)
386 {
387     u32 res;
388 
389     res = d + s;
390     set_szp_flags_32(res);
391     calc_carry_chain(32,s,d,res,0);
392 
393     CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
394 
395     return res;
396 }
397 
398 /****************************************************************************
399 REMARKS:
400 Implements the AND instruction and side effects.
401 ****************************************************************************/
and_byte(u8 d,u8 s)402 u8 and_byte(u8 d, u8 s)
403 {
404     u8 res;    /* all operands in native machine order */
405 
406     res = d & s;
407 
408     no_carry_byte_side_eff(res);
409     return res;
410 }
411 
412 /****************************************************************************
413 REMARKS:
414 Implements the AND instruction and side effects.
415 ****************************************************************************/
and_word(u16 d,u16 s)416 u16 and_word(u16 d, u16 s)
417 {
418     u16 res;   /* all operands in native machine order */
419 
420     res = d & s;
421 
422     no_carry_word_side_eff(res);
423     return res;
424 }
425 
426 /****************************************************************************
427 REMARKS:
428 Implements the AND instruction and side effects.
429 ****************************************************************************/
and_long(u32 d,u32 s)430 u32 and_long(u32 d, u32 s)
431 {
432     u32 res;   /* all operands in native machine order */
433 
434     res = d & s;
435     no_carry_long_side_eff(res);
436     return res;
437 }
438 
439 /****************************************************************************
440 REMARKS:
441 Implements the CMP instruction and side effects.
442 ****************************************************************************/
cmp_byte(u8 d,u8 s)443 u8 cmp_byte(u8 d, u8 s)
444 {
445     u32 res;   /* all operands in native machine order */
446 
447     res = d - s;
448     set_szp_flags_8((u8)res);
449     calc_borrow_chain(8, d, s, res, 1);
450 
451     return d;
452 }
453 
454 /****************************************************************************
455 REMARKS:
456 Implements the CMP instruction and side effects.
457 ****************************************************************************/
cmp_word(u16 d,u16 s)458 u16 cmp_word(u16 d, u16 s)
459 {
460     u32 res;   /* all operands in native machine order */
461 
462     res = d - s;
463     set_szp_flags_16((u16)res);
464     calc_borrow_chain(16, d, s, res, 1);
465 
466     return d;
467 }
468 
469 /****************************************************************************
470 REMARKS:
471 Implements the CMP instruction and side effects.
472 ****************************************************************************/
cmp_long(u32 d,u32 s)473 u32 cmp_long(u32 d, u32 s)
474 {
475     u32 res;   /* all operands in native machine order */
476 
477     res = d - s;
478     set_szp_flags_32(res);
479     calc_borrow_chain(32, d, s, res, 1);
480 
481     return d;
482 }
483 
484 /****************************************************************************
485 REMARKS:
486 Implements the DAA instruction and side effects.
487 ****************************************************************************/
daa_byte(u8 d)488 u8 daa_byte(u8 d)
489 {
490     u32 res = d;
491     if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
492         res += 6;
493         SET_FLAG(F_AF);
494     }
495     if (res > 0x9F || ACCESS_FLAG(F_CF)) {
496         res += 0x60;
497         SET_FLAG(F_CF);
498     }
499     set_szp_flags_8((u8)res);
500     return (u8)res;
501 }
502 
503 /****************************************************************************
504 REMARKS:
505 Implements the DAS instruction and side effects.
506 ****************************************************************************/
das_byte(u8 d)507 u8 das_byte(u8 d)
508 {
509     if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
510         d -= 6;
511         SET_FLAG(F_AF);
512     }
513     if (d > 0x9F || ACCESS_FLAG(F_CF)) {
514         d -= 0x60;
515         SET_FLAG(F_CF);
516     }
517     set_szp_flags_8(d);
518     return d;
519 }
520 
521 /****************************************************************************
522 REMARKS:
523 Implements the DEC instruction and side effects.
524 ****************************************************************************/
dec_byte(u8 d)525 u8 dec_byte(u8 d)
526 {
527     u32 res;   /* all operands in native machine order */
528 
529     res = d - 1;
530     set_szp_flags_8((u8)res);
531     calc_borrow_chain(8, d, 1, res, 0);
532 
533     return (u8)res;
534 }
535 
536 /****************************************************************************
537 REMARKS:
538 Implements the DEC instruction and side effects.
539 ****************************************************************************/
dec_word(u16 d)540 u16 dec_word(u16 d)
541 {
542     u32 res;   /* all operands in native machine order */
543 
544     res = d - 1;
545     set_szp_flags_16((u16)res);
546     calc_borrow_chain(16, d, 1, res, 0);
547 
548     return (u16)res;
549 }
550 
551 /****************************************************************************
552 REMARKS:
553 Implements the DEC instruction and side effects.
554 ****************************************************************************/
dec_long(u32 d)555 u32 dec_long(u32 d)
556 {
557     u32 res;   /* all operands in native machine order */
558 
559     res = d - 1;
560 
561     set_szp_flags_32(res);
562     calc_borrow_chain(32, d, 1, res, 0);
563 
564     return res;
565 }
566 
567 /****************************************************************************
568 REMARKS:
569 Implements the INC instruction and side effects.
570 ****************************************************************************/
inc_byte(u8 d)571 u8 inc_byte(u8 d)
572 {
573     u32 res;   /* all operands in native machine order */
574 
575     res = d + 1;
576     set_szp_flags_8((u8)res);
577     calc_carry_chain(8, d, 1, res, 0);
578 
579     return (u8)res;
580 }
581 
582 /****************************************************************************
583 REMARKS:
584 Implements the INC instruction and side effects.
585 ****************************************************************************/
inc_word(u16 d)586 u16 inc_word(u16 d)
587 {
588     u32 res;   /* all operands in native machine order */
589 
590     res = d + 1;
591     set_szp_flags_16((u16)res);
592     calc_carry_chain(16, d, 1, res, 0);
593 
594     return (u16)res;
595 }
596 
597 /****************************************************************************
598 REMARKS:
599 Implements the INC instruction and side effects.
600 ****************************************************************************/
inc_long(u32 d)601 u32 inc_long(u32 d)
602 {
603     u32 res;   /* all operands in native machine order */
604 
605     res = d + 1;
606     set_szp_flags_32(res);
607     calc_carry_chain(32, d, 1, res, 0);
608 
609     return res;
610 }
611 
612 /****************************************************************************
613 REMARKS:
614 Implements the OR instruction and side effects.
615 ****************************************************************************/
or_byte(u8 d,u8 s)616 u8 or_byte(u8 d, u8 s)
617 {
618     u8 res;    /* all operands in native machine order */
619 
620     res = d | s;
621     no_carry_byte_side_eff(res);
622 
623     return res;
624 }
625 
626 /****************************************************************************
627 REMARKS:
628 Implements the OR instruction and side effects.
629 ****************************************************************************/
or_word(u16 d,u16 s)630 u16 or_word(u16 d, u16 s)
631 {
632     u16 res;   /* all operands in native machine order */
633 
634     res = d | s;
635     no_carry_word_side_eff(res);
636     return res;
637 }
638 
639 /****************************************************************************
640 REMARKS:
641 Implements the OR instruction and side effects.
642 ****************************************************************************/
or_long(u32 d,u32 s)643 u32 or_long(u32 d, u32 s)
644 {
645     u32 res;   /* all operands in native machine order */
646 
647     res = d | s;
648     no_carry_long_side_eff(res);
649     return res;
650 }
651 
652 /****************************************************************************
653 REMARKS:
654 Implements the OR instruction and side effects.
655 ****************************************************************************/
neg_byte(u8 s)656 u8 neg_byte(u8 s)
657 {
658     u8 res;
659 
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);
664 
665     return res;
666 }
667 
668 /****************************************************************************
669 REMARKS:
670 Implements the OR instruction and side effects.
671 ****************************************************************************/
neg_word(u16 s)672 u16 neg_word(u16 s)
673 {
674     u16 res;
675 
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);
680 
681     return res;
682 }
683 
684 /****************************************************************************
685 REMARKS:
686 Implements the OR instruction and side effects.
687 ****************************************************************************/
neg_long(u32 s)688 u32 neg_long(u32 s)
689 {
690     u32 res;
691 
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);
696 
697     return res;
698 }
699 
700 /****************************************************************************
701 REMARKS:
702 Implements the NOT instruction and side effects.
703 ****************************************************************************/
not_byte(u8 s)704 u8 not_byte(u8 s)
705 {
706     return ~s;
707 }
708 
709 /****************************************************************************
710 REMARKS:
711 Implements the NOT instruction and side effects.
712 ****************************************************************************/
not_word(u16 s)713 u16 not_word(u16 s)
714 {
715     return ~s;
716 }
717 
718 /****************************************************************************
719 REMARKS:
720 Implements the NOT instruction and side effects.
721 ****************************************************************************/
not_long(u32 s)722 u32 not_long(u32 s)
723 {
724     return ~s;
725 }
726 
727 /****************************************************************************
728 REMARKS:
729 Implements the RCL instruction and side effects.
730 ****************************************************************************/
rcl_byte(u8 d,u8 s)731 u8 rcl_byte(u8 d, u8 s)
732 {
733     unsigned int res, cnt, mask, cf;
734 
735     /* s is the rotate distance.  It varies from 0 - 8. */
736     /* have
737 
738        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
739 
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:
743 
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
747 
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:
754 
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))
760      */
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;
766 
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;
772 
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.
778          */
779         mask = (1 << (cnt - 1)) - 1;
780         res |= (d >> (9 - cnt)) & mask;
781 
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);
786         }
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);
795 
796     }
797     return (u8)res;
798 }
799 
800 /****************************************************************************
801 REMARKS:
802 Implements the RCL instruction and side effects.
803 ****************************************************************************/
rcl_word(u16 d,u8 s)804 u16 rcl_word(u16 d, u8 s)
805 {
806     unsigned int res, cnt, mask, cf;
807 
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);
816         }
817         CONDITIONAL_SET_FLAG(cf, F_CF);
818         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
819                              F_OF);
820     }
821     return (u16)res;
822 }
823 
824 /****************************************************************************
825 REMARKS:
826 Implements the RCL instruction and side effects.
827 ****************************************************************************/
rcl_long(u32 d,u8 s)828 u32 rcl_long(u32 d, u8 s)
829 {
830     u32 res, cnt, mask, cf;
831 
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);
840         }
841         CONDITIONAL_SET_FLAG(cf, F_CF);
842         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
843                              F_OF);
844     }
845     return res;
846 }
847 
848 /****************************************************************************
849 REMARKS:
850 Implements the RCR instruction and side effects.
851 ****************************************************************************/
rcr_byte(u8 d,u8 s)852 u8 rcr_byte(u8 d, u8 s)
853 {
854     u32 res, cnt;
855     u32 mask, cf, ocf = 0;
856 
857     /* rotate right through carry */
858     /*
859        s is the rotate distance.  It varies from 0 - 8.
860        d is the byte object rotated.
861 
862        have
863 
864        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
865 
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:
872 
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)
878      */
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.)
891              */
892             ocf = ACCESS_FLAG(F_CF) != 0;
893         } else
894             cf = (d >> (cnt - 1)) & 0x1;
895 
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??? */
902 
903         mask = (1 << (8 - cnt)) - 1;
904         res = (d >> cnt) & mask;
905 
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.
911          */
912         res |= (d << (9 - cnt));
913 
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);
918         }
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);
927         }
928     }
929     return (u8)res;
930 }
931 
932 /****************************************************************************
933 REMARKS:
934 Implements the RCR instruction and side effects.
935 ****************************************************************************/
rcr_word(u16 d,u8 s)936 u16 rcr_word(u16 d, u8 s)
937 {
938     u32 res, cnt;
939     u32 mask, cf, ocf = 0;
940 
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);
954         }
955         CONDITIONAL_SET_FLAG(cf, F_CF);
956         if (cnt == 1) {
957             CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
958                                  F_OF);
959         }
960     }
961     return (u16)res;
962 }
963 
964 /****************************************************************************
965 REMARKS:
966 Implements the RCR instruction and side effects.
967 ****************************************************************************/
rcr_long(u32 d,u8 s)968 u32 rcr_long(u32 d, u8 s)
969 {
970     u32 res, cnt;
971     u32 mask, cf, ocf = 0;
972 
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);
987         }
988         CONDITIONAL_SET_FLAG(cf, F_CF);
989         if (cnt == 1) {
990             CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
991                                  F_OF);
992         }
993     }
994     return res;
995 }
996 
997 /****************************************************************************
998 REMARKS:
999 Implements the ROL instruction and side effects.
1000 ****************************************************************************/
rol_byte(u8 d,u8 s)1001 u8 rol_byte(u8 d, u8 s)
1002 {
1003     unsigned int res, cnt, mask;
1004 
1005     /* rotate left */
1006     /*
1007        s is the rotate distance.  It varies from 0 - 8.
1008        d is the byte object rotated.
1009 
1010        have
1011 
1012        CF  B_7 ... B_0
1013 
1014        The new rotate is done mod 8.
1015        Much simpler than the "rcl" or "rcr" operations.
1016 
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)
1020      */
1021     res = d;
1022     if ((cnt = s % 8) != 0) {
1023         /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1024         res = (d << cnt);
1025 
1026         /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1027         mask = (1 << cnt) - 1;
1028         res |= (d >> (8 - cnt)) & mask;
1029 
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);
1042     }
1043     return (u8)res;
1044 }
1045 
1046 /****************************************************************************
1047 REMARKS:
1048 Implements the ROL instruction and side effects.
1049 ****************************************************************************/
rol_word(u16 d,u8 s)1050 u16 rol_word(u16 d, u8 s)
1051 {
1052     unsigned int res, cnt, mask;
1053 
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);
1067     }
1068     return (u16)res;
1069 }
1070 
1071 /****************************************************************************
1072 REMARKS:
1073 Implements the ROL instruction and side effects.
1074 ****************************************************************************/
rol_long(u32 d,u8 s)1075 u32 rol_long(u32 d, u8 s)
1076 {
1077     u32 res, cnt, mask;
1078 
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);
1092     }
1093     return res;
1094 }
1095 
1096 /****************************************************************************
1097 REMARKS:
1098 Implements the ROR instruction and side effects.
1099 ****************************************************************************/
ror_byte(u8 d,u8 s)1100 u8 ror_byte(u8 d, u8 s)
1101 {
1102     unsigned int res, cnt, mask;
1103 
1104     /* rotate right */
1105     /*
1106        s is the rotate distance.  It varies from 0 - 8.
1107        d is the byte object rotated.
1108 
1109        have
1110 
1111        B_7 ... B_0
1112 
1113        The rotate is done mod 8.
1114 
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)
1118      */
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));
1123 
1124         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
1125         mask = (1 << (8 - cnt)) - 1;
1126         res |= (d >> (cnt)) & mask;
1127 
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);
1138     }
1139     return (u8)res;
1140 }
1141 
1142 /****************************************************************************
1143 REMARKS:
1144 Implements the ROR instruction and side effects.
1145 ****************************************************************************/
ror_word(u16 d,u8 s)1146 u16 ror_word(u16 d, u8 s)
1147 {
1148     unsigned int res, cnt, mask;
1149 
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);
1161     }
1162     return (u16)res;
1163 }
1164 
1165 /****************************************************************************
1166 REMARKS:
1167 Implements the ROR instruction and side effects.
1168 ****************************************************************************/
ror_long(u32 d,u8 s)1169 u32 ror_long(u32 d, u8 s)
1170 {
1171     u32 res, cnt, mask;
1172 
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);
1184     }
1185     return res;
1186 }
1187 
1188 /****************************************************************************
1189 REMARKS:
1190 Implements the SHL instruction and side effects.
1191 ****************************************************************************/
shl_byte(u8 d,u8 s)1192 u8 shl_byte(u8 d, u8 s)
1193 {
1194     unsigned int cnt, res, cf;
1195 
1196     if (s < 8) {
1197         cnt = s % 8;
1198 
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;
1207         }
1208 
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);
1218         }
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);
1226     }
1227     return (u8)res;
1228 }
1229 
1230 /****************************************************************************
1231 REMARKS:
1232 Implements the SHL instruction and side effects.
1233 ****************************************************************************/
shl_word(u16 d,u8 s)1234 u16 shl_word(u16 d, u8 s)
1235 {
1236     unsigned int cnt, res, cf;
1237 
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;
1247         }
1248 
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);
1256         }
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);
1264     }
1265     return (u16)res;
1266 }
1267 
1268 /****************************************************************************
1269 REMARKS:
1270 Implements the SHL instruction and side effects.
1271 ****************************************************************************/
shl_long(u32 d,u8 s)1272 u32 shl_long(u32 d, u8 s)
1273 {
1274     unsigned int cnt, res, cf;
1275 
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;
1285         }
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);
1291         }
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);
1299     }
1300     return res;
1301 }
1302 
1303 /****************************************************************************
1304 REMARKS:
1305 Implements the SHR instruction and side effects.
1306 ****************************************************************************/
shr_byte(u8 d,u8 s)1307 u8 shr_byte(u8 d, u8 s)
1308 {
1309     unsigned int cnt, res, cf;
1310 
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;
1320         }
1321 
1322         if (cnt == 1) {
1323             CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1324         } else {
1325             CLEAR_FLAG(F_OF);
1326         }
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);
1334     }
1335     return (u8)res;
1336 }
1337 
1338 /****************************************************************************
1339 REMARKS:
1340 Implements the SHR instruction and side effects.
1341 ****************************************************************************/
shr_word(u16 d,u8 s)1342 u16 shr_word(u16 d, u8 s)
1343 {
1344     unsigned int cnt, res, cf;
1345 
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;
1355         }
1356 
1357         if (cnt == 1) {
1358             CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1359         } else {
1360             CLEAR_FLAG(F_OF);
1361         }
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);
1369     }
1370     return (u16)res;
1371 }
1372 
1373 /****************************************************************************
1374 REMARKS:
1375 Implements the SHR instruction and side effects.
1376 ****************************************************************************/
shr_long(u32 d,u8 s)1377 u32 shr_long(u32 d, u8 s)
1378 {
1379     unsigned int cnt, res, cf;
1380 
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;
1390         }
1391         if (cnt == 1) {
1392             CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1393         } else {
1394             CLEAR_FLAG(F_OF);
1395         }
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);
1403     }
1404     return res;
1405 }
1406 
1407 /****************************************************************************
1408 REMARKS:
1409 Implements the SAR instruction and side effects.
1410 ****************************************************************************/
sar_byte(u8 d,u8 s)1411 u8 sar_byte(u8 d, u8 s)
1412 {
1413     unsigned int cnt, res, cf, mask, sf;
1414 
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;
1425         }
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);
1440         }
1441     }
1442     return (u8)res;
1443 }
1444 
1445 /****************************************************************************
1446 REMARKS:
1447 Implements the SAR instruction and side effects.
1448 ****************************************************************************/
sar_word(u16 d,u8 s)1449 u16 sar_word(u16 d, u8 s)
1450 {
1451     unsigned int cnt, res, cf, mask, sf;
1452 
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;
1463         }
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);
1478         }
1479     }
1480     return (u16)res;
1481 }
1482 
1483 /****************************************************************************
1484 REMARKS:
1485 Implements the SAR instruction and side effects.
1486 ****************************************************************************/
sar_long(u32 d,u8 s)1487 u32 sar_long(u32 d, u8 s)
1488 {
1489     u32 cnt, res, cf, mask, sf;
1490 
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;
1501         }
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);
1516         }
1517     }
1518     return res;
1519 }
1520 
1521 /****************************************************************************
1522 REMARKS:
1523 Implements the SHLD instruction and side effects.
1524 ****************************************************************************/
shld_word(u16 d,u16 fill,u8 s)1525 u16 shld_word (u16 d, u16 fill, u8 s)
1526 {
1527     unsigned int cnt, res, cf;
1528 
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;
1538         }
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);
1544         }
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);
1552     }
1553     return (u16)res;
1554 }
1555 
1556 /****************************************************************************
1557 REMARKS:
1558 Implements the SHLD instruction and side effects.
1559 ****************************************************************************/
shld_long(u32 d,u32 fill,u8 s)1560 u32 shld_long (u32 d, u32 fill, u8 s)
1561 {
1562     unsigned int cnt, res, cf;
1563 
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;
1573         }
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);
1579         }
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);
1587     }
1588     return res;
1589 }
1590 
1591 /****************************************************************************
1592 REMARKS:
1593 Implements the SHRD instruction and side effects.
1594 ****************************************************************************/
shrd_word(u16 d,u16 fill,u8 s)1595 u16 shrd_word (u16 d, u16 fill, u8 s)
1596 {
1597     unsigned int cnt, res, cf;
1598 
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;
1608         }
1609 
1610         if (cnt == 1) {
1611             CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1612         } else {
1613             CLEAR_FLAG(F_OF);
1614         }
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);
1622     }
1623     return (u16)res;
1624 }
1625 
1626 /****************************************************************************
1627 REMARKS:
1628 Implements the SHRD instruction and side effects.
1629 ****************************************************************************/
shrd_long(u32 d,u32 fill,u8 s)1630 u32 shrd_long (u32 d, u32 fill, u8 s)
1631 {
1632     unsigned int cnt, res, cf;
1633 
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;
1643         }
1644         if (cnt == 1) {
1645             CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1646         } else {
1647             CLEAR_FLAG(F_OF);
1648         }
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);
1656     }
1657     return res;
1658 }
1659 
1660 /****************************************************************************
1661 REMARKS:
1662 Implements the SBB instruction and side effects.
1663 ****************************************************************************/
sbb_byte(u8 d,u8 s)1664 u8 sbb_byte(u8 d, u8 s)
1665 {
1666     u32 res;   /* all operands in native machine order */
1667     u32 bc;
1668 
1669     if (ACCESS_FLAG(F_CF))
1670         res = d - s - 1;
1671     else
1672         res = d - s;
1673     set_szp_flags_8((u8)res);
1674 
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;
1681 }
1682 
1683 /****************************************************************************
1684 REMARKS:
1685 Implements the SBB instruction and side effects.
1686 ****************************************************************************/
sbb_word(u16 d,u16 s)1687 u16 sbb_word(u16 d, u16 s)
1688 {
1689     u32 res;   /* all operands in native machine order */
1690     u32 bc;
1691 
1692     if (ACCESS_FLAG(F_CF))
1693         res = d - s - 1;
1694     else
1695         res = d - s;
1696     set_szp_flags_16((u16)res);
1697 
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;
1704 }
1705 
1706 /****************************************************************************
1707 REMARKS:
1708 Implements the SBB instruction and side effects.
1709 ****************************************************************************/
sbb_long(u32 d,u32 s)1710 u32 sbb_long(u32 d, u32 s)
1711 {
1712     u32 res;   /* all operands in native machine order */
1713     u32 bc;
1714 
1715     if (ACCESS_FLAG(F_CF))
1716         res = d - s - 1;
1717     else
1718         res = d - s;
1719 
1720     set_szp_flags_32(res);
1721 
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;
1728 }
1729 
1730 /****************************************************************************
1731 REMARKS:
1732 Implements the SUB instruction and side effects.
1733 ****************************************************************************/
sub_byte(u8 d,u8 s)1734 u8 sub_byte(u8 d, u8 s)
1735 {
1736     u32 res;   /* all operands in native machine order */
1737     u32 bc;
1738 
1739     res = d - s;
1740     set_szp_flags_8((u8)res);
1741 
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;
1748 }
1749 
1750 /****************************************************************************
1751 REMARKS:
1752 Implements the SUB instruction and side effects.
1753 ****************************************************************************/
sub_word(u16 d,u16 s)1754 u16 sub_word(u16 d, u16 s)
1755 {
1756     u32 res;   /* all operands in native machine order */
1757     u32 bc;
1758 
1759     res = d - s;
1760     set_szp_flags_16((u16)res);
1761 
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;
1768 }
1769 
1770 /****************************************************************************
1771 REMARKS:
1772 Implements the SUB instruction and side effects.
1773 ****************************************************************************/
sub_long(u32 d,u32 s)1774 u32 sub_long(u32 d, u32 s)
1775 {
1776     u32 res;   /* all operands in native machine order */
1777     u32 bc;
1778 
1779     res = d - s;
1780     set_szp_flags_32(res);
1781 
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;
1788 }
1789 
1790 /****************************************************************************
1791 REMARKS:
1792 Implements the TEST instruction and side effects.
1793 ****************************************************************************/
test_byte(u8 d,u8 s)1794 void test_byte(u8 d, u8 s)
1795 {
1796     u32 res;   /* all operands in native machine order */
1797 
1798     res = d & s;
1799 
1800     CLEAR_FLAG(F_OF);
1801     set_szp_flags_8((u8)res);
1802     /* AF == don't care */
1803     CLEAR_FLAG(F_CF);
1804 }
1805 
1806 /****************************************************************************
1807 REMARKS:
1808 Implements the TEST instruction and side effects.
1809 ****************************************************************************/
test_word(u16 d,u16 s)1810 void test_word(u16 d, u16 s)
1811 {
1812     u32 res;   /* all operands in native machine order */
1813 
1814     res = d & s;
1815 
1816     CLEAR_FLAG(F_OF);
1817     set_szp_flags_16((u16)res);
1818     /* AF == don't care */
1819     CLEAR_FLAG(F_CF);
1820 }
1821 
1822 /****************************************************************************
1823 REMARKS:
1824 Implements the TEST instruction and side effects.
1825 ****************************************************************************/
test_long(u32 d,u32 s)1826 void test_long(u32 d, u32 s)
1827 {
1828     u32 res;   /* all operands in native machine order */
1829 
1830     res = d & s;
1831 
1832     CLEAR_FLAG(F_OF);
1833     set_szp_flags_32(res);
1834     /* AF == don't care */
1835     CLEAR_FLAG(F_CF);
1836 }
1837 
1838 /****************************************************************************
1839 REMARKS:
1840 Implements the XOR instruction and side effects.
1841 ****************************************************************************/
xor_byte(u8 d,u8 s)1842 u8 xor_byte(u8 d, u8 s)
1843 {
1844     u8 res;    /* all operands in native machine order */
1845 
1846     res = d ^ s;
1847     no_carry_byte_side_eff(res);
1848     return res;
1849 }
1850 
1851 /****************************************************************************
1852 REMARKS:
1853 Implements the XOR instruction and side effects.
1854 ****************************************************************************/
xor_word(u16 d,u16 s)1855 u16 xor_word(u16 d, u16 s)
1856 {
1857     u16 res;   /* all operands in native machine order */
1858 
1859     res = d ^ s;
1860     no_carry_word_side_eff(res);
1861     return res;
1862 }
1863 
1864 /****************************************************************************
1865 REMARKS:
1866 Implements the XOR instruction and side effects.
1867 ****************************************************************************/
xor_long(u32 d,u32 s)1868 u32 xor_long(u32 d, u32 s)
1869 {
1870     u32 res;   /* all operands in native machine order */
1871 
1872     res = d ^ s;
1873     no_carry_long_side_eff(res);
1874     return res;
1875 }
1876 
1877 /****************************************************************************
1878 REMARKS:
1879 Implements the IMUL instruction and side effects.
1880 ****************************************************************************/
imul_byte(u8 s)1881 void imul_byte(u8 s)
1882 {
1883     s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1884 
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);
1893     }
1894 }
1895 
1896 /****************************************************************************
1897 REMARKS:
1898 Implements the IMUL instruction and side effects.
1899 ****************************************************************************/
imul_word(u16 s)1900 void imul_word(u16 s)
1901 {
1902     s32 res = (s16)M.x86.R_AX * (s16)s;
1903 
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);
1913     }
1914 }
1915 
1916 /****************************************************************************
1917 REMARKS:
1918 Implements the IMUL instruction and side effects.
1919 ****************************************************************************/
imul_long_direct(u32 * res_lo,u32 * res_hi,u32 d,u32 s)1920 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1921 {
1922 #ifdef  __HAS_LONG_LONG__
1923     s64 res = (s64)(s32)d * (s64)(s32)s;
1924 
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;
1931 
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);
1950         }
1951 #endif
1952 }
1953 
1954 /****************************************************************************
1955 REMARKS:
1956 Implements the IMUL instruction and side effects.
1957 ****************************************************************************/
imul_long(u32 s)1958 void imul_long(u32 s)
1959 {
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);
1968     }
1969 }
1970 
1971 /****************************************************************************
1972 REMARKS:
1973 Implements the MUL instruction and side effects.
1974 ****************************************************************************/
mul_byte(u8 s)1975 void mul_byte(u8 s)
1976 {
1977     u16 res = (u16)(M.x86.R_AL * s);
1978 
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);
1986     }
1987 }
1988 
1989 /****************************************************************************
1990 REMARKS:
1991 Implements the MUL instruction and side effects.
1992 ****************************************************************************/
mul_word(u16 s)1993 void mul_word(u16 s)
1994 {
1995     u32 res = M.x86.R_AX * s;
1996 
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);
2005     }
2006 }
2007 
2008 /****************************************************************************
2009 REMARKS:
2010 Implements the MUL instruction and side effects.
2011 ****************************************************************************/
mul_long(u32 s)2012 void mul_long(u32 s)
2013 {
2014 #ifdef  __HAS_LONG_LONG__
2015     u64 res = (u64)M.x86.R_EAX * s;
2016 
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;
2023 
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);
2041     }
2042 }
2043 
2044 /****************************************************************************
2045 REMARKS:
2046 Implements the IDIV instruction and side effects.
2047 ****************************************************************************/
idiv_byte(u8 s)2048 void idiv_byte(u8 s)
2049 {
2050     s32 dvd, div, mod;
2051 
2052     dvd = (s16)M.x86.R_AX;
2053     if (s == 0) {
2054         x86emu_intr_raise(0);
2055         return;
2056     }
2057     div = dvd / (s8)s;
2058     mod = dvd % (s8)s;
2059     if (abs(div) > 0x7f) {
2060         x86emu_intr_raise(0);
2061         return;
2062     }
2063     M.x86.R_AL = (s8) div;
2064     M.x86.R_AH = (s8) mod;
2065 }
2066 
2067 /****************************************************************************
2068 REMARKS:
2069 Implements the IDIV instruction and side effects.
2070 ****************************************************************************/
idiv_word(u16 s)2071 void idiv_word(u16 s)
2072 {
2073     s32 dvd, div, mod;
2074 
2075     dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2076     if (s == 0) {
2077         x86emu_intr_raise(0);
2078         return;
2079     }
2080     div = dvd / (s16)s;
2081     mod = dvd % (s16)s;
2082     if (abs(div) > 0x7fff) {
2083         x86emu_intr_raise(0);
2084         return;
2085     }
2086     CLEAR_FLAG(F_CF);
2087     CLEAR_FLAG(F_SF);
2088     CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2089     set_parity_flag(mod);
2090 
2091     M.x86.R_AX = (u16)div;
2092     M.x86.R_DX = (u16)mod;
2093 }
2094 
2095 /****************************************************************************
2096 REMARKS:
2097 Implements the IDIV instruction and side effects.
2098 ****************************************************************************/
idiv_long(u32 s)2099 void idiv_long(u32 s)
2100 {
2101 #ifdef  __HAS_LONG_LONG__
2102     s64 dvd, div, mod;
2103 
2104     dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2105     if (s == 0) {
2106         x86emu_intr_raise(0);
2107         return;
2108     }
2109     div = dvd / (s32)s;
2110     mod = dvd % (s32)s;
2111     if (abs(div) > 0x7fffffff) {
2112         x86emu_intr_raise(0);
2113         return;
2114     }
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;
2125 
2126     if (s == 0) {
2127         x86emu_intr_raise(0);
2128         return;
2129     }
2130     do {
2131         div <<= 1;
2132         carry = (l_dvd >= l_s) ? 0 : 1;
2133 
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;
2146         }
2147 
2148     } while (counter > -1);
2149     /* overflow */
2150     if (abs_h_dvd || (l_dvd > abs_s)) {
2151         x86emu_intr_raise(0);
2152         return;
2153     }
2154     /* sign */
2155     div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2156     mod = l_dvd;
2157 
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);
2164 
2165     M.x86.R_EAX = (u32)div;
2166     M.x86.R_EDX = (u32)mod;
2167 }
2168 
2169 /****************************************************************************
2170 REMARKS:
2171 Implements the DIV instruction and side effects.
2172 ****************************************************************************/
div_byte(u8 s)2173 void div_byte(u8 s)
2174 {
2175     u32 dvd, div, mod;
2176 
2177     dvd = M.x86.R_AX;
2178     if (s == 0) {
2179         x86emu_intr_raise(0);
2180         return;
2181     }
2182     div = dvd / (u8)s;
2183     mod = dvd % (u8)s;
2184     if (abs(div) > 0xff) {
2185         x86emu_intr_raise(0);
2186         return;
2187     }
2188     M.x86.R_AL = (u8)div;
2189     M.x86.R_AH = (u8)mod;
2190 }
2191 
2192 /****************************************************************************
2193 REMARKS:
2194 Implements the DIV instruction and side effects.
2195 ****************************************************************************/
div_word(u16 s)2196 void div_word(u16 s)
2197 {
2198     u32 dvd, div, mod;
2199 
2200     dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2201     if (s == 0) {
2202         x86emu_intr_raise(0);
2203         return;
2204     }
2205     div = dvd / (u16)s;
2206     mod = dvd % (u16)s;
2207     if (abs(div) > 0xffff) {
2208         x86emu_intr_raise(0);
2209         return;
2210     }
2211     CLEAR_FLAG(F_CF);
2212     CLEAR_FLAG(F_SF);
2213     CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2214     set_parity_flag(mod);
2215 
2216     M.x86.R_AX = (u16)div;
2217     M.x86.R_DX = (u16)mod;
2218 }
2219 
2220 /****************************************************************************
2221 REMARKS:
2222 Implements the DIV instruction and side effects.
2223 ****************************************************************************/
div_long(u32 s)2224 void div_long(u32 s)
2225 {
2226 #ifdef  __HAS_LONG_LONG__
2227     u64 dvd, div, mod;
2228 
2229     dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2230     if (s == 0) {
2231         x86emu_intr_raise(0);
2232         return;
2233     }
2234     div = dvd / (u32)s;
2235     mod = dvd % (u32)s;
2236     if (abs(div) > 0xffffffff) {
2237         x86emu_intr_raise(0);
2238         return;
2239     }
2240 #else
2241     s32 div = 0, mod;
2242     s32 h_dvd = M.x86.R_EDX;
2243     u32 l_dvd = M.x86.R_EAX;
2244 
2245     u32 h_s = s;
2246     u32 l_s = 0;
2247     int counter = 32;
2248     int carry;
2249 
2250     if (s == 0) {
2251         x86emu_intr_raise(0);
2252         return;
2253     }
2254     do {
2255         div <<= 1;
2256         carry = (l_dvd >= l_s) ? 0 : 1;
2257 
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;
2270         }
2271 
2272     } while (counter > -1);
2273     /* overflow */
2274     if (h_dvd || (l_dvd > s)) {
2275         x86emu_intr_raise(0);
2276         return;
2277     }
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);
2285 
2286     M.x86.R_EAX = (u32)div;
2287     M.x86.R_EDX = (u32)mod;
2288 }
2289 
2290 /****************************************************************************
2291 REMARKS:
2292 Implements the IN string instruction and side effects.
2293 ****************************************************************************/
2294 
single_in(int size)2295 static void single_in(int size)
2296 {
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));
2303 }
2304 
ins(int size)2305 void ins(int size)
2306 {
2307     int inc = size;
2308 
2309     if (ACCESS_FLAG(F_DF)) {
2310         inc = -size;
2311     }
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;
2320           }
2321         M.x86.R_CX = 0;
2322         if (M.x86.mode & SYSMODE_32BIT_REP) {
2323             M.x86.R_ECX = 0;
2324         }
2325         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2326     } else {
2327         single_in(size);
2328         M.x86.R_DI += inc;
2329     }
2330 }
2331 
2332 /****************************************************************************
2333 REMARKS:
2334 Implements the OUT string instruction and side effects.
2335 ****************************************************************************/
2336 
single_out(int size)2337 static void single_out(int size)
2338 {
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));
2345 }
2346 
outs(int size)2347 void outs(int size)
2348 {
2349     int inc = size;
2350 
2351     if (ACCESS_FLAG(F_DF)) {
2352         inc = -size;
2353     }
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;
2362           }
2363         M.x86.R_CX = 0;
2364         if (M.x86.mode & SYSMODE_32BIT_REP) {
2365             M.x86.R_ECX = 0;
2366         }
2367         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2368     } else {
2369         single_out(size);
2370         M.x86.R_SI += inc;
2371     }
2372 }
2373 
2374 /****************************************************************************
2375 PARAMETERS:
2376 addr    - Address to fetch word from
2377 
2378 REMARKS:
2379 Fetches a word from emulator memory using an absolute address.
2380 ****************************************************************************/
mem_access_word(int addr)2381 u16 mem_access_word(int addr)
2382 {
2383 DB( if (CHECK_MEM_ACCESS())
2384       x86emu_check_mem_access(addr);)
2385     return (*sys_rdw)(addr);
2386 }
2387 
2388 /****************************************************************************
2389 REMARKS:
2390 Pushes a word onto the stack.
2391 
2392 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2393 ****************************************************************************/
push_word(u16 w)2394 void push_word(u16 w)
2395 {
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);
2400 }
2401 
2402 /****************************************************************************
2403 REMARKS:
2404 Pushes a long onto the stack.
2405 
2406 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2407 ****************************************************************************/
push_long(u32 w)2408 void push_long(u32 w)
2409 {
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);
2414 }
2415 
2416 /****************************************************************************
2417 REMARKS:
2418 Pops a word from the stack.
2419 
2420 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2421 ****************************************************************************/
pop_word(void)2422 u16 pop_word(void)
2423 {
2424     u16 res;
2425 
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;
2431 }
2432 
2433 /****************************************************************************
2434 REMARKS:
2435 Pops a long from the stack.
2436 
2437 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2438 ****************************************************************************/
pop_long(void)2439 u32 pop_long(void)
2440 {
2441     u32 res;
2442 
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;
2448 }
2449 
2450 /****************************************************************************
2451 REMARKS:
2452 CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
2453 ****************************************************************************/
x86emu_cpuid(void)2454 void x86emu_cpuid(void)
2455 {
2456     u32 feature = M.x86.R_EAX;
2457 
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.
2463          */
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.
2473          */
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.
2480          */
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.
2487          */
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;
2493     }
2494 }
2495