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