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