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