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