105b261ecSmrg/****************************************************************************
205b261ecSmrg*
305b261ecSmrg*						Realmode X86 Emulator Library
405b261ecSmrg*
505b261ecSmrg*            	Copyright (C) 1996-1999 SciTech Software, Inc.
605b261ecSmrg* 				     Copyright (C) David Mosberger-Tang
705b261ecSmrg* 					   Copyright (C) 1999 Egbert Eich
805b261ecSmrg*
905b261ecSmrg*  ========================================================================
1005b261ecSmrg*
1105b261ecSmrg*  Permission to use, copy, modify, distribute, and sell this software and
1205b261ecSmrg*  its documentation for any purpose is hereby granted without fee,
1305b261ecSmrg*  provided that the above copyright notice appear in all copies and that
1405b261ecSmrg*  both that copyright notice and this permission notice appear in
1505b261ecSmrg*  supporting documentation, and that the name of the authors not be used
1605b261ecSmrg*  in advertising or publicity pertaining to distribution of the software
1705b261ecSmrg*  without specific, written prior permission.  The authors makes no
1805b261ecSmrg*  representations about the suitability of this software for any purpose.
1905b261ecSmrg*  It is provided "as is" without express or implied warranty.
2005b261ecSmrg*
2105b261ecSmrg*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2205b261ecSmrg*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2305b261ecSmrg*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2405b261ecSmrg*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
2505b261ecSmrg*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2605b261ecSmrg*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2705b261ecSmrg*  PERFORMANCE OF THIS SOFTWARE.
2805b261ecSmrg*
2905b261ecSmrg*  ========================================================================
3005b261ecSmrg*
3105b261ecSmrg* Language:		ANSI C
3205b261ecSmrg* Environment:	Any
3305b261ecSmrg* Developer:    Kendall Bennett
3405b261ecSmrg*
3505b261ecSmrg* Description:  This file includes subroutines which are related to
3605b261ecSmrg*				instruction decoding and accessess of immediate data via IP.  etc.
3705b261ecSmrg*
3805b261ecSmrg****************************************************************************/
3905b261ecSmrg
4005b261ecSmrg#include <stdlib.h>
4135c4bbdfSmrg
4235c4bbdfSmrg#if defined(__sun) && defined(CS) /* avoid conflicts with Solaris sys/regset.h */
4335c4bbdfSmrg# undef CS
4435c4bbdfSmrg# undef DS
4535c4bbdfSmrg# undef SS
4635c4bbdfSmrg# undef ES
4735c4bbdfSmrg# undef FS
4835c4bbdfSmrg# undef GS
4935c4bbdfSmrg#endif
5035c4bbdfSmrg
5105b261ecSmrg#include "x86emu/x86emui.h"
5205b261ecSmrg
5305b261ecSmrg/*----------------------------- Implementation ----------------------------*/
5405b261ecSmrg
5505b261ecSmrg/****************************************************************************
5605b261ecSmrgREMARKS:
5705b261ecSmrgHandles any pending asychronous interrupts.
5805b261ecSmrg****************************************************************************/
5935c4bbdfSmrgstatic void
6035c4bbdfSmrgx86emu_intr_handle(void)
6105b261ecSmrg{
6235c4bbdfSmrg    u8 intno;
6335c4bbdfSmrg
6435c4bbdfSmrg    if (M.x86.intr & INTR_SYNCH) {
6535c4bbdfSmrg        intno = M.x86.intno;
6635c4bbdfSmrg        if (_X86EMU_intrTab[intno]) {
6735c4bbdfSmrg            (*_X86EMU_intrTab[intno]) (intno);
6835c4bbdfSmrg        }
6935c4bbdfSmrg        else {
7035c4bbdfSmrg            push_word((u16) M.x86.R_FLG);
7135c4bbdfSmrg            CLEAR_FLAG(F_IF);
7235c4bbdfSmrg            CLEAR_FLAG(F_TF);
7335c4bbdfSmrg            push_word(M.x86.R_CS);
7435c4bbdfSmrg            M.x86.R_CS = mem_access_word(intno * 4 + 2);
7535c4bbdfSmrg            push_word(M.x86.R_IP);
7635c4bbdfSmrg            M.x86.R_IP = mem_access_word(intno * 4);
7735c4bbdfSmrg            M.x86.intr = 0;
7835c4bbdfSmrg        }
7935c4bbdfSmrg    }
8005b261ecSmrg}
8105b261ecSmrg
8205b261ecSmrg/****************************************************************************
8305b261ecSmrgPARAMETERS:
8405b261ecSmrgintrnum - Interrupt number to raise
8505b261ecSmrg
8605b261ecSmrgREMARKS:
8705b261ecSmrgRaise the specified interrupt to be handled before the execution of the
8805b261ecSmrgnext instruction.
8905b261ecSmrg****************************************************************************/
9035c4bbdfSmrgvoid
9135c4bbdfSmrgx86emu_intr_raise(u8 intrnum)
9205b261ecSmrg{
9335c4bbdfSmrg    M.x86.intno = intrnum;
9435c4bbdfSmrg    M.x86.intr |= INTR_SYNCH;
9505b261ecSmrg}
9605b261ecSmrg
9705b261ecSmrg/****************************************************************************
9805b261ecSmrgREMARKS:
9905b261ecSmrgMain execution loop for the emulator. We return from here when the system
10005b261ecSmrghalts, which is normally caused by a stack fault when we return from the
10105b261ecSmrgoriginal real mode call.
10205b261ecSmrg****************************************************************************/
10335c4bbdfSmrgvoid
10435c4bbdfSmrgX86EMU_exec(void)
10505b261ecSmrg{
10635c4bbdfSmrg    u8 op1;
10735c4bbdfSmrg
10835c4bbdfSmrg    M.x86.intr = 0;
10935c4bbdfSmrg    DB(x86emu_end_instr();
11035c4bbdfSmrg        )
11135c4bbdfSmrg
11235c4bbdfSmrg        for (;;) {
11335c4bbdfSmrg        DB(if (CHECK_IP_FETCH())
11435c4bbdfSmrg           x86emu_check_ip_access();)
11535c4bbdfSmrg            /* If debugging, save the IP and CS values. */
11635c4bbdfSmrg            SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
11735c4bbdfSmrg        INC_DECODED_INST_LEN(1);
11835c4bbdfSmrg        if (M.x86.intr) {
11935c4bbdfSmrg            if (M.x86.intr & INTR_HALTED) {
12035c4bbdfSmrg                DB(if (M.x86.R_SP != 0) {
12135c4bbdfSmrg                   printk("halted\n"); X86EMU_trace_regs();}
12235c4bbdfSmrg                   else {
12335c4bbdfSmrg                   if (M.x86.debug)
12435c4bbdfSmrg                   printk("Service completed successfully\n");}
12535c4bbdfSmrg                )
12635c4bbdfSmrg                    return;
12705b261ecSmrg            }
12835c4bbdfSmrg            if (((M.x86.intr & INTR_SYNCH) &&
12935c4bbdfSmrg                 (M.x86.intno == 0 || M.x86.intno == 2)) ||
13035c4bbdfSmrg                !ACCESS_FLAG(F_IF)) {
13135c4bbdfSmrg                x86emu_intr_handle();
13235c4bbdfSmrg            }
13335c4bbdfSmrg        }
13435c4bbdfSmrg        op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
13535c4bbdfSmrg        (*x86emu_optab[op1]) (op1);
13605b261ecSmrg        if (M.x86.debug & DEBUG_EXIT) {
13705b261ecSmrg            M.x86.debug &= ~DEBUG_EXIT;
13805b261ecSmrg            return;
13905b261ecSmrg        }
14005b261ecSmrg    }
14105b261ecSmrg}
14205b261ecSmrg
14305b261ecSmrg/****************************************************************************
14405b261ecSmrgREMARKS:
14505b261ecSmrgHalts the system by setting the halted system flag.
14605b261ecSmrg****************************************************************************/
14735c4bbdfSmrgvoid
14835c4bbdfSmrgX86EMU_halt_sys(void)
14905b261ecSmrg{
15035c4bbdfSmrg    M.x86.intr |= INTR_HALTED;
15105b261ecSmrg}
15205b261ecSmrg
15305b261ecSmrg/****************************************************************************
15405b261ecSmrgPARAMETERS:
15505b261ecSmrgmod		- Mod value from decoded byte
15605b261ecSmrgregh	- Reg h value from decoded byte
15705b261ecSmrgregl	- Reg l value from decoded byte
15805b261ecSmrg
15905b261ecSmrgREMARKS:
16005b261ecSmrgRaise the specified interrupt to be handled before the execution of the
16105b261ecSmrgnext instruction.
16205b261ecSmrg
16305b261ecSmrgNOTE: Do not inline this function, as (*sys_rdb) is already inline!
16405b261ecSmrg****************************************************************************/
16535c4bbdfSmrgvoid
16635c4bbdfSmrgfetch_decode_modrm(int *mod, int *regh, int *regl)
16705b261ecSmrg{
16835c4bbdfSmrg    int fetched;
16935c4bbdfSmrg
17035c4bbdfSmrg    DB(if (CHECK_IP_FETCH())
17135c4bbdfSmrg       x86emu_check_ip_access();)
17235c4bbdfSmrg        fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
17335c4bbdfSmrg    INC_DECODED_INST_LEN(1);
17435c4bbdfSmrg    *mod = (fetched >> 6) & 0x03;
17535c4bbdfSmrg    *regh = (fetched >> 3) & 0x07;
17605b261ecSmrg    *regl = (fetched >> 0) & 0x07;
17705b261ecSmrg}
17805b261ecSmrg
17905b261ecSmrg/****************************************************************************
18005b261ecSmrgRETURNS:
18105b261ecSmrgImmediate byte value read from instruction queue
18205b261ecSmrg
18305b261ecSmrgREMARKS:
18405b261ecSmrgThis function returns the immediate byte from the instruction queue, and
18505b261ecSmrgmoves the instruction pointer to the next value.
18605b261ecSmrg
18705b261ecSmrgNOTE: Do not inline this function, as (*sys_rdb) is already inline!
18805b261ecSmrg****************************************************************************/
18935c4bbdfSmrgu8
19035c4bbdfSmrgfetch_byte_imm(void)
19105b261ecSmrg{
19235c4bbdfSmrg    u8 fetched;
19305b261ecSmrg
19435c4bbdfSmrg    DB(if (CHECK_IP_FETCH())
19535c4bbdfSmrg       x86emu_check_ip_access();)
19635c4bbdfSmrg        fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
19735c4bbdfSmrg    INC_DECODED_INST_LEN(1);
19835c4bbdfSmrg    return fetched;
19905b261ecSmrg}
20005b261ecSmrg
20105b261ecSmrg/****************************************************************************
20205b261ecSmrgRETURNS:
20305b261ecSmrgImmediate word value read from instruction queue
20405b261ecSmrg
20505b261ecSmrgREMARKS:
20605b261ecSmrgThis function returns the immediate byte from the instruction queue, and
20705b261ecSmrgmoves the instruction pointer to the next value.
20805b261ecSmrg
20905b261ecSmrgNOTE: Do not inline this function, as (*sys_rdw) is already inline!
21005b261ecSmrg****************************************************************************/
21135c4bbdfSmrgu16
21235c4bbdfSmrgfetch_word_imm(void)
21305b261ecSmrg{
21435c4bbdfSmrg    u16 fetched;
21535c4bbdfSmrg
21635c4bbdfSmrg    DB(if (CHECK_IP_FETCH())
21735c4bbdfSmrg       x86emu_check_ip_access();)
21835c4bbdfSmrg        fetched = (*sys_rdw) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP));
21935c4bbdfSmrg    M.x86.R_IP += 2;
22035c4bbdfSmrg    INC_DECODED_INST_LEN(2);
22135c4bbdfSmrg    return fetched;
22205b261ecSmrg}
22305b261ecSmrg
22405b261ecSmrg/****************************************************************************
22505b261ecSmrgRETURNS:
22605b261ecSmrgImmediate lone value read from instruction queue
22705b261ecSmrg
22805b261ecSmrgREMARKS:
22905b261ecSmrgThis function returns the immediate byte from the instruction queue, and
23005b261ecSmrgmoves the instruction pointer to the next value.
23105b261ecSmrg
23205b261ecSmrgNOTE: Do not inline this function, as (*sys_rdw) is already inline!
23305b261ecSmrg****************************************************************************/
23435c4bbdfSmrgu32
23535c4bbdfSmrgfetch_long_imm(void)
23605b261ecSmrg{
23735c4bbdfSmrg    u32 fetched;
23835c4bbdfSmrg
23935c4bbdfSmrg    DB(if (CHECK_IP_FETCH())
24035c4bbdfSmrg       x86emu_check_ip_access();)
24135c4bbdfSmrg        fetched = (*sys_rdl) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP));
24235c4bbdfSmrg    M.x86.R_IP += 4;
24335c4bbdfSmrg    INC_DECODED_INST_LEN(4);
24435c4bbdfSmrg    return fetched;
24505b261ecSmrg}
24605b261ecSmrg
24705b261ecSmrg/****************************************************************************
24805b261ecSmrgRETURNS:
24905b261ecSmrgValue of the default data segment
25005b261ecSmrg
25105b261ecSmrgREMARKS:
25205b261ecSmrgInline function that returns the default data segment for the current
25305b261ecSmrginstruction.
25405b261ecSmrg
25505b261ecSmrgOn the x86 processor, the default segment is not always DS if there is
25605b261ecSmrgno segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
25705b261ecSmrgaddresses relative to SS (ie: on the stack). So, at the minimum, all
25805b261ecSmrgdecodings of addressing modes would have to set/clear a bit describing
25905b261ecSmrgwhether the access is relative to DS or SS.  That is the function of the
26005b261ecSmrgcpu-state-varible M.x86.mode. There are several potential states:
26105b261ecSmrg
26205b261ecSmrg	repe prefix seen  (handled elsewhere)
26305b261ecSmrg	repne prefix seen  (ditto)
26405b261ecSmrg
26505b261ecSmrg	cs segment override
26605b261ecSmrg	ds segment override
26705b261ecSmrg	es segment override
26805b261ecSmrg	fs segment override
26905b261ecSmrg	gs segment override
27005b261ecSmrg	ss segment override
27105b261ecSmrg
272ed6184dfSmrg	ds/ss select (in absence of override)
27305b261ecSmrg
27405b261ecSmrgEach of the above 7 items are handled with a bit in the mode field.
27505b261ecSmrg****************************************************************************/
27635c4bbdfSmrg_INLINE u32
27735c4bbdfSmrgget_data_segment(void)
27805b261ecSmrg{
27905b261ecSmrg#define	GET_SEGMENT(segment)
28035c4bbdfSmrg    switch (M.x86.mode & SYSMODE_SEGMASK) {
28135c4bbdfSmrg    case 0:                    /* default case: use ds register */
28235c4bbdfSmrg    case SYSMODE_SEGOVR_DS:
28335c4bbdfSmrg    case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
28435c4bbdfSmrg        return M.x86.R_DS;
28535c4bbdfSmrg    case SYSMODE_SEG_DS_SS:    /* non-overridden, use ss register */
28635c4bbdfSmrg        return M.x86.R_SS;
28735c4bbdfSmrg    case SYSMODE_SEGOVR_CS:
28835c4bbdfSmrg    case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
28935c4bbdfSmrg        return M.x86.R_CS;
29035c4bbdfSmrg    case SYSMODE_SEGOVR_ES:
29135c4bbdfSmrg    case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
29235c4bbdfSmrg        return M.x86.R_ES;
29335c4bbdfSmrg    case SYSMODE_SEGOVR_FS:
29435c4bbdfSmrg    case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
29535c4bbdfSmrg        return M.x86.R_FS;
29635c4bbdfSmrg    case SYSMODE_SEGOVR_GS:
29735c4bbdfSmrg    case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
29835c4bbdfSmrg        return M.x86.R_GS;
29935c4bbdfSmrg    case SYSMODE_SEGOVR_SS:
30035c4bbdfSmrg    case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
30135c4bbdfSmrg        return M.x86.R_SS;
30235c4bbdfSmrg    default:
30305b261ecSmrg#ifdef	DEBUG
30435c4bbdfSmrg        printk("error: should not happen:  multiple overrides.\n");
30505b261ecSmrg#endif
30635c4bbdfSmrg        HALT_SYS();
30735c4bbdfSmrg        return 0;
30835c4bbdfSmrg    }
30905b261ecSmrg}
31005b261ecSmrg
31105b261ecSmrg/****************************************************************************
31205b261ecSmrgPARAMETERS:
31305b261ecSmrgoffset	- Offset to load data from
31405b261ecSmrg
31505b261ecSmrgRETURNS:
31605b261ecSmrgByte value read from the absolute memory location.
31705b261ecSmrg
31805b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline!
31905b261ecSmrg****************************************************************************/
32035c4bbdfSmrgu8
32135c4bbdfSmrgfetch_data_byte(uint offset)
32205b261ecSmrg{
32305b261ecSmrg#ifdef DEBUG
32435c4bbdfSmrg    if (CHECK_DATA_ACCESS())
32535c4bbdfSmrg        x86emu_check_data_access((u16) get_data_segment(), offset);
32605b261ecSmrg#endif
32735c4bbdfSmrg    return (*sys_rdb) ((get_data_segment() << 4) + offset);
32805b261ecSmrg}
32905b261ecSmrg
33005b261ecSmrg/****************************************************************************
33105b261ecSmrgPARAMETERS:
33205b261ecSmrgoffset	- Offset to load data from
33305b261ecSmrg
33405b261ecSmrgRETURNS:
33505b261ecSmrgWord value read from the absolute memory location.
33605b261ecSmrg
33705b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline!
33805b261ecSmrg****************************************************************************/
33935c4bbdfSmrgu16
34035c4bbdfSmrgfetch_data_word(uint offset)
34105b261ecSmrg{
34205b261ecSmrg#ifdef DEBUG
34335c4bbdfSmrg    if (CHECK_DATA_ACCESS())
34435c4bbdfSmrg        x86emu_check_data_access((u16) get_data_segment(), offset);
34505b261ecSmrg#endif
34635c4bbdfSmrg    return (*sys_rdw) ((get_data_segment() << 4) + offset);
34705b261ecSmrg}
34805b261ecSmrg
34905b261ecSmrg/****************************************************************************
35005b261ecSmrgPARAMETERS:
35105b261ecSmrgoffset	- Offset to load data from
35205b261ecSmrg
35305b261ecSmrgRETURNS:
35405b261ecSmrgLong value read from the absolute memory location.
35505b261ecSmrg
35605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline!
35705b261ecSmrg****************************************************************************/
35835c4bbdfSmrgu32
35935c4bbdfSmrgfetch_data_long(uint offset)
36005b261ecSmrg{
36105b261ecSmrg#ifdef DEBUG
36235c4bbdfSmrg    if (CHECK_DATA_ACCESS())
36335c4bbdfSmrg        x86emu_check_data_access((u16) get_data_segment(), offset);
36405b261ecSmrg#endif
36535c4bbdfSmrg    return (*sys_rdl) ((get_data_segment() << 4) + offset);
36605b261ecSmrg}
36705b261ecSmrg
36805b261ecSmrg/****************************************************************************
36905b261ecSmrgPARAMETERS:
37005b261ecSmrgsegment	- Segment to load data from
37105b261ecSmrgoffset	- Offset to load data from
37205b261ecSmrg
37305b261ecSmrgRETURNS:
37405b261ecSmrgByte value read from the absolute memory location.
37505b261ecSmrg
37605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline!
37705b261ecSmrg****************************************************************************/
37835c4bbdfSmrgu8
37935c4bbdfSmrgfetch_data_byte_abs(uint segment, uint offset)
38005b261ecSmrg{
38105b261ecSmrg#ifdef DEBUG
38235c4bbdfSmrg    if (CHECK_DATA_ACCESS())
38335c4bbdfSmrg        x86emu_check_data_access(segment, offset);
38405b261ecSmrg#endif
38535c4bbdfSmrg    return (*sys_rdb) (((u32) segment << 4) + offset);
38605b261ecSmrg}
38705b261ecSmrg
38805b261ecSmrg/****************************************************************************
38905b261ecSmrgPARAMETERS:
39005b261ecSmrgsegment	- Segment to load data from
39105b261ecSmrgoffset	- Offset to load data from
39205b261ecSmrg
39305b261ecSmrgRETURNS:
39405b261ecSmrgWord value read from the absolute memory location.
39505b261ecSmrg
39605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline!
39705b261ecSmrg****************************************************************************/
39835c4bbdfSmrgu16
39935c4bbdfSmrgfetch_data_word_abs(uint segment, uint offset)
40005b261ecSmrg{
40105b261ecSmrg#ifdef DEBUG
40235c4bbdfSmrg    if (CHECK_DATA_ACCESS())
40335c4bbdfSmrg        x86emu_check_data_access(segment, offset);
40405b261ecSmrg#endif
40535c4bbdfSmrg    return (*sys_rdw) (((u32) segment << 4) + offset);
40605b261ecSmrg}
40705b261ecSmrg
40805b261ecSmrg/****************************************************************************
40905b261ecSmrgPARAMETERS:
41005b261ecSmrgsegment	- Segment to load data from
41105b261ecSmrgoffset	- Offset to load data from
41205b261ecSmrg
41305b261ecSmrgRETURNS:
41405b261ecSmrgLong value read from the absolute memory location.
41505b261ecSmrg
41605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline!
41705b261ecSmrg****************************************************************************/
41835c4bbdfSmrgu32
41935c4bbdfSmrgfetch_data_long_abs(uint segment, uint offset)
42005b261ecSmrg{
42105b261ecSmrg#ifdef DEBUG
42235c4bbdfSmrg    if (CHECK_DATA_ACCESS())
42335c4bbdfSmrg        x86emu_check_data_access(segment, offset);
42405b261ecSmrg#endif
42535c4bbdfSmrg    return (*sys_rdl) (((u32) segment << 4) + offset);
42605b261ecSmrg}
42705b261ecSmrg
42805b261ecSmrg/****************************************************************************
42905b261ecSmrgPARAMETERS:
43005b261ecSmrgoffset	- Offset to store data at
43105b261ecSmrgval		- Value to store
43205b261ecSmrg
43305b261ecSmrgREMARKS:
43405b261ecSmrgWrites a word value to an segmented memory location. The segment used is
43505b261ecSmrgthe current 'default' segment, which may have been overridden.
43605b261ecSmrg
43705b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline!
43805b261ecSmrg****************************************************************************/
43935c4bbdfSmrgvoid
44035c4bbdfSmrgstore_data_byte(uint offset, u8 val)
44105b261ecSmrg{
44205b261ecSmrg#ifdef DEBUG
44335c4bbdfSmrg    if (CHECK_DATA_ACCESS())
44435c4bbdfSmrg        x86emu_check_data_access((u16) get_data_segment(), offset);
44505b261ecSmrg#endif
44635c4bbdfSmrg    (*sys_wrb) ((get_data_segment() << 4) + offset, val);
44705b261ecSmrg}
44805b261ecSmrg
44905b261ecSmrg/****************************************************************************
45005b261ecSmrgPARAMETERS:
45105b261ecSmrgoffset	- Offset to store data at
45205b261ecSmrgval		- Value to store
45305b261ecSmrg
45405b261ecSmrgREMARKS:
45505b261ecSmrgWrites a word value to an segmented memory location. The segment used is
45605b261ecSmrgthe current 'default' segment, which may have been overridden.
45705b261ecSmrg
45805b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline!
45905b261ecSmrg****************************************************************************/
46035c4bbdfSmrgvoid
46135c4bbdfSmrgstore_data_word(uint offset, u16 val)
46205b261ecSmrg{
46305b261ecSmrg#ifdef DEBUG
46435c4bbdfSmrg    if (CHECK_DATA_ACCESS())
46535c4bbdfSmrg        x86emu_check_data_access((u16) get_data_segment(), offset);
46605b261ecSmrg#endif
46735c4bbdfSmrg    (*sys_wrw) ((get_data_segment() << 4) + offset, val);
46805b261ecSmrg}
46905b261ecSmrg
47005b261ecSmrg/****************************************************************************
47105b261ecSmrgPARAMETERS:
47205b261ecSmrgoffset	- Offset to store data at
47305b261ecSmrgval		- Value to store
47405b261ecSmrg
47505b261ecSmrgREMARKS:
47605b261ecSmrgWrites a long value to an segmented memory location. The segment used is
47705b261ecSmrgthe current 'default' segment, which may have been overridden.
47805b261ecSmrg
47905b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline!
48005b261ecSmrg****************************************************************************/
48135c4bbdfSmrgvoid
48235c4bbdfSmrgstore_data_long(uint offset, u32 val)
48305b261ecSmrg{
48405b261ecSmrg#ifdef DEBUG
48535c4bbdfSmrg    if (CHECK_DATA_ACCESS())
48635c4bbdfSmrg        x86emu_check_data_access((u16) get_data_segment(), offset);
48705b261ecSmrg#endif
48835c4bbdfSmrg    (*sys_wrl) ((get_data_segment() << 4) + offset, val);
48905b261ecSmrg}
49005b261ecSmrg
49105b261ecSmrg/****************************************************************************
49205b261ecSmrgPARAMETERS:
49305b261ecSmrgsegment	- Segment to store data at
49405b261ecSmrgoffset	- Offset to store data at
49505b261ecSmrgval		- Value to store
49605b261ecSmrg
49705b261ecSmrgREMARKS:
49805b261ecSmrgWrites a byte value to an absolute memory location.
49905b261ecSmrg
50005b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline!
50105b261ecSmrg****************************************************************************/
50235c4bbdfSmrgvoid
50335c4bbdfSmrgstore_data_byte_abs(uint segment, uint offset, u8 val)
50405b261ecSmrg{
50505b261ecSmrg#ifdef DEBUG
50635c4bbdfSmrg    if (CHECK_DATA_ACCESS())
50735c4bbdfSmrg        x86emu_check_data_access(segment, offset);
50805b261ecSmrg#endif
50935c4bbdfSmrg    (*sys_wrb) (((u32) segment << 4) + offset, val);
51005b261ecSmrg}
51105b261ecSmrg
51205b261ecSmrg/****************************************************************************
51305b261ecSmrgPARAMETERS:
51405b261ecSmrgsegment	- Segment to store data at
51505b261ecSmrgoffset	- Offset to store data at
51605b261ecSmrgval		- Value to store
51705b261ecSmrg
51805b261ecSmrgREMARKS:
51905b261ecSmrgWrites a word value to an absolute memory location.
52005b261ecSmrg
52105b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline!
52205b261ecSmrg****************************************************************************/
52335c4bbdfSmrgvoid
52435c4bbdfSmrgstore_data_word_abs(uint segment, uint offset, u16 val)
52505b261ecSmrg{
52605b261ecSmrg#ifdef DEBUG
52735c4bbdfSmrg    if (CHECK_DATA_ACCESS())
52835c4bbdfSmrg        x86emu_check_data_access(segment, offset);
52905b261ecSmrg#endif
53035c4bbdfSmrg    (*sys_wrw) (((u32) segment << 4) + offset, val);
53105b261ecSmrg}
53205b261ecSmrg
53305b261ecSmrg/****************************************************************************
53405b261ecSmrgPARAMETERS:
53505b261ecSmrgsegment	- Segment to store data at
53605b261ecSmrgoffset	- Offset to store data at
53705b261ecSmrgval		- Value to store
53805b261ecSmrg
53905b261ecSmrgREMARKS:
54005b261ecSmrgWrites a long value to an absolute memory location.
54105b261ecSmrg
54205b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline!
54305b261ecSmrg****************************************************************************/
54435c4bbdfSmrgvoid
54535c4bbdfSmrgstore_data_long_abs(uint segment, uint offset, u32 val)
54605b261ecSmrg{
54705b261ecSmrg#ifdef DEBUG
54835c4bbdfSmrg    if (CHECK_DATA_ACCESS())
54935c4bbdfSmrg        x86emu_check_data_access(segment, offset);
55005b261ecSmrg#endif
55135c4bbdfSmrg    (*sys_wrl) (((u32) segment << 4) + offset, val);
55205b261ecSmrg}
55305b261ecSmrg
55405b261ecSmrg/****************************************************************************
55505b261ecSmrgPARAMETERS:
55605b261ecSmrgreg	- Register to decode
55705b261ecSmrg
55805b261ecSmrgRETURNS:
55905b261ecSmrgPointer to the appropriate register
56005b261ecSmrg
56105b261ecSmrgREMARKS:
56205b261ecSmrgReturn a pointer to the register given by the R/RM field of the
56305b261ecSmrgmodrm byte, for byte operands. Also enables the decoding of instructions.
56405b261ecSmrg****************************************************************************/
56535c4bbdfSmrgu8 *
56635c4bbdfSmrgdecode_rm_byte_register(int reg)
56705b261ecSmrg{
56835c4bbdfSmrg    switch (reg) {
56935c4bbdfSmrg    case 0:
57035c4bbdfSmrg        DECODE_PRINTF("AL");
57135c4bbdfSmrg        return &M.x86.R_AL;
57235c4bbdfSmrg    case 1:
57335c4bbdfSmrg        DECODE_PRINTF("CL");
57435c4bbdfSmrg        return &M.x86.R_CL;
57535c4bbdfSmrg    case 2:
57635c4bbdfSmrg        DECODE_PRINTF("DL");
57735c4bbdfSmrg        return &M.x86.R_DL;
57835c4bbdfSmrg    case 3:
57935c4bbdfSmrg        DECODE_PRINTF("BL");
58035c4bbdfSmrg        return &M.x86.R_BL;
58135c4bbdfSmrg    case 4:
58235c4bbdfSmrg        DECODE_PRINTF("AH");
58335c4bbdfSmrg        return &M.x86.R_AH;
58435c4bbdfSmrg    case 5:
58535c4bbdfSmrg        DECODE_PRINTF("CH");
58635c4bbdfSmrg        return &M.x86.R_CH;
58735c4bbdfSmrg    case 6:
58835c4bbdfSmrg        DECODE_PRINTF("DH");
58935c4bbdfSmrg        return &M.x86.R_DH;
59035c4bbdfSmrg    case 7:
59135c4bbdfSmrg        DECODE_PRINTF("BH");
59235c4bbdfSmrg        return &M.x86.R_BH;
59335c4bbdfSmrg    }
59435c4bbdfSmrg    HALT_SYS();
59535c4bbdfSmrg    return NULL;                /* NOT REACHED OR REACHED ON ERROR */
59605b261ecSmrg}
59705b261ecSmrg
59805b261ecSmrg/****************************************************************************
59905b261ecSmrgPARAMETERS:
60005b261ecSmrgreg	- Register to decode
60105b261ecSmrg
60205b261ecSmrgRETURNS:
60305b261ecSmrgPointer to the appropriate register
60405b261ecSmrg
60505b261ecSmrgREMARKS:
60605b261ecSmrgReturn a pointer to the register given by the R/RM field of the
60705b261ecSmrgmodrm byte, for word operands.  Also enables the decoding of instructions.
60805b261ecSmrg****************************************************************************/
60935c4bbdfSmrgu16 *
61035c4bbdfSmrgdecode_rm_word_register(int reg)
61105b261ecSmrg{
61235c4bbdfSmrg    switch (reg) {
61335c4bbdfSmrg    case 0:
61435c4bbdfSmrg        DECODE_PRINTF("AX");
61535c4bbdfSmrg        return &M.x86.R_AX;
61635c4bbdfSmrg    case 1:
61735c4bbdfSmrg        DECODE_PRINTF("CX");
61835c4bbdfSmrg        return &M.x86.R_CX;
61935c4bbdfSmrg    case 2:
62035c4bbdfSmrg        DECODE_PRINTF("DX");
62135c4bbdfSmrg        return &M.x86.R_DX;
62235c4bbdfSmrg    case 3:
62335c4bbdfSmrg        DECODE_PRINTF("BX");
62435c4bbdfSmrg        return &M.x86.R_BX;
62535c4bbdfSmrg    case 4:
62635c4bbdfSmrg        DECODE_PRINTF("SP");
62735c4bbdfSmrg        return &M.x86.R_SP;
62835c4bbdfSmrg    case 5:
62935c4bbdfSmrg        DECODE_PRINTF("BP");
63035c4bbdfSmrg        return &M.x86.R_BP;
63135c4bbdfSmrg    case 6:
63235c4bbdfSmrg        DECODE_PRINTF("SI");
63335c4bbdfSmrg        return &M.x86.R_SI;
63435c4bbdfSmrg    case 7:
63535c4bbdfSmrg        DECODE_PRINTF("DI");
63635c4bbdfSmrg        return &M.x86.R_DI;
63735c4bbdfSmrg    }
63835c4bbdfSmrg    HALT_SYS();
63905b261ecSmrg    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
64005b261ecSmrg}
64105b261ecSmrg
64205b261ecSmrg/****************************************************************************
64305b261ecSmrgPARAMETERS:
64405b261ecSmrgreg	- Register to decode
64505b261ecSmrg
64605b261ecSmrgRETURNS:
64705b261ecSmrgPointer to the appropriate register
64805b261ecSmrg
64905b261ecSmrgREMARKS:
65005b261ecSmrgReturn a pointer to the register given by the R/RM field of the
65105b261ecSmrgmodrm byte, for dword operands.  Also enables the decoding of instructions.
65205b261ecSmrg****************************************************************************/
65335c4bbdfSmrgu32 *
65435c4bbdfSmrgdecode_rm_long_register(int reg)
65505b261ecSmrg{
65605b261ecSmrg    switch (reg) {
65735c4bbdfSmrg    case 0:
65835c4bbdfSmrg        DECODE_PRINTF("EAX");
65935c4bbdfSmrg        return &M.x86.R_EAX;
66035c4bbdfSmrg    case 1:
66135c4bbdfSmrg        DECODE_PRINTF("ECX");
66235c4bbdfSmrg        return &M.x86.R_ECX;
66335c4bbdfSmrg    case 2:
66435c4bbdfSmrg        DECODE_PRINTF("EDX");
66535c4bbdfSmrg        return &M.x86.R_EDX;
66635c4bbdfSmrg    case 3:
66735c4bbdfSmrg        DECODE_PRINTF("EBX");
66835c4bbdfSmrg        return &M.x86.R_EBX;
66935c4bbdfSmrg    case 4:
67035c4bbdfSmrg        DECODE_PRINTF("ESP");
67135c4bbdfSmrg        return &M.x86.R_ESP;
67235c4bbdfSmrg    case 5:
67335c4bbdfSmrg        DECODE_PRINTF("EBP");
67435c4bbdfSmrg        return &M.x86.R_EBP;
67535c4bbdfSmrg    case 6:
67635c4bbdfSmrg        DECODE_PRINTF("ESI");
67735c4bbdfSmrg        return &M.x86.R_ESI;
67835c4bbdfSmrg    case 7:
67935c4bbdfSmrg        DECODE_PRINTF("EDI");
68035c4bbdfSmrg        return &M.x86.R_EDI;
68135c4bbdfSmrg    }
68235c4bbdfSmrg    HALT_SYS();
68305b261ecSmrg    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
68405b261ecSmrg}
68505b261ecSmrg
68605b261ecSmrg/****************************************************************************
68705b261ecSmrgPARAMETERS:
68805b261ecSmrgreg	- Register to decode
68905b261ecSmrg
69005b261ecSmrgRETURNS:
69105b261ecSmrgPointer to the appropriate register
69205b261ecSmrg
69305b261ecSmrgREMARKS:
69405b261ecSmrgReturn a pointer to the register given by the R/RM field of the
69505b261ecSmrgmodrm byte, for word operands, modified from above for the weirdo
69605b261ecSmrgspecial case of segreg operands.  Also enables the decoding of instructions.
69705b261ecSmrg****************************************************************************/
69835c4bbdfSmrgu16 *
69935c4bbdfSmrgdecode_rm_seg_register(int reg)
70005b261ecSmrg{
70135c4bbdfSmrg    switch (reg) {
70235c4bbdfSmrg    case 0:
70335c4bbdfSmrg        DECODE_PRINTF("ES");
70435c4bbdfSmrg        return &M.x86.R_ES;
70535c4bbdfSmrg    case 1:
70635c4bbdfSmrg        DECODE_PRINTF("CS");
70735c4bbdfSmrg        return &M.x86.R_CS;
70835c4bbdfSmrg    case 2:
70935c4bbdfSmrg        DECODE_PRINTF("SS");
71035c4bbdfSmrg        return &M.x86.R_SS;
71135c4bbdfSmrg    case 3:
71235c4bbdfSmrg        DECODE_PRINTF("DS");
71335c4bbdfSmrg        return &M.x86.R_DS;
71435c4bbdfSmrg    case 4:
71535c4bbdfSmrg        DECODE_PRINTF("FS");
71635c4bbdfSmrg        return &M.x86.R_FS;
71735c4bbdfSmrg    case 5:
71835c4bbdfSmrg        DECODE_PRINTF("GS");
71935c4bbdfSmrg        return &M.x86.R_GS;
72035c4bbdfSmrg    case 6:
72135c4bbdfSmrg    case 7:
72235c4bbdfSmrg        DECODE_PRINTF("ILLEGAL SEGREG");
72335c4bbdfSmrg        break;
72435c4bbdfSmrg    }
72535c4bbdfSmrg    HALT_SYS();
72635c4bbdfSmrg    return NULL;                /* NOT REACHED OR REACHED ON ERROR */
72705b261ecSmrg}
72805b261ecSmrg
72905b261ecSmrg/*
73005b261ecSmrg *
73105b261ecSmrg * return offset from the SIB Byte
73205b261ecSmrg */
73335c4bbdfSmrgu32
73435c4bbdfSmrgdecode_sib_address(int sib, int mod)
73505b261ecSmrg{
73605b261ecSmrg    u32 base = 0, i = 0, scale = 1;
73705b261ecSmrg
73835c4bbdfSmrg    switch (sib & 0x07) {
73905b261ecSmrg    case 0:
74035c4bbdfSmrg        DECODE_PRINTF("[EAX]");
74135c4bbdfSmrg        base = M.x86.R_EAX;
74235c4bbdfSmrg        break;
74305b261ecSmrg    case 1:
74435c4bbdfSmrg        DECODE_PRINTF("[ECX]");
74535c4bbdfSmrg        base = M.x86.R_ECX;
74635c4bbdfSmrg        break;
74705b261ecSmrg    case 2:
74835c4bbdfSmrg        DECODE_PRINTF("[EDX]");
74935c4bbdfSmrg        base = M.x86.R_EDX;
75035c4bbdfSmrg        break;
75105b261ecSmrg    case 3:
75235c4bbdfSmrg        DECODE_PRINTF("[EBX]");
75335c4bbdfSmrg        base = M.x86.R_EBX;
75435c4bbdfSmrg        break;
75505b261ecSmrg    case 4:
75635c4bbdfSmrg        DECODE_PRINTF("[ESP]");
75735c4bbdfSmrg        base = M.x86.R_ESP;
75835c4bbdfSmrg        M.x86.mode |= SYSMODE_SEG_DS_SS;
75935c4bbdfSmrg        break;
76005b261ecSmrg    case 5:
76135c4bbdfSmrg        if (mod == 0) {
76235c4bbdfSmrg            base = fetch_long_imm();
76335c4bbdfSmrg            DECODE_PRINTF2("%08x", base);
76435c4bbdfSmrg        }
76535c4bbdfSmrg        else {
76635c4bbdfSmrg            DECODE_PRINTF("[EBP]");
76735c4bbdfSmrg            base = M.x86.R_ESP;
76835c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
76935c4bbdfSmrg        }
77035c4bbdfSmrg        break;
77105b261ecSmrg    case 6:
77235c4bbdfSmrg        DECODE_PRINTF("[ESI]");
77335c4bbdfSmrg        base = M.x86.R_ESI;
77435c4bbdfSmrg        break;
77505b261ecSmrg    case 7:
77635c4bbdfSmrg        DECODE_PRINTF("[EDI]");
77735c4bbdfSmrg        base = M.x86.R_EDI;
77835c4bbdfSmrg        break;
77905b261ecSmrg    }
78005b261ecSmrg    switch ((sib >> 3) & 0x07) {
78105b261ecSmrg    case 0:
78235c4bbdfSmrg        DECODE_PRINTF("[EAX");
78335c4bbdfSmrg        i = M.x86.R_EAX;
78435c4bbdfSmrg        break;
78505b261ecSmrg    case 1:
78635c4bbdfSmrg        DECODE_PRINTF("[ECX");
78735c4bbdfSmrg        i = M.x86.R_ECX;
78835c4bbdfSmrg        break;
78905b261ecSmrg    case 2:
79035c4bbdfSmrg        DECODE_PRINTF("[EDX");
79135c4bbdfSmrg        i = M.x86.R_EDX;
79235c4bbdfSmrg        break;
79305b261ecSmrg    case 3:
79435c4bbdfSmrg        DECODE_PRINTF("[EBX");
79535c4bbdfSmrg        i = M.x86.R_EBX;
79635c4bbdfSmrg        break;
79705b261ecSmrg    case 4:
79835c4bbdfSmrg        i = 0;
79935c4bbdfSmrg        break;
80005b261ecSmrg    case 5:
80135c4bbdfSmrg        DECODE_PRINTF("[EBP");
80235c4bbdfSmrg        i = M.x86.R_EBP;
80335c4bbdfSmrg        break;
80405b261ecSmrg    case 6:
80535c4bbdfSmrg        DECODE_PRINTF("[ESI");
80635c4bbdfSmrg        i = M.x86.R_ESI;
80735c4bbdfSmrg        break;
80805b261ecSmrg    case 7:
80935c4bbdfSmrg        DECODE_PRINTF("[EDI");
81035c4bbdfSmrg        i = M.x86.R_EDI;
81135c4bbdfSmrg        break;
81205b261ecSmrg    }
81305b261ecSmrg    scale = 1 << ((sib >> 6) & 0x03);
81405b261ecSmrg    if (((sib >> 3) & 0x07) != 4) {
81535c4bbdfSmrg        if (scale == 1) {
81635c4bbdfSmrg            DECODE_PRINTF("]");
81735c4bbdfSmrg        }
81835c4bbdfSmrg        else {
81935c4bbdfSmrg            DECODE_PRINTF2("*%d]", scale);
82035c4bbdfSmrg        }
82105b261ecSmrg    }
82205b261ecSmrg    return base + (i * scale);
82305b261ecSmrg}
82405b261ecSmrg
82505b261ecSmrg/****************************************************************************
82605b261ecSmrgPARAMETERS:
82705b261ecSmrgrm	- RM value to decode
82805b261ecSmrg
82905b261ecSmrgRETURNS:
83005b261ecSmrgOffset in memory for the address decoding
83105b261ecSmrg
83205b261ecSmrgREMARKS:
83305b261ecSmrgReturn the offset given by mod=00 addressing.  Also enables the
83405b261ecSmrgdecoding of instructions.
83505b261ecSmrg
83605b261ecSmrgNOTE: 	The code which specifies the corresponding segment (ds vs ss)
83705b261ecSmrg		below in the case of [BP+..].  The assumption here is that at the
83805b261ecSmrg		point that this subroutine is called, the bit corresponding to
83905b261ecSmrg		SYSMODE_SEG_DS_SS will be zero.  After every instruction
84005b261ecSmrg		except the segment override instructions, this bit (as well
84105b261ecSmrg		as any bits indicating segment overrides) will be clear.  So
84205b261ecSmrg		if a SS access is needed, set this bit.  Otherwise, DS access
84305b261ecSmrg		occurs (unless any of the segment override bits are set).
84405b261ecSmrg****************************************************************************/
84535c4bbdfSmrgu32
84635c4bbdfSmrgdecode_rm00_address(int rm)
84705b261ecSmrg{
84805b261ecSmrg    u32 offset;
84905b261ecSmrg    int sib;
85005b261ecSmrg
85105b261ecSmrg    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
85205b261ecSmrg        /* 32-bit addressing */
85335c4bbdfSmrg        switch (rm) {
85435c4bbdfSmrg        case 0:
85535c4bbdfSmrg            DECODE_PRINTF("[EAX]");
85635c4bbdfSmrg            return M.x86.R_EAX;
85735c4bbdfSmrg        case 1:
85835c4bbdfSmrg            DECODE_PRINTF("[ECX]");
85935c4bbdfSmrg            return M.x86.R_ECX;
86035c4bbdfSmrg        case 2:
86135c4bbdfSmrg            DECODE_PRINTF("[EDX]");
86235c4bbdfSmrg            return M.x86.R_EDX;
86335c4bbdfSmrg        case 3:
86435c4bbdfSmrg            DECODE_PRINTF("[EBX]");
86535c4bbdfSmrg            return M.x86.R_EBX;
86635c4bbdfSmrg        case 4:
86735c4bbdfSmrg            sib = fetch_byte_imm();
86835c4bbdfSmrg            return decode_sib_address(sib, 0);
86935c4bbdfSmrg        case 5:
87035c4bbdfSmrg            offset = fetch_long_imm();
87135c4bbdfSmrg            DECODE_PRINTF2("[%08x]", offset);
87235c4bbdfSmrg            return offset;
87335c4bbdfSmrg        case 6:
87435c4bbdfSmrg            DECODE_PRINTF("[ESI]");
87535c4bbdfSmrg            return M.x86.R_ESI;
87635c4bbdfSmrg        case 7:
87735c4bbdfSmrg            DECODE_PRINTF("[EDI]");
87835c4bbdfSmrg            return M.x86.R_EDI;
87935c4bbdfSmrg        }
88035c4bbdfSmrg        HALT_SYS();
88135c4bbdfSmrg    }
88235c4bbdfSmrg    else {
88305b261ecSmrg        /* 16-bit addressing */
88435c4bbdfSmrg        switch (rm) {
88535c4bbdfSmrg        case 0:
88635c4bbdfSmrg            DECODE_PRINTF("[BX+SI]");
88705b261ecSmrg            return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
88835c4bbdfSmrg        case 1:
88935c4bbdfSmrg            DECODE_PRINTF("[BX+DI]");
89005b261ecSmrg            return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
89135c4bbdfSmrg        case 2:
89235c4bbdfSmrg            DECODE_PRINTF("[BP+SI]");
89335c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
89405b261ecSmrg            return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
89535c4bbdfSmrg        case 3:
89635c4bbdfSmrg            DECODE_PRINTF("[BP+DI]");
89735c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
89805b261ecSmrg            return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
89935c4bbdfSmrg        case 4:
90035c4bbdfSmrg            DECODE_PRINTF("[SI]");
90135c4bbdfSmrg            return M.x86.R_SI;
90235c4bbdfSmrg        case 5:
90335c4bbdfSmrg            DECODE_PRINTF("[DI]");
90435c4bbdfSmrg            return M.x86.R_DI;
90535c4bbdfSmrg        case 6:
90635c4bbdfSmrg            offset = fetch_word_imm();
90735c4bbdfSmrg            DECODE_PRINTF2("[%04x]", offset);
90835c4bbdfSmrg            return offset;
90935c4bbdfSmrg        case 7:
91035c4bbdfSmrg            DECODE_PRINTF("[BX]");
91135c4bbdfSmrg            return M.x86.R_BX;
91235c4bbdfSmrg        }
91335c4bbdfSmrg        HALT_SYS();
91405b261ecSmrg    }
91505b261ecSmrg    return 0;
91605b261ecSmrg}
91705b261ecSmrg
91805b261ecSmrg/****************************************************************************
91905b261ecSmrgPARAMETERS:
92005b261ecSmrgrm	- RM value to decode
92105b261ecSmrg
92205b261ecSmrgRETURNS:
92305b261ecSmrgOffset in memory for the address decoding
92405b261ecSmrg
92505b261ecSmrgREMARKS:
92605b261ecSmrgReturn the offset given by mod=01 addressing.  Also enables the
92705b261ecSmrgdecoding of instructions.
92805b261ecSmrg****************************************************************************/
92935c4bbdfSmrgu32
93035c4bbdfSmrgdecode_rm01_address(int rm)
93105b261ecSmrg{
93205b261ecSmrg    int displacement = 0;
93305b261ecSmrg    int sib;
93405b261ecSmrg
93505b261ecSmrg    /* Fetch disp8 if no SIB byte */
93605b261ecSmrg    if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4)))
93735c4bbdfSmrg        displacement = (s8) fetch_byte_imm();
93805b261ecSmrg
93905b261ecSmrg    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
94005b261ecSmrg        /* 32-bit addressing */
94135c4bbdfSmrg        switch (rm) {
94235c4bbdfSmrg        case 0:
94335c4bbdfSmrg            DECODE_PRINTF2("%d[EAX]", displacement);
94435c4bbdfSmrg            return M.x86.R_EAX + displacement;
94535c4bbdfSmrg        case 1:
94635c4bbdfSmrg            DECODE_PRINTF2("%d[ECX]", displacement);
94735c4bbdfSmrg            return M.x86.R_ECX + displacement;
94835c4bbdfSmrg        case 2:
94935c4bbdfSmrg            DECODE_PRINTF2("%d[EDX]", displacement);
95035c4bbdfSmrg            return M.x86.R_EDX + displacement;
95135c4bbdfSmrg        case 3:
95235c4bbdfSmrg            DECODE_PRINTF2("%d[EBX]", displacement);
95335c4bbdfSmrg            return M.x86.R_EBX + displacement;
95435c4bbdfSmrg        case 4:
95535c4bbdfSmrg            sib = fetch_byte_imm();
95635c4bbdfSmrg            displacement = (s8) fetch_byte_imm();
95735c4bbdfSmrg            DECODE_PRINTF2("%d", displacement);
95835c4bbdfSmrg            return decode_sib_address(sib, 1) + displacement;
95935c4bbdfSmrg        case 5:
96035c4bbdfSmrg            DECODE_PRINTF2("%d[EBP]", displacement);
96135c4bbdfSmrg            return M.x86.R_EBP + displacement;
96235c4bbdfSmrg        case 6:
96335c4bbdfSmrg            DECODE_PRINTF2("%d[ESI]", displacement);
96435c4bbdfSmrg            return M.x86.R_ESI + displacement;
96535c4bbdfSmrg        case 7:
96635c4bbdfSmrg            DECODE_PRINTF2("%d[EDI]", displacement);
96735c4bbdfSmrg            return M.x86.R_EDI + displacement;
96835c4bbdfSmrg        }
96935c4bbdfSmrg        HALT_SYS();
97035c4bbdfSmrg    }
97135c4bbdfSmrg    else {
97205b261ecSmrg        /* 16-bit addressing */
97335c4bbdfSmrg        switch (rm) {
97435c4bbdfSmrg        case 0:
97535c4bbdfSmrg            DECODE_PRINTF2("%d[BX+SI]", displacement);
97605b261ecSmrg            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
97735c4bbdfSmrg        case 1:
97835c4bbdfSmrg            DECODE_PRINTF2("%d[BX+DI]", displacement);
97905b261ecSmrg            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
98035c4bbdfSmrg        case 2:
98135c4bbdfSmrg            DECODE_PRINTF2("%d[BP+SI]", displacement);
98235c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
98305b261ecSmrg            return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
98435c4bbdfSmrg        case 3:
98535c4bbdfSmrg            DECODE_PRINTF2("%d[BP+DI]", displacement);
98635c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
98705b261ecSmrg            return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
98835c4bbdfSmrg        case 4:
98935c4bbdfSmrg            DECODE_PRINTF2("%d[SI]", displacement);
99005b261ecSmrg            return (M.x86.R_SI + displacement) & 0xffff;
99135c4bbdfSmrg        case 5:
99235c4bbdfSmrg            DECODE_PRINTF2("%d[DI]", displacement);
99305b261ecSmrg            return (M.x86.R_DI + displacement) & 0xffff;
99435c4bbdfSmrg        case 6:
99535c4bbdfSmrg            DECODE_PRINTF2("%d[BP]", displacement);
99635c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
99705b261ecSmrg            return (M.x86.R_BP + displacement) & 0xffff;
99835c4bbdfSmrg        case 7:
99935c4bbdfSmrg            DECODE_PRINTF2("%d[BX]", displacement);
100005b261ecSmrg            return (M.x86.R_BX + displacement) & 0xffff;
100135c4bbdfSmrg        }
100235c4bbdfSmrg        HALT_SYS();
100305b261ecSmrg    }
100405b261ecSmrg    return 0;                   /* SHOULD NOT HAPPEN */
100505b261ecSmrg}
100605b261ecSmrg
100705b261ecSmrg/****************************************************************************
100805b261ecSmrgPARAMETERS:
100905b261ecSmrgrm	- RM value to decode
101005b261ecSmrg
101105b261ecSmrgRETURNS:
101205b261ecSmrgOffset in memory for the address decoding
101305b261ecSmrg
101405b261ecSmrgREMARKS:
101505b261ecSmrgReturn the offset given by mod=10 addressing.  Also enables the
101605b261ecSmrgdecoding of instructions.
101705b261ecSmrg****************************************************************************/
101835c4bbdfSmrgu32
101935c4bbdfSmrgdecode_rm10_address(int rm)
102005b261ecSmrg{
102105b261ecSmrg    u32 displacement = 0;
102205b261ecSmrg    int sib;
102305b261ecSmrg
102405b261ecSmrg    /* Fetch disp16 if 16-bit addr mode */
102505b261ecSmrg    if (!(M.x86.mode & SYSMODE_PREFIX_ADDR))
102635c4bbdfSmrg        displacement = (u16) fetch_word_imm();
102705b261ecSmrg    else {
102835c4bbdfSmrg        /* Fetch disp32 if no SIB byte */
102935c4bbdfSmrg        if (rm != 4)
103035c4bbdfSmrg            displacement = (u32) fetch_long_imm();
103105b261ecSmrg    }
103205b261ecSmrg
103305b261ecSmrg    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
103405b261ecSmrg        /* 32-bit addressing */
103535c4bbdfSmrg        switch (rm) {
103635c4bbdfSmrg        case 0:
103735c4bbdfSmrg            DECODE_PRINTF2("%08x[EAX]", displacement);
103835c4bbdfSmrg            return M.x86.R_EAX + displacement;
103935c4bbdfSmrg        case 1:
104035c4bbdfSmrg            DECODE_PRINTF2("%08x[ECX]", displacement);
104135c4bbdfSmrg            return M.x86.R_ECX + displacement;
104235c4bbdfSmrg        case 2:
104335c4bbdfSmrg            DECODE_PRINTF2("%08x[EDX]", displacement);
104435c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
104535c4bbdfSmrg            return M.x86.R_EDX + displacement;
104635c4bbdfSmrg        case 3:
104735c4bbdfSmrg            DECODE_PRINTF2("%08x[EBX]", displacement);
104835c4bbdfSmrg            return M.x86.R_EBX + displacement;
104935c4bbdfSmrg        case 4:
105035c4bbdfSmrg            sib = fetch_byte_imm();
105135c4bbdfSmrg            displacement = (u32) fetch_long_imm();
105235c4bbdfSmrg            DECODE_PRINTF2("%08x", displacement);
105335c4bbdfSmrg            return decode_sib_address(sib, 2) + displacement;
105435c4bbdfSmrg            break;
105535c4bbdfSmrg        case 5:
105635c4bbdfSmrg            DECODE_PRINTF2("%08x[EBP]", displacement);
105735c4bbdfSmrg            return M.x86.R_EBP + displacement;
105835c4bbdfSmrg        case 6:
105935c4bbdfSmrg            DECODE_PRINTF2("%08x[ESI]", displacement);
106035c4bbdfSmrg            return M.x86.R_ESI + displacement;
106135c4bbdfSmrg        case 7:
106235c4bbdfSmrg            DECODE_PRINTF2("%08x[EDI]", displacement);
106335c4bbdfSmrg            return M.x86.R_EDI + displacement;
106435c4bbdfSmrg        }
106535c4bbdfSmrg        HALT_SYS();
106635c4bbdfSmrg    }
106735c4bbdfSmrg    else {
106805b261ecSmrg        /* 16-bit addressing */
106935c4bbdfSmrg        switch (rm) {
107035c4bbdfSmrg        case 0:
107105b261ecSmrg            DECODE_PRINTF2("%04x[BX+SI]", displacement);
107205b261ecSmrg            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
107335c4bbdfSmrg        case 1:
107405b261ecSmrg            DECODE_PRINTF2("%04x[BX+DI]", displacement);
107505b261ecSmrg            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
107635c4bbdfSmrg        case 2:
107735c4bbdfSmrg            DECODE_PRINTF2("%04x[BP+SI]", displacement);
107835c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
107905b261ecSmrg            return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
108035c4bbdfSmrg        case 3:
108135c4bbdfSmrg            DECODE_PRINTF2("%04x[BP+DI]", displacement);
108235c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
108305b261ecSmrg            return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
108435c4bbdfSmrg        case 4:
108505b261ecSmrg            DECODE_PRINTF2("%04x[SI]", displacement);
108605b261ecSmrg            return (M.x86.R_SI + displacement) & 0xffff;
108735c4bbdfSmrg        case 5:
108805b261ecSmrg            DECODE_PRINTF2("%04x[DI]", displacement);
108905b261ecSmrg            return (M.x86.R_DI + displacement) & 0xffff;
109035c4bbdfSmrg        case 6:
109135c4bbdfSmrg            DECODE_PRINTF2("%04x[BP]", displacement);
109235c4bbdfSmrg            M.x86.mode |= SYSMODE_SEG_DS_SS;
109305b261ecSmrg            return (M.x86.R_BP + displacement) & 0xffff;
109435c4bbdfSmrg        case 7:
109505b261ecSmrg            DECODE_PRINTF2("%04x[BX]", displacement);
109605b261ecSmrg            return (M.x86.R_BX + displacement) & 0xffff;
109735c4bbdfSmrg        }
109835c4bbdfSmrg        HALT_SYS();
109905b261ecSmrg    }
110005b261ecSmrg    return 0;
110105b261ecSmrg    /*NOTREACHED */
110205b261ecSmrg}
1103