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