xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

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 }