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/**************************************************************************** 56REMARKS: 57Handles any pending asychronous interrupts. 58****************************************************************************/ 59static void 60x86emu_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/**************************************************************************** 83PARAMETERS: 84intrnum - Interrupt number to raise 85 86REMARKS: 87Raise the specified interrupt to be handled before the execution of the 88next instruction. 89****************************************************************************/ 90void 91x86emu_intr_raise(u8 intrnum) 92{ 93 M.x86.intno = intrnum; 94 M.x86.intr |= INTR_SYNCH; 95} 96 97/**************************************************************************** 98REMARKS: 99Main execution loop for the emulator. We return from here when the system 100halts, which is normally caused by a stack fault when we return from the 101original real mode call. 102****************************************************************************/ 103void 104X86EMU_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/**************************************************************************** 144REMARKS: 145Halts the system by setting the halted system flag. 146****************************************************************************/ 147void 148X86EMU_halt_sys(void) 149{ 150 M.x86.intr |= INTR_HALTED; 151} 152 153/**************************************************************************** 154PARAMETERS: 155mod - Mod value from decoded byte 156regh - Reg h value from decoded byte 157regl - Reg l value from decoded byte 158 159REMARKS: 160Raise the specified interrupt to be handled before the execution of the 161next instruction. 162 163NOTE: Do not inline this function, as (*sys_rdb) is already inline! 164****************************************************************************/ 165void 166fetch_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/**************************************************************************** 180RETURNS: 181Immediate byte value read from instruction queue 182 183REMARKS: 184This function returns the immediate byte from the instruction queue, and 185moves the instruction pointer to the next value. 186 187NOTE: Do not inline this function, as (*sys_rdb) is already inline! 188****************************************************************************/ 189u8 190fetch_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/**************************************************************************** 202RETURNS: 203Immediate word value read from instruction queue 204 205REMARKS: 206This function returns the immediate byte from the instruction queue, and 207moves the instruction pointer to the next value. 208 209NOTE: Do not inline this function, as (*sys_rdw) is already inline! 210****************************************************************************/ 211u16 212fetch_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/**************************************************************************** 225RETURNS: 226Immediate lone value read from instruction queue 227 228REMARKS: 229This function returns the immediate byte from the instruction queue, and 230moves the instruction pointer to the next value. 231 232NOTE: Do not inline this function, as (*sys_rdw) is already inline! 233****************************************************************************/ 234u32 235fetch_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/**************************************************************************** 248RETURNS: 249Value of the default data segment 250 251REMARKS: 252Inline function that returns the default data segment for the current 253instruction. 254 255On the x86 processor, the default segment is not always DS if there is 256no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 257addresses relative to SS (ie: on the stack). So, at the minimum, all 258decodings of addressing modes would have to set/clear a bit describing 259whether the access is relative to DS or SS. That is the function of the 260cpu-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 274Each of the above 7 items are handled with a bit in the mode field. 275****************************************************************************/ 276_INLINE u32 277get_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/**************************************************************************** 312PARAMETERS: 313offset - Offset to load data from 314 315RETURNS: 316Byte value read from the absolute memory location. 317 318NOTE: Do not inline this function as (*sys_rdX) is already inline! 319****************************************************************************/ 320u8 321fetch_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/**************************************************************************** 331PARAMETERS: 332offset - Offset to load data from 333 334RETURNS: 335Word value read from the absolute memory location. 336 337NOTE: Do not inline this function as (*sys_rdX) is already inline! 338****************************************************************************/ 339u16 340fetch_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/**************************************************************************** 350PARAMETERS: 351offset - Offset to load data from 352 353RETURNS: 354Long value read from the absolute memory location. 355 356NOTE: Do not inline this function as (*sys_rdX) is already inline! 357****************************************************************************/ 358u32 359fetch_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/**************************************************************************** 369PARAMETERS: 370segment - Segment to load data from 371offset - Offset to load data from 372 373RETURNS: 374Byte value read from the absolute memory location. 375 376NOTE: Do not inline this function as (*sys_rdX) is already inline! 377****************************************************************************/ 378u8 379fetch_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/**************************************************************************** 389PARAMETERS: 390segment - Segment to load data from 391offset - Offset to load data from 392 393RETURNS: 394Word value read from the absolute memory location. 395 396NOTE: Do not inline this function as (*sys_rdX) is already inline! 397****************************************************************************/ 398u16 399fetch_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/**************************************************************************** 409PARAMETERS: 410segment - Segment to load data from 411offset - Offset to load data from 412 413RETURNS: 414Long value read from the absolute memory location. 415 416NOTE: Do not inline this function as (*sys_rdX) is already inline! 417****************************************************************************/ 418u32 419fetch_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/**************************************************************************** 429PARAMETERS: 430offset - Offset to store data at 431val - Value to store 432 433REMARKS: 434Writes a word value to an segmented memory location. The segment used is 435the current 'default' segment, which may have been overridden. 436 437NOTE: Do not inline this function as (*sys_wrX) is already inline! 438****************************************************************************/ 439void 440store_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/**************************************************************************** 450PARAMETERS: 451offset - Offset to store data at 452val - Value to store 453 454REMARKS: 455Writes a word value to an segmented memory location. The segment used is 456the current 'default' segment, which may have been overridden. 457 458NOTE: Do not inline this function as (*sys_wrX) is already inline! 459****************************************************************************/ 460void 461store_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/**************************************************************************** 471PARAMETERS: 472offset - Offset to store data at 473val - Value to store 474 475REMARKS: 476Writes a long value to an segmented memory location. The segment used is 477the current 'default' segment, which may have been overridden. 478 479NOTE: Do not inline this function as (*sys_wrX) is already inline! 480****************************************************************************/ 481void 482store_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/**************************************************************************** 492PARAMETERS: 493segment - Segment to store data at 494offset - Offset to store data at 495val - Value to store 496 497REMARKS: 498Writes a byte value to an absolute memory location. 499 500NOTE: Do not inline this function as (*sys_wrX) is already inline! 501****************************************************************************/ 502void 503store_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/**************************************************************************** 513PARAMETERS: 514segment - Segment to store data at 515offset - Offset to store data at 516val - Value to store 517 518REMARKS: 519Writes a word value to an absolute memory location. 520 521NOTE: Do not inline this function as (*sys_wrX) is already inline! 522****************************************************************************/ 523void 524store_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/**************************************************************************** 534PARAMETERS: 535segment - Segment to store data at 536offset - Offset to store data at 537val - Value to store 538 539REMARKS: 540Writes a long value to an absolute memory location. 541 542NOTE: Do not inline this function as (*sys_wrX) is already inline! 543****************************************************************************/ 544void 545store_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/**************************************************************************** 555PARAMETERS: 556reg - Register to decode 557 558RETURNS: 559Pointer to the appropriate register 560 561REMARKS: 562Return a pointer to the register given by the R/RM field of the 563modrm byte, for byte operands. Also enables the decoding of instructions. 564****************************************************************************/ 565u8 * 566decode_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/**************************************************************************** 599PARAMETERS: 600reg - Register to decode 601 602RETURNS: 603Pointer to the appropriate register 604 605REMARKS: 606Return a pointer to the register given by the R/RM field of the 607modrm byte, for word operands. Also enables the decoding of instructions. 608****************************************************************************/ 609u16 * 610decode_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/**************************************************************************** 643PARAMETERS: 644reg - Register to decode 645 646RETURNS: 647Pointer to the appropriate register 648 649REMARKS: 650Return a pointer to the register given by the R/RM field of the 651modrm byte, for dword operands. Also enables the decoding of instructions. 652****************************************************************************/ 653u32 * 654decode_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/**************************************************************************** 687PARAMETERS: 688reg - Register to decode 689 690RETURNS: 691Pointer to the appropriate register 692 693REMARKS: 694Return a pointer to the register given by the R/RM field of the 695modrm byte, for word operands, modified from above for the weirdo 696special case of segreg operands. Also enables the decoding of instructions. 697****************************************************************************/ 698u16 * 699decode_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 */ 733u32 734decode_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/**************************************************************************** 826PARAMETERS: 827rm - RM value to decode 828 829RETURNS: 830Offset in memory for the address decoding 831 832REMARKS: 833Return the offset given by mod=00 addressing. Also enables the 834decoding of instructions. 835 836NOTE: 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****************************************************************************/ 845u32 846decode_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/**************************************************************************** 919PARAMETERS: 920rm - RM value to decode 921 922RETURNS: 923Offset in memory for the address decoding 924 925REMARKS: 926Return the offset given by mod=01 addressing. Also enables the 927decoding of instructions. 928****************************************************************************/ 929u32 930decode_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/**************************************************************************** 1008PARAMETERS: 1009rm - RM value to decode 1010 1011RETURNS: 1012Offset in memory for the address decoding 1013 1014REMARKS: 1015Return the offset given by mod=10 addressing. Also enables the 1016decoding of instructions. 1017****************************************************************************/ 1018u32 1019decode_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} 1103