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