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