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