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