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