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