1 /**************************************************************************** 2 * 3 * Realmode X86 Emulator Library 4 * 5 * Copyright (C) 1991-2004 SciTech Software, Inc. 6 * Copyright (C) David Mosberger-Tang 7 * Copyright (C) 1999 Egbert Eich 8 * 9 * ======================================================================== 10 * 11 * Permission to use, copy, modify, distribute, and sell this software and 12 * its documentation for any purpose is hereby granted without fee, 13 * provided that the above copyright notice appear in all copies and that 14 * both that copyright notice and this permission notice appear in 15 * supporting documentation, and that the name of the authors not be used 16 * in advertising or publicity pertaining to distribution of the software 17 * without specific, written prior permission. The authors makes no 18 * representations about the suitability of this software for any purpose. 19 * It is provided "as is" without express or implied warranty. 20 * 21 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27 * PERFORMANCE OF THIS SOFTWARE. 28 * 29 * ======================================================================== 30 * 31 * Language: ANSI C 32 * Environment: Any 33 * Developer: Kendall Bennett 34 * 35 * Description: This file includes subroutines which are related to 36 * instruction decoding and accessess of immediate data via IP. etc. 37 * 38 ****************************************************************************/ 39 40 #include "x86emu/x86emui.h" 41 42 #if defined(CONFIG_BIOSEMU) 43 44 /*----------------------------- Implementation ----------------------------*/ 45 46 /**************************************************************************** 47 REMARKS: 48 Handles any pending asychronous interrupts. 49 ****************************************************************************/ 50 static void x86emu_intr_handle(void) 51 { 52 u8 intno; 53 54 if (M.x86.intr & INTR_SYNCH) { 55 intno = M.x86.intno; 56 if (_X86EMU_intrTab[intno]) { 57 (*_X86EMU_intrTab[intno])(intno); 58 } else { 59 push_word((u16)M.x86.R_FLG); 60 CLEAR_FLAG(F_IF); 61 CLEAR_FLAG(F_TF); 62 push_word(M.x86.R_CS); 63 M.x86.R_CS = mem_access_word(intno * 4 + 2); 64 push_word(M.x86.R_IP); 65 M.x86.R_IP = mem_access_word(intno * 4); 66 M.x86.intr = 0; 67 } 68 } 69 } 70 71 /**************************************************************************** 72 PARAMETERS: 73 intrnum - Interrupt number to raise 74 75 REMARKS: 76 Raise the specified interrupt to be handled before the execution of the 77 next instruction. 78 ****************************************************************************/ 79 void x86emu_intr_raise( 80 u8 intrnum) 81 { 82 M.x86.intno = intrnum; 83 M.x86.intr |= INTR_SYNCH; 84 } 85 86 /**************************************************************************** 87 REMARKS: 88 Main execution loop for the emulator. We return from here when the system 89 halts, which is normally caused by a stack fault when we return from the 90 original real mode call. 91 ****************************************************************************/ 92 void X86EMU_exec(void) 93 { 94 u8 op1; 95 96 M.x86.intr = 0; 97 DB(x86emu_end_instr();) 98 99 for (;;) { 100 DB( if (CHECK_IP_FETCH()) 101 x86emu_check_ip_access();) 102 /* If debugging, save the IP and CS values. */ 103 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP); 104 INC_DECODED_INST_LEN(1); 105 if (M.x86.intr) { 106 if (M.x86.intr & INTR_HALTED) { 107 DB( if (M.x86.R_SP != 0) { 108 printk("halted\n"); 109 X86EMU_trace_regs(); 110 } 111 else { 112 if (M.x86.debug) 113 printk("Service completed successfully\n"); 114 }) 115 return; 116 } 117 if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) || 118 !ACCESS_FLAG(F_IF)) { 119 x86emu_intr_handle(); 120 } 121 } 122 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 123 (*x86emu_optab[op1])(op1); 124 if (M.x86.debug & DEBUG_EXIT) { 125 M.x86.debug &= ~DEBUG_EXIT; 126 return; 127 } 128 } 129 } 130 131 /**************************************************************************** 132 REMARKS: 133 Halts the system by setting the halted system flag. 134 ****************************************************************************/ 135 void X86EMU_halt_sys(void) 136 { 137 M.x86.intr |= INTR_HALTED; 138 } 139 140 /**************************************************************************** 141 PARAMETERS: 142 mod - Mod value from decoded byte 143 regh - Reg h value from decoded byte 144 regl - Reg l value from decoded byte 145 146 REMARKS: 147 Raise the specified interrupt to be handled before the execution of the 148 next instruction. 149 150 NOTE: Do not inline this function, as (*sys_rdb) is already inline! 151 ****************************************************************************/ 152 void fetch_decode_modrm( 153 int *mod, 154 int *regh, 155 int *regl) 156 { 157 int fetched; 158 159 DB( if (CHECK_IP_FETCH()) 160 x86emu_check_ip_access();) 161 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 162 INC_DECODED_INST_LEN(1); 163 *mod = (fetched >> 6) & 0x03; 164 *regh = (fetched >> 3) & 0x07; 165 *regl = (fetched >> 0) & 0x07; 166 } 167 168 /**************************************************************************** 169 RETURNS: 170 Immediate byte value read from instruction queue 171 172 REMARKS: 173 This function returns the immediate byte from the instruction queue, and 174 moves the instruction pointer to the next value. 175 176 NOTE: Do not inline this function, as (*sys_rdb) is already inline! 177 ****************************************************************************/ 178 u8 fetch_byte_imm(void) 179 { 180 u8 fetched; 181 182 DB( if (CHECK_IP_FETCH()) 183 x86emu_check_ip_access();) 184 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 185 INC_DECODED_INST_LEN(1); 186 return fetched; 187 } 188 189 /**************************************************************************** 190 RETURNS: 191 Immediate word value read from instruction queue 192 193 REMARKS: 194 This function returns the immediate byte from the instruction queue, and 195 moves the instruction pointer to the next value. 196 197 NOTE: Do not inline this function, as (*sys_rdw) is already inline! 198 ****************************************************************************/ 199 u16 fetch_word_imm(void) 200 { 201 u16 fetched; 202 203 DB( if (CHECK_IP_FETCH()) 204 x86emu_check_ip_access();) 205 fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); 206 M.x86.R_IP += 2; 207 INC_DECODED_INST_LEN(2); 208 return fetched; 209 } 210 211 /**************************************************************************** 212 RETURNS: 213 Immediate lone value read from instruction queue 214 215 REMARKS: 216 This function returns the immediate byte from the instruction queue, and 217 moves the instruction pointer to the next value. 218 219 NOTE: Do not inline this function, as (*sys_rdw) is already inline! 220 ****************************************************************************/ 221 u32 fetch_long_imm(void) 222 { 223 u32 fetched; 224 225 DB( if (CHECK_IP_FETCH()) 226 x86emu_check_ip_access();) 227 fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); 228 M.x86.R_IP += 4; 229 INC_DECODED_INST_LEN(4); 230 return fetched; 231 } 232 233 /**************************************************************************** 234 RETURNS: 235 Value of the default data segment 236 237 REMARKS: 238 Inline function that returns the default data segment for the current 239 instruction. 240 241 On the x86 processor, the default segment is not always DS if there is 242 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 243 addresses relative to SS (ie: on the stack). So, at the minimum, all 244 decodings of addressing modes would have to set/clear a bit describing 245 whether the access is relative to DS or SS. That is the function of the 246 cpu-state-varible M.x86.mode. There are several potential states: 247 248 repe prefix seen (handled elsewhere) 249 repne prefix seen (ditto) 250 251 cs segment override 252 ds segment override 253 es segment override 254 fs segment override 255 gs segment override 256 ss segment override 257 258 ds/ss select (in absense of override) 259 260 Each of the above 7 items are handled with a bit in the mode field. 261 ****************************************************************************/ 262 _INLINE u32 get_data_segment(void) 263 { 264 #define GET_SEGMENT(segment) 265 switch (M.x86.mode & SYSMODE_SEGMASK) { 266 case 0: /* default case: use ds register */ 267 case SYSMODE_SEGOVR_DS: 268 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 269 return M.x86.R_DS; 270 case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */ 271 return M.x86.R_SS; 272 case SYSMODE_SEGOVR_CS: 273 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 274 return M.x86.R_CS; 275 case SYSMODE_SEGOVR_ES: 276 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 277 return M.x86.R_ES; 278 case SYSMODE_SEGOVR_FS: 279 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 280 return M.x86.R_FS; 281 case SYSMODE_SEGOVR_GS: 282 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 283 return M.x86.R_GS; 284 case SYSMODE_SEGOVR_SS: 285 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 286 return M.x86.R_SS; 287 default: 288 #ifdef DEBUG 289 printk("error: should not happen: multiple overrides.\n"); 290 #endif 291 HALT_SYS(); 292 return 0; 293 } 294 } 295 296 /**************************************************************************** 297 PARAMETERS: 298 offset - Offset to load data from 299 300 RETURNS: 301 Byte value read from the absolute memory location. 302 303 NOTE: Do not inline this function as (*sys_rdX) is already inline! 304 ****************************************************************************/ 305 u8 fetch_data_byte( 306 uint offset) 307 { 308 #ifdef DEBUG 309 if (CHECK_DATA_ACCESS()) 310 x86emu_check_data_access((u16)get_data_segment(), offset); 311 #endif 312 return (*sys_rdb)((get_data_segment() << 4) + offset); 313 } 314 315 /**************************************************************************** 316 PARAMETERS: 317 offset - Offset to load data from 318 319 RETURNS: 320 Word value read from the absolute memory location. 321 322 NOTE: Do not inline this function as (*sys_rdX) is already inline! 323 ****************************************************************************/ 324 u16 fetch_data_word( 325 uint offset) 326 { 327 #ifdef DEBUG 328 if (CHECK_DATA_ACCESS()) 329 x86emu_check_data_access((u16)get_data_segment(), offset); 330 #endif 331 return (*sys_rdw)((get_data_segment() << 4) + offset); 332 } 333 334 /**************************************************************************** 335 PARAMETERS: 336 offset - Offset to load data from 337 338 RETURNS: 339 Long value read from the absolute memory location. 340 341 NOTE: Do not inline this function as (*sys_rdX) is already inline! 342 ****************************************************************************/ 343 u32 fetch_data_long( 344 uint offset) 345 { 346 #ifdef DEBUG 347 if (CHECK_DATA_ACCESS()) 348 x86emu_check_data_access((u16)get_data_segment(), offset); 349 #endif 350 return (*sys_rdl)((get_data_segment() << 4) + offset); 351 } 352 353 /**************************************************************************** 354 PARAMETERS: 355 segment - Segment to load data from 356 offset - Offset to load data from 357 358 RETURNS: 359 Byte value read from the absolute memory location. 360 361 NOTE: Do not inline this function as (*sys_rdX) is already inline! 362 ****************************************************************************/ 363 u8 fetch_data_byte_abs( 364 uint segment, 365 uint offset) 366 { 367 #ifdef DEBUG 368 if (CHECK_DATA_ACCESS()) 369 x86emu_check_data_access(segment, offset); 370 #endif 371 return (*sys_rdb)(((u32)segment << 4) + offset); 372 } 373 374 /**************************************************************************** 375 PARAMETERS: 376 segment - Segment to load data from 377 offset - Offset to load data from 378 379 RETURNS: 380 Word value read from the absolute memory location. 381 382 NOTE: Do not inline this function as (*sys_rdX) is already inline! 383 ****************************************************************************/ 384 u16 fetch_data_word_abs( 385 uint segment, 386 uint offset) 387 { 388 #ifdef DEBUG 389 if (CHECK_DATA_ACCESS()) 390 x86emu_check_data_access(segment, offset); 391 #endif 392 return (*sys_rdw)(((u32)segment << 4) + offset); 393 } 394 395 /**************************************************************************** 396 PARAMETERS: 397 segment - Segment to load data from 398 offset - Offset to load data from 399 400 RETURNS: 401 Long value read from the absolute memory location. 402 403 NOTE: Do not inline this function as (*sys_rdX) is already inline! 404 ****************************************************************************/ 405 u32 fetch_data_long_abs( 406 uint segment, 407 uint offset) 408 { 409 #ifdef DEBUG 410 if (CHECK_DATA_ACCESS()) 411 x86emu_check_data_access(segment, offset); 412 #endif 413 return (*sys_rdl)(((u32)segment << 4) + offset); 414 } 415 416 /**************************************************************************** 417 PARAMETERS: 418 offset - Offset to store data at 419 val - Value to store 420 421 REMARKS: 422 Writes a word value to an segmented memory location. The segment used is 423 the current 'default' segment, which may have been overridden. 424 425 NOTE: Do not inline this function as (*sys_wrX) is already inline! 426 ****************************************************************************/ 427 void store_data_byte( 428 uint offset, 429 u8 val) 430 { 431 #ifdef DEBUG 432 if (CHECK_DATA_ACCESS()) 433 x86emu_check_data_access((u16)get_data_segment(), offset); 434 #endif 435 (*sys_wrb)((get_data_segment() << 4) + offset, val); 436 } 437 438 /**************************************************************************** 439 PARAMETERS: 440 offset - Offset to store data at 441 val - Value to store 442 443 REMARKS: 444 Writes a word value to an segmented memory location. The segment used is 445 the current 'default' segment, which may have been overridden. 446 447 NOTE: Do not inline this function as (*sys_wrX) is already inline! 448 ****************************************************************************/ 449 void store_data_word( 450 uint offset, 451 u16 val) 452 { 453 #ifdef DEBUG 454 if (CHECK_DATA_ACCESS()) 455 x86emu_check_data_access((u16)get_data_segment(), offset); 456 #endif 457 (*sys_wrw)((get_data_segment() << 4) + offset, val); 458 } 459 460 /**************************************************************************** 461 PARAMETERS: 462 offset - Offset to store data at 463 val - Value to store 464 465 REMARKS: 466 Writes a long value to an segmented memory location. The segment used is 467 the current 'default' segment, which may have been overridden. 468 469 NOTE: Do not inline this function as (*sys_wrX) is already inline! 470 ****************************************************************************/ 471 void store_data_long( 472 uint offset, 473 u32 val) 474 { 475 #ifdef DEBUG 476 if (CHECK_DATA_ACCESS()) 477 x86emu_check_data_access((u16)get_data_segment(), offset); 478 #endif 479 (*sys_wrl)((get_data_segment() << 4) + offset, val); 480 } 481 482 /**************************************************************************** 483 PARAMETERS: 484 segment - Segment to store data at 485 offset - Offset to store data at 486 val - Value to store 487 488 REMARKS: 489 Writes a byte value to an absolute memory location. 490 491 NOTE: Do not inline this function as (*sys_wrX) is already inline! 492 ****************************************************************************/ 493 void store_data_byte_abs( 494 uint segment, 495 uint offset, 496 u8 val) 497 { 498 #ifdef DEBUG 499 if (CHECK_DATA_ACCESS()) 500 x86emu_check_data_access(segment, offset); 501 #endif 502 (*sys_wrb)(((u32)segment << 4) + offset, val); 503 } 504 505 /**************************************************************************** 506 PARAMETERS: 507 segment - Segment to store data at 508 offset - Offset to store data at 509 val - Value to store 510 511 REMARKS: 512 Writes a word value to an absolute memory location. 513 514 NOTE: Do not inline this function as (*sys_wrX) is already inline! 515 ****************************************************************************/ 516 void store_data_word_abs( 517 uint segment, 518 uint offset, 519 u16 val) 520 { 521 #ifdef DEBUG 522 if (CHECK_DATA_ACCESS()) 523 x86emu_check_data_access(segment, offset); 524 #endif 525 (*sys_wrw)(((u32)segment << 4) + offset, val); 526 } 527 528 /**************************************************************************** 529 PARAMETERS: 530 segment - Segment to store data at 531 offset - Offset to store data at 532 val - Value to store 533 534 REMARKS: 535 Writes a long value to an absolute memory location. 536 537 NOTE: Do not inline this function as (*sys_wrX) is already inline! 538 ****************************************************************************/ 539 void store_data_long_abs( 540 uint segment, 541 uint offset, 542 u32 val) 543 { 544 #ifdef DEBUG 545 if (CHECK_DATA_ACCESS()) 546 x86emu_check_data_access(segment, offset); 547 #endif 548 (*sys_wrl)(((u32)segment << 4) + offset, val); 549 } 550 551 /**************************************************************************** 552 PARAMETERS: 553 reg - Register to decode 554 555 RETURNS: 556 Pointer to the appropriate register 557 558 REMARKS: 559 Return a pointer to the register given by the R/RM field of the 560 modrm byte, for byte operands. Also enables the decoding of instructions. 561 ****************************************************************************/ 562 u8* decode_rm_byte_register( 563 int reg) 564 { 565 switch (reg) { 566 case 0: 567 DECODE_PRINTF("AL"); 568 return &M.x86.R_AL; 569 case 1: 570 DECODE_PRINTF("CL"); 571 return &M.x86.R_CL; 572 case 2: 573 DECODE_PRINTF("DL"); 574 return &M.x86.R_DL; 575 case 3: 576 DECODE_PRINTF("BL"); 577 return &M.x86.R_BL; 578 case 4: 579 DECODE_PRINTF("AH"); 580 return &M.x86.R_AH; 581 case 5: 582 DECODE_PRINTF("CH"); 583 return &M.x86.R_CH; 584 case 6: 585 DECODE_PRINTF("DH"); 586 return &M.x86.R_DH; 587 case 7: 588 DECODE_PRINTF("BH"); 589 return &M.x86.R_BH; 590 } 591 HALT_SYS(); 592 return NULL; /* NOT REACHED OR REACHED ON ERROR */ 593 } 594 595 /**************************************************************************** 596 PARAMETERS: 597 reg - Register to decode 598 599 RETURNS: 600 Pointer to the appropriate register 601 602 REMARKS: 603 Return a pointer to the register given by the R/RM field of the 604 modrm byte, for word operands. Also enables the decoding of instructions. 605 ****************************************************************************/ 606 u16* decode_rm_word_register( 607 int reg) 608 { 609 switch (reg) { 610 case 0: 611 DECODE_PRINTF("AX"); 612 return &M.x86.R_AX; 613 case 1: 614 DECODE_PRINTF("CX"); 615 return &M.x86.R_CX; 616 case 2: 617 DECODE_PRINTF("DX"); 618 return &M.x86.R_DX; 619 case 3: 620 DECODE_PRINTF("BX"); 621 return &M.x86.R_BX; 622 case 4: 623 DECODE_PRINTF("SP"); 624 return &M.x86.R_SP; 625 case 5: 626 DECODE_PRINTF("BP"); 627 return &M.x86.R_BP; 628 case 6: 629 DECODE_PRINTF("SI"); 630 return &M.x86.R_SI; 631 case 7: 632 DECODE_PRINTF("DI"); 633 return &M.x86.R_DI; 634 } 635 HALT_SYS(); 636 return NULL; /* NOTREACHED OR REACHED ON ERROR */ 637 } 638 639 /**************************************************************************** 640 PARAMETERS: 641 reg - Register to decode 642 643 RETURNS: 644 Pointer to the appropriate register 645 646 REMARKS: 647 Return a pointer to the register given by the R/RM field of the 648 modrm byte, for dword operands. Also enables the decoding of instructions. 649 ****************************************************************************/ 650 u32* decode_rm_long_register( 651 int reg) 652 { 653 switch (reg) { 654 case 0: 655 DECODE_PRINTF("EAX"); 656 return &M.x86.R_EAX; 657 case 1: 658 DECODE_PRINTF("ECX"); 659 return &M.x86.R_ECX; 660 case 2: 661 DECODE_PRINTF("EDX"); 662 return &M.x86.R_EDX; 663 case 3: 664 DECODE_PRINTF("EBX"); 665 return &M.x86.R_EBX; 666 case 4: 667 DECODE_PRINTF("ESP"); 668 return &M.x86.R_ESP; 669 case 5: 670 DECODE_PRINTF("EBP"); 671 return &M.x86.R_EBP; 672 case 6: 673 DECODE_PRINTF("ESI"); 674 return &M.x86.R_ESI; 675 case 7: 676 DECODE_PRINTF("EDI"); 677 return &M.x86.R_EDI; 678 } 679 HALT_SYS(); 680 return NULL; /* NOTREACHED OR REACHED ON ERROR */ 681 } 682 683 /**************************************************************************** 684 PARAMETERS: 685 reg - Register to decode 686 687 RETURNS: 688 Pointer to the appropriate register 689 690 REMARKS: 691 Return a pointer to the register given by the R/RM field of the 692 modrm byte, for word operands, modified from above for the weirdo 693 special case of segreg operands. Also enables the decoding of instructions. 694 ****************************************************************************/ 695 u16* decode_rm_seg_register( 696 int reg) 697 { 698 switch (reg) { 699 case 0: 700 DECODE_PRINTF("ES"); 701 return &M.x86.R_ES; 702 case 1: 703 DECODE_PRINTF("CS"); 704 return &M.x86.R_CS; 705 case 2: 706 DECODE_PRINTF("SS"); 707 return &M.x86.R_SS; 708 case 3: 709 DECODE_PRINTF("DS"); 710 return &M.x86.R_DS; 711 case 4: 712 DECODE_PRINTF("FS"); 713 return &M.x86.R_FS; 714 case 5: 715 DECODE_PRINTF("GS"); 716 return &M.x86.R_GS; 717 case 6: 718 case 7: 719 DECODE_PRINTF("ILLEGAL SEGREG"); 720 break; 721 } 722 HALT_SYS(); 723 return NULL; /* NOT REACHED OR REACHED ON ERROR */ 724 } 725 726 /**************************************************************************** 727 PARAMETERS: 728 scale - scale value of SIB byte 729 index - index value of SIB byte 730 731 RETURNS: 732 Value of scale * index 733 734 REMARKS: 735 Decodes scale/index of SIB byte and returns relevant offset part of 736 effective address. 737 ****************************************************************************/ 738 unsigned decode_sib_si( 739 int scale, 740 int index) 741 { 742 scale = 1 << scale; 743 if (scale > 1) { 744 DECODE_PRINTF2("[%d*", scale); 745 } else { 746 DECODE_PRINTF("["); 747 } 748 switch (index) { 749 case 0: 750 DECODE_PRINTF("EAX]"); 751 return M.x86.R_EAX * index; 752 case 1: 753 DECODE_PRINTF("ECX]"); 754 return M.x86.R_ECX * index; 755 case 2: 756 DECODE_PRINTF("EDX]"); 757 return M.x86.R_EDX * index; 758 case 3: 759 DECODE_PRINTF("EBX]"); 760 return M.x86.R_EBX * index; 761 case 4: 762 DECODE_PRINTF("0]"); 763 return 0; 764 case 5: 765 DECODE_PRINTF("EBP]"); 766 return M.x86.R_EBP * index; 767 case 6: 768 DECODE_PRINTF("ESI]"); 769 return M.x86.R_ESI * index; 770 case 7: 771 DECODE_PRINTF("EDI]"); 772 return M.x86.R_EDI * index; 773 } 774 HALT_SYS(); 775 return 0; /* NOT REACHED OR REACHED ON ERROR */ 776 } 777 778 /**************************************************************************** 779 PARAMETERS: 780 mod - MOD value of preceding ModR/M byte 781 782 RETURNS: 783 Offset in memory for the address decoding 784 785 REMARKS: 786 Decodes SIB addressing byte and returns calculated effective address. 787 ****************************************************************************/ 788 unsigned decode_sib_address( 789 int mod) 790 { 791 int sib = fetch_byte_imm(); 792 int ss = (sib >> 6) & 0x03; 793 int index = (sib >> 3) & 0x07; 794 int base = sib & 0x07; 795 int offset = 0; 796 int displacement; 797 798 switch (base) { 799 case 0: 800 DECODE_PRINTF("[EAX]"); 801 offset = M.x86.R_EAX; 802 break; 803 case 1: 804 DECODE_PRINTF("[ECX]"); 805 offset = M.x86.R_ECX; 806 break; 807 case 2: 808 DECODE_PRINTF("[EDX]"); 809 offset = M.x86.R_EDX; 810 break; 811 case 3: 812 DECODE_PRINTF("[EBX]"); 813 offset = M.x86.R_EBX; 814 break; 815 case 4: 816 DECODE_PRINTF("[ESP]"); 817 offset = M.x86.R_ESP; 818 break; 819 case 5: 820 switch (mod) { 821 case 0: 822 displacement = (s32)fetch_long_imm(); 823 DECODE_PRINTF2("[%d]", displacement); 824 offset = displacement; 825 break; 826 case 1: 827 displacement = (s8)fetch_byte_imm(); 828 DECODE_PRINTF2("[%d][EBP]", displacement); 829 offset = M.x86.R_EBP + displacement; 830 break; 831 case 2: 832 displacement = (s32)fetch_long_imm(); 833 DECODE_PRINTF2("[%d][EBP]", displacement); 834 offset = M.x86.R_EBP + displacement; 835 break; 836 default: 837 HALT_SYS(); 838 } 839 DECODE_PRINTF("[EAX]"); 840 offset = M.x86.R_EAX; 841 break; 842 case 6: 843 DECODE_PRINTF("[ESI]"); 844 offset = M.x86.R_ESI; 845 break; 846 case 7: 847 DECODE_PRINTF("[EDI]"); 848 offset = M.x86.R_EDI; 849 break; 850 default: 851 HALT_SYS(); 852 } 853 offset += decode_sib_si(ss, index); 854 return offset; 855 856 } 857 858 /**************************************************************************** 859 PARAMETERS: 860 rm - RM value to decode 861 862 RETURNS: 863 Offset in memory for the address decoding 864 865 REMARKS: 866 Return the offset given by mod=00 addressing. Also enables the 867 decoding of instructions. 868 869 NOTE: The code which specifies the corresponding segment (ds vs ss) 870 below in the case of [BP+..]. The assumption here is that at the 871 point that this subroutine is called, the bit corresponding to 872 SYSMODE_SEG_DS_SS will be zero. After every instruction 873 except the segment override instructions, this bit (as well 874 as any bits indicating segment overrides) will be clear. So 875 if a SS access is needed, set this bit. Otherwise, DS access 876 occurs (unless any of the segment override bits are set). 877 ****************************************************************************/ 878 unsigned decode_rm00_address( 879 int rm) 880 { 881 unsigned offset; 882 883 if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 884 /* 32-bit addressing */ 885 switch (rm) { 886 case 0: 887 DECODE_PRINTF("[EAX]"); 888 return M.x86.R_EAX; 889 case 1: 890 DECODE_PRINTF("[ECX]"); 891 return M.x86.R_ECX; 892 case 2: 893 DECODE_PRINTF("[EDX]"); 894 return M.x86.R_EDX; 895 case 3: 896 DECODE_PRINTF("[EBX]"); 897 return M.x86.R_EBX; 898 case 4: 899 return decode_sib_address(0); 900 case 5: 901 offset = fetch_long_imm(); 902 DECODE_PRINTF2("[%08x]", offset); 903 return offset; 904 case 6: 905 DECODE_PRINTF("[ESI]"); 906 return M.x86.R_ESI; 907 case 7: 908 DECODE_PRINTF("[EDI]"); 909 return M.x86.R_EDI; 910 } 911 } else { 912 /* 16-bit addressing */ 913 switch (rm) { 914 case 0: 915 DECODE_PRINTF("[BX+SI]"); 916 return (M.x86.R_BX + M.x86.R_SI) & 0xffff; 917 case 1: 918 DECODE_PRINTF("[BX+DI]"); 919 return (M.x86.R_BX + M.x86.R_DI) & 0xffff; 920 case 2: 921 DECODE_PRINTF("[BP+SI]"); 922 M.x86.mode |= SYSMODE_SEG_DS_SS; 923 return (M.x86.R_BP + M.x86.R_SI) & 0xffff; 924 case 3: 925 DECODE_PRINTF("[BP+DI]"); 926 M.x86.mode |= SYSMODE_SEG_DS_SS; 927 return (M.x86.R_BP + M.x86.R_DI) & 0xffff; 928 case 4: 929 DECODE_PRINTF("[SI]"); 930 return M.x86.R_SI; 931 case 5: 932 DECODE_PRINTF("[DI]"); 933 return M.x86.R_DI; 934 case 6: 935 offset = fetch_word_imm(); 936 DECODE_PRINTF2("[%04x]", offset); 937 return offset; 938 case 7: 939 DECODE_PRINTF("[BX]"); 940 return M.x86.R_BX; 941 } 942 } 943 HALT_SYS(); 944 return 0; 945 } 946 947 /**************************************************************************** 948 PARAMETERS: 949 rm - RM value to decode 950 951 RETURNS: 952 Offset in memory for the address decoding 953 954 REMARKS: 955 Return the offset given by mod=01 addressing. Also enables the 956 decoding of instructions. 957 ****************************************************************************/ 958 unsigned decode_rm01_address( 959 int rm) 960 { 961 int displacement; 962 963 if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 964 /* 32-bit addressing */ 965 if (rm != 4) 966 displacement = (s8)fetch_byte_imm(); 967 else 968 displacement = 0; 969 970 switch (rm) { 971 case 0: 972 DECODE_PRINTF2("%d[EAX]", displacement); 973 return M.x86.R_EAX + displacement; 974 case 1: 975 DECODE_PRINTF2("%d[ECX]", displacement); 976 return M.x86.R_ECX + displacement; 977 case 2: 978 DECODE_PRINTF2("%d[EDX]", displacement); 979 return M.x86.R_EDX + displacement; 980 case 3: 981 DECODE_PRINTF2("%d[EBX]", displacement); 982 return M.x86.R_EBX + displacement; 983 case 4: { 984 int offset = decode_sib_address(1); 985 displacement = (s8)fetch_byte_imm(); 986 DECODE_PRINTF2("[%d]", displacement); 987 return offset + displacement; 988 } 989 case 5: 990 DECODE_PRINTF2("%d[EBP]", displacement); 991 return M.x86.R_EBP + displacement; 992 case 6: 993 DECODE_PRINTF2("%d[ESI]", displacement); 994 return M.x86.R_ESI + displacement; 995 case 7: 996 DECODE_PRINTF2("%d[EDI]", displacement); 997 return M.x86.R_EDI + displacement; 998 } 999 } else { 1000 /* 16-bit addressing */ 1001 displacement = (s8)fetch_byte_imm(); 1002 switch (rm) { 1003 case 0: 1004 DECODE_PRINTF2("%d[BX+SI]", displacement); 1005 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; 1006 case 1: 1007 DECODE_PRINTF2("%d[BX+DI]", displacement); 1008 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; 1009 case 2: 1010 DECODE_PRINTF2("%d[BP+SI]", displacement); 1011 M.x86.mode |= SYSMODE_SEG_DS_SS; 1012 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; 1013 case 3: 1014 DECODE_PRINTF2("%d[BP+DI]", displacement); 1015 M.x86.mode |= SYSMODE_SEG_DS_SS; 1016 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; 1017 case 4: 1018 DECODE_PRINTF2("%d[SI]", displacement); 1019 return (M.x86.R_SI + displacement) & 0xffff; 1020 case 5: 1021 DECODE_PRINTF2("%d[DI]", displacement); 1022 return (M.x86.R_DI + displacement) & 0xffff; 1023 case 6: 1024 DECODE_PRINTF2("%d[BP]", displacement); 1025 M.x86.mode |= SYSMODE_SEG_DS_SS; 1026 return (M.x86.R_BP + displacement) & 0xffff; 1027 case 7: 1028 DECODE_PRINTF2("%d[BX]", displacement); 1029 return (M.x86.R_BX + displacement) & 0xffff; 1030 } 1031 } 1032 HALT_SYS(); 1033 return 0; /* SHOULD NOT HAPPEN */ 1034 } 1035 1036 /**************************************************************************** 1037 PARAMETERS: 1038 rm - RM value to decode 1039 1040 RETURNS: 1041 Offset in memory for the address decoding 1042 1043 REMARKS: 1044 Return the offset given by mod=10 addressing. Also enables the 1045 decoding of instructions. 1046 ****************************************************************************/ 1047 unsigned decode_rm10_address( 1048 int rm) 1049 { 1050 if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 1051 int displacement; 1052 1053 /* 32-bit addressing */ 1054 if (rm != 4) 1055 displacement = (s32)fetch_long_imm(); 1056 else 1057 displacement = 0; 1058 1059 switch (rm) { 1060 case 0: 1061 DECODE_PRINTF2("%d[EAX]", displacement); 1062 return M.x86.R_EAX + displacement; 1063 case 1: 1064 DECODE_PRINTF2("%d[ECX]", displacement); 1065 return M.x86.R_ECX + displacement; 1066 case 2: 1067 DECODE_PRINTF2("%d[EDX]", displacement); 1068 return M.x86.R_EDX + displacement; 1069 case 3: 1070 DECODE_PRINTF2("%d[EBX]", displacement); 1071 return M.x86.R_EBX + displacement; 1072 case 4: { 1073 int offset = decode_sib_address(2); 1074 displacement = (s32)fetch_long_imm(); 1075 DECODE_PRINTF2("[%d]", displacement); 1076 return offset + displacement; 1077 } 1078 case 5: 1079 DECODE_PRINTF2("%d[EBP]", displacement); 1080 return M.x86.R_EBP + displacement; 1081 case 6: 1082 DECODE_PRINTF2("%d[ESI]", displacement); 1083 return M.x86.R_ESI + displacement; 1084 case 7: 1085 DECODE_PRINTF2("%d[EDI]", displacement); 1086 return M.x86.R_EDI + displacement; 1087 } 1088 } else { 1089 int displacement = (s16)fetch_word_imm(); 1090 1091 /* 16-bit addressing */ 1092 switch (rm) { 1093 case 0: 1094 DECODE_PRINTF2("%d[BX+SI]", displacement); 1095 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; 1096 case 1: 1097 DECODE_PRINTF2("%d[BX+DI]", displacement); 1098 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; 1099 case 2: 1100 DECODE_PRINTF2("%d[BP+SI]", displacement); 1101 M.x86.mode |= SYSMODE_SEG_DS_SS; 1102 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; 1103 case 3: 1104 DECODE_PRINTF2("%d[BP+DI]", displacement); 1105 M.x86.mode |= SYSMODE_SEG_DS_SS; 1106 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; 1107 case 4: 1108 DECODE_PRINTF2("%d[SI]", displacement); 1109 return (M.x86.R_SI + displacement) & 0xffff; 1110 case 5: 1111 DECODE_PRINTF2("%d[DI]", displacement); 1112 return (M.x86.R_DI + displacement) & 0xffff; 1113 case 6: 1114 DECODE_PRINTF2("%d[BP]", displacement); 1115 M.x86.mode |= SYSMODE_SEG_DS_SS; 1116 return (M.x86.R_BP + displacement) & 0xffff; 1117 case 7: 1118 DECODE_PRINTF2("%d[BX]", displacement); 1119 return (M.x86.R_BX + displacement) & 0xffff; 1120 } 1121 } 1122 HALT_SYS(); 1123 return 0; /* SHOULD NOT HAPPEN */ 1124 } 1125 1126 /**************************************************************************** 1127 PARAMETERS: 1128 mod - modifier 1129 rm - RM value to decode 1130 1131 RETURNS: 1132 Offset in memory for the address decoding, multiplexing calls to 1133 the decode_rmXX_address functions 1134 1135 REMARKS: 1136 Return the offset given by "mod" addressing. 1137 ****************************************************************************/ 1138 1139 unsigned decode_rmXX_address(int mod, int rm) 1140 { 1141 if(mod == 0) 1142 return decode_rm00_address(rm); 1143 if(mod == 1) 1144 return decode_rm01_address(rm); 1145 return decode_rm10_address(rm); 1146 } 1147 1148 #endif 1149