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