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