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