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