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