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