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