1*4882a593Smuzhiyun /****************************************************************************
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * BIOS emulator and interface
4*4882a593Smuzhiyun * to Realmode X86 Emulator Library
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2007 Freescale Semiconductor, Inc.
7*4882a593Smuzhiyun * Jason Jin <Jason.jin@freescale.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Copyright (C) 1996-1999 SciTech Software, Inc.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * ========================================================================
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software and
14*4882a593Smuzhiyun * its documentation for any purpose is hereby granted without fee,
15*4882a593Smuzhiyun * provided that the above copyright notice appear in all copies and that
16*4882a593Smuzhiyun * both that copyright notice and this permission notice appear in
17*4882a593Smuzhiyun * supporting documentation, and that the name of the authors not be used
18*4882a593Smuzhiyun * in advertising or publicity pertaining to distribution of the software
19*4882a593Smuzhiyun * without specific, written prior permission. The authors makes no
20*4882a593Smuzhiyun * representations about the suitability of this software for any purpose.
21*4882a593Smuzhiyun * It is provided "as is" without express or implied warranty.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24*4882a593Smuzhiyun * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25*4882a593Smuzhiyun * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27*4882a593Smuzhiyun * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28*4882a593Smuzhiyun * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29*4882a593Smuzhiyun * PERFORMANCE OF THIS SOFTWARE.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * ========================================================================
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * Language: ANSI C
34*4882a593Smuzhiyun * Environment: Any
35*4882a593Smuzhiyun * Developer: Kendall Bennett
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * Description: Module implementing the system specific functions. This
38*4882a593Smuzhiyun * module is always compiled and linked in the OS depedent
39*4882a593Smuzhiyun * libraries, and never in a binary portable driver.
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun * Jason ported this file to u-boot to run the ATI video card BIOS
42*4882a593Smuzhiyun * in u-boot. Made all the video memory be emulated during the
43*4882a593Smuzhiyun * BIOS runing process which may affect the VGA function but the
44*4882a593Smuzhiyun * frambuffer function can work after run the BIOS.
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun ****************************************************************************/
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #include <malloc.h>
49*4882a593Smuzhiyun #include <common.h>
50*4882a593Smuzhiyun #include "biosemui.h"
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun BE_sysEnv _BE_env = {{0}};
53*4882a593Smuzhiyun static X86EMU_memFuncs _BE_mem __attribute__((section(GOT2_TYPE))) = {
54*4882a593Smuzhiyun BE_rdb,
55*4882a593Smuzhiyun BE_rdw,
56*4882a593Smuzhiyun BE_rdl,
57*4882a593Smuzhiyun BE_wrb,
58*4882a593Smuzhiyun BE_wrw,
59*4882a593Smuzhiyun BE_wrl,
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun static X86EMU_pioFuncs _BE_pio __attribute__((section(GOT2_TYPE))) = {
63*4882a593Smuzhiyun BE_inb,
64*4882a593Smuzhiyun BE_inw,
65*4882a593Smuzhiyun BE_inl,
66*4882a593Smuzhiyun BE_outb,
67*4882a593Smuzhiyun BE_outw,
68*4882a593Smuzhiyun BE_outl,
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define OFF(addr) (u16)(((addr) >> 0) & 0xffff)
72*4882a593Smuzhiyun #define SEG(addr) (u16)(((addr) >> 4) & 0xf000)
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /****************************************************************************
75*4882a593Smuzhiyun PARAMETERS:
76*4882a593Smuzhiyun debugFlags - Flags to enable debugging options (debug builds only)
77*4882a593Smuzhiyun memSize - Amount of memory to allocate for real mode machine
78*4882a593Smuzhiyun info - Pointer to default VGA device information
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun REMARKS:
81*4882a593Smuzhiyun This functions initialises the BElib, and uses the passed in
82*4882a593Smuzhiyun BIOS image as the BIOS that is used and emulated at 0xC0000.
83*4882a593Smuzhiyun ****************************************************************************/
BE_init(u32 debugFlags,int memSize,BE_VGAInfo * info,int shared)84*4882a593Smuzhiyun int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun #if !defined(__DRIVER__) && !defined(__KERNEL__)
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun PM_init();
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun memset(&M, 0, sizeof(M));
91*4882a593Smuzhiyun if (memSize < 20480){
92*4882a593Smuzhiyun printf("Emulator requires at least 20Kb of memory!\n");
93*4882a593Smuzhiyun return 0;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun M.mem_base = malloc(memSize);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun if (M.mem_base == NULL){
99*4882a593Smuzhiyun printf("Biosemu:Out of memory!");
100*4882a593Smuzhiyun return 0;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun M.mem_size = memSize;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun _BE_env.emulateVGA = 0;
105*4882a593Smuzhiyun _BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
106*4882a593Smuzhiyun if ((void *)_BE_env.busmem_base == NULL){
107*4882a593Smuzhiyun printf("Biosemu:Out of memory!");
108*4882a593Smuzhiyun return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun M.x86.debug = debugFlags;
111*4882a593Smuzhiyun _BE_bios_init((u32*)info->LowMem);
112*4882a593Smuzhiyun X86EMU_setupMemFuncs(&_BE_mem);
113*4882a593Smuzhiyun X86EMU_setupPioFuncs(&_BE_pio);
114*4882a593Smuzhiyun BE_setVGA(info);
115*4882a593Smuzhiyun return 1;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /****************************************************************************
119*4882a593Smuzhiyun PARAMETERS:
120*4882a593Smuzhiyun info - Pointer to VGA device information to make current
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun REMARKS:
123*4882a593Smuzhiyun This function sets the VGA BIOS functions in the emulator to point to the
124*4882a593Smuzhiyun specific VGA BIOS in use. This includes swapping the BIOS interrupt
125*4882a593Smuzhiyun vectors, BIOS image and BIOS data area to the new BIOS. This allows the
126*4882a593Smuzhiyun real mode BIOS to be swapped without resetting the entire emulator.
127*4882a593Smuzhiyun ****************************************************************************/
BE_setVGA(BE_VGAInfo * info)128*4882a593Smuzhiyun void X86API BE_setVGA(BE_VGAInfo * info)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun #ifdef __KERNEL__
132*4882a593Smuzhiyun _BE_env.vgaInfo.function = info->function;
133*4882a593Smuzhiyun _BE_env.vgaInfo.device = info->device;
134*4882a593Smuzhiyun _BE_env.vgaInfo.bus = info->bus;
135*4882a593Smuzhiyun _BE_env.vgaInfo.pcidev = info->pcidev;
136*4882a593Smuzhiyun #else
137*4882a593Smuzhiyun _BE_env.vgaInfo.pciInfo = info->pciInfo;
138*4882a593Smuzhiyun #endif
139*4882a593Smuzhiyun _BE_env.vgaInfo.BIOSImage = info->BIOSImage;
140*4882a593Smuzhiyun if (info->BIOSImage) {
141*4882a593Smuzhiyun _BE_env.biosmem_base = (ulong) info->BIOSImage;
142*4882a593Smuzhiyun _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen - 1;
143*4882a593Smuzhiyun } else {
144*4882a593Smuzhiyun _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
145*4882a593Smuzhiyun _BE_env.biosmem_limit = 0xC7FFF;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun if ((info->LowMem[0] == 0) && (info->LowMem[1] == 0) &&
148*4882a593Smuzhiyun (info->LowMem[2] == 0) && (info->LowMem[3] == 0))
149*4882a593Smuzhiyun _BE_bios_init((u32 *) info->LowMem);
150*4882a593Smuzhiyun memcpy((u8 *) M.mem_base, info->LowMem, sizeof(info->LowMem));
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /****************************************************************************
154*4882a593Smuzhiyun PARAMETERS:
155*4882a593Smuzhiyun info - Pointer to VGA device information to retrieve current
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun REMARKS:
158*4882a593Smuzhiyun This function returns the VGA BIOS functions currently active in the
159*4882a593Smuzhiyun emulator, so they can be restored at a later date.
160*4882a593Smuzhiyun ****************************************************************************/
BE_getVGA(BE_VGAInfo * info)161*4882a593Smuzhiyun void X86API BE_getVGA(BE_VGAInfo * info)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun #ifdef __KERNEL__
164*4882a593Smuzhiyun info->function = _BE_env.vgaInfo.function;
165*4882a593Smuzhiyun info->device = _BE_env.vgaInfo.device;
166*4882a593Smuzhiyun info->bus = _BE_env.vgaInfo.bus;
167*4882a593Smuzhiyun info->pcidev = _BE_env.vgaInfo.pcidev;
168*4882a593Smuzhiyun #else
169*4882a593Smuzhiyun info->pciInfo = _BE_env.vgaInfo.pciInfo;
170*4882a593Smuzhiyun #endif
171*4882a593Smuzhiyun info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
172*4882a593Smuzhiyun memcpy(info->LowMem, (u8 *) M.mem_base, sizeof(info->LowMem));
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /****************************************************************************
176*4882a593Smuzhiyun PARAMETERS:
177*4882a593Smuzhiyun r_seg - Segment for pointer to convert
178*4882a593Smuzhiyun r_off - Offset for pointer to convert
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun REMARKS:
181*4882a593Smuzhiyun This function maps a real mode pointer in the emulator memory to a protected
182*4882a593Smuzhiyun mode pointer that can be used to directly access the memory.
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun NOTE: The memory is *always* in little endian format, son on non-x86
185*4882a593Smuzhiyun systems you will need to do endian translations to access this
186*4882a593Smuzhiyun memory.
187*4882a593Smuzhiyun ****************************************************************************/
BE_mapRealPointer(uint r_seg,uint r_off)188*4882a593Smuzhiyun void *X86API BE_mapRealPointer(uint r_seg, uint r_off)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun u32 addr = ((u32) r_seg << 4) + r_off;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
193*4882a593Smuzhiyun return (void *)(_BE_env.biosmem_base + addr - 0xC0000);
194*4882a593Smuzhiyun } else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
195*4882a593Smuzhiyun return (void *)(_BE_env.busmem_base + addr - 0xA0000);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun return (void *)(M.mem_base + addr);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun /****************************************************************************
201*4882a593Smuzhiyun PARAMETERS:
202*4882a593Smuzhiyun len - Return the length of the VESA buffer
203*4882a593Smuzhiyun rseg - Place to store VESA buffer segment
204*4882a593Smuzhiyun roff - Place to store VESA buffer offset
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun REMARKS:
207*4882a593Smuzhiyun This function returns the address of the VESA transfer buffer in real
208*4882a593Smuzhiyun _BE_piomode emulator memory. The VESA transfer buffer is always 1024 bytes long,
209*4882a593Smuzhiyun and located at 15Kb into the start of the real mode memory (16Kb is where
210*4882a593Smuzhiyun we put the real mode code we execute for issuing interrupts).
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun NOTE: The memory is *always* in little endian format, son on non-x86
213*4882a593Smuzhiyun systems you will need to do endian translations to access this
214*4882a593Smuzhiyun memory.
215*4882a593Smuzhiyun ****************************************************************************/
BE_getVESABuf(uint * len,uint * rseg,uint * roff)216*4882a593Smuzhiyun void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun *len = 1024;
219*4882a593Smuzhiyun *rseg = SEG(0x03C00);
220*4882a593Smuzhiyun *roff = OFF(0x03C00);
221*4882a593Smuzhiyun return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /****************************************************************************
225*4882a593Smuzhiyun REMARKS:
226*4882a593Smuzhiyun Cleans up and exits the emulator.
227*4882a593Smuzhiyun ****************************************************************************/
BE_exit(void)228*4882a593Smuzhiyun void X86API BE_exit(void)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun free(M.mem_base);
231*4882a593Smuzhiyun free((void *)_BE_env.busmem_base);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /****************************************************************************
235*4882a593Smuzhiyun PARAMETERS:
236*4882a593Smuzhiyun seg - Segment of code to call
237*4882a593Smuzhiyun off - Offset of code to call
238*4882a593Smuzhiyun regs - Real mode registers to load
239*4882a593Smuzhiyun sregs - Real mode segment registers to load
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun REMARKS:
242*4882a593Smuzhiyun This functions calls a real mode far function at the specified address,
243*4882a593Smuzhiyun and loads all the x86 registers from the passed in registers structure.
244*4882a593Smuzhiyun On exit the registers returned from the call are returned in the same
245*4882a593Smuzhiyun structures.
246*4882a593Smuzhiyun ****************************************************************************/
BE_callRealMode(uint seg,uint off,RMREGS * regs,RMSREGS * sregs)247*4882a593Smuzhiyun void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun M.x86.R_EAX = regs->e.eax;
250*4882a593Smuzhiyun M.x86.R_EBX = regs->e.ebx;
251*4882a593Smuzhiyun M.x86.R_ECX = regs->e.ecx;
252*4882a593Smuzhiyun M.x86.R_EDX = regs->e.edx;
253*4882a593Smuzhiyun M.x86.R_ESI = regs->e.esi;
254*4882a593Smuzhiyun M.x86.R_EDI = regs->e.edi;
255*4882a593Smuzhiyun M.x86.R_DS = sregs->ds;
256*4882a593Smuzhiyun M.x86.R_ES = sregs->es;
257*4882a593Smuzhiyun M.x86.R_FS = sregs->fs;
258*4882a593Smuzhiyun M.x86.R_GS = sregs->gs;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4000] = 0x9A;
261*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4001] = (u8) off;
262*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4002] = (u8) (off >> 8);
263*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4003] = (u8) seg;
264*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4004] = (u8) (seg >> 8);
265*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4005] = 0xF1; /* Illegal op-code */
266*4882a593Smuzhiyun M.x86.R_CS = SEG(0x04000);
267*4882a593Smuzhiyun M.x86.R_IP = OFF(0x04000);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun M.x86.R_SS = SEG(M.mem_size - 2);
270*4882a593Smuzhiyun M.x86.R_SP = OFF(M.mem_size - 2) + 2;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun X86EMU_exec();
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun regs->e.cflag = M.x86.R_EFLG & F_CF;
275*4882a593Smuzhiyun regs->e.eax = M.x86.R_EAX;
276*4882a593Smuzhiyun regs->e.ebx = M.x86.R_EBX;
277*4882a593Smuzhiyun regs->e.ecx = M.x86.R_ECX;
278*4882a593Smuzhiyun regs->e.edx = M.x86.R_EDX;
279*4882a593Smuzhiyun regs->e.esi = M.x86.R_ESI;
280*4882a593Smuzhiyun regs->e.edi = M.x86.R_EDI;
281*4882a593Smuzhiyun sregs->ds = M.x86.R_DS;
282*4882a593Smuzhiyun sregs->es = M.x86.R_ES;
283*4882a593Smuzhiyun sregs->fs = M.x86.R_FS;
284*4882a593Smuzhiyun sregs->gs = M.x86.R_GS;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /****************************************************************************
288*4882a593Smuzhiyun PARAMETERS:
289*4882a593Smuzhiyun intno - Interrupt number to execute
290*4882a593Smuzhiyun in - Real mode registers to load
291*4882a593Smuzhiyun out - Place to store resulting real mode registers
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun REMARKS:
294*4882a593Smuzhiyun This functions calls a real mode interrupt function at the specified address,
295*4882a593Smuzhiyun and loads all the x86 registers from the passed in registers structure.
296*4882a593Smuzhiyun On exit the registers returned from the call are returned in out stucture.
297*4882a593Smuzhiyun ****************************************************************************/
BE_int86(int intno,RMREGS * in,RMREGS * out)298*4882a593Smuzhiyun int X86API BE_int86(int intno, RMREGS * in, RMREGS * out)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun M.x86.R_EAX = in->e.eax;
301*4882a593Smuzhiyun M.x86.R_EBX = in->e.ebx;
302*4882a593Smuzhiyun M.x86.R_ECX = in->e.ecx;
303*4882a593Smuzhiyun M.x86.R_EDX = in->e.edx;
304*4882a593Smuzhiyun M.x86.R_ESI = in->e.esi;
305*4882a593Smuzhiyun M.x86.R_EDI = in->e.edi;
306*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4000] = 0xCD;
307*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4001] = (u8) intno;
308*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4002] = 0xF1;
309*4882a593Smuzhiyun M.x86.R_CS = SEG(0x04000);
310*4882a593Smuzhiyun M.x86.R_IP = OFF(0x04000);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun M.x86.R_SS = SEG(M.mem_size - 1);
313*4882a593Smuzhiyun M.x86.R_SP = OFF(M.mem_size - 1) - 1;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun X86EMU_exec();
316*4882a593Smuzhiyun out->e.cflag = M.x86.R_EFLG & F_CF;
317*4882a593Smuzhiyun out->e.eax = M.x86.R_EAX;
318*4882a593Smuzhiyun out->e.ebx = M.x86.R_EBX;
319*4882a593Smuzhiyun out->e.ecx = M.x86.R_ECX;
320*4882a593Smuzhiyun out->e.edx = M.x86.R_EDX;
321*4882a593Smuzhiyun out->e.esi = M.x86.R_ESI;
322*4882a593Smuzhiyun out->e.edi = M.x86.R_EDI;
323*4882a593Smuzhiyun return out->x.ax;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /****************************************************************************
327*4882a593Smuzhiyun PARAMETERS:
328*4882a593Smuzhiyun intno - Interrupt number to execute
329*4882a593Smuzhiyun in - Real mode registers to load
330*4882a593Smuzhiyun out - Place to store resulting real mode registers
331*4882a593Smuzhiyun sregs - Real mode segment registers to load
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun REMARKS:
334*4882a593Smuzhiyun This functions calls a real mode interrupt function at the specified address,
335*4882a593Smuzhiyun and loads all the x86 registers from the passed in registers structure.
336*4882a593Smuzhiyun On exit the registers returned from the call are returned in out stucture.
337*4882a593Smuzhiyun ****************************************************************************/
BE_int86x(int intno,RMREGS * in,RMREGS * out,RMSREGS * sregs)338*4882a593Smuzhiyun int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out, RMSREGS * sregs)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun M.x86.R_EAX = in->e.eax;
341*4882a593Smuzhiyun M.x86.R_EBX = in->e.ebx;
342*4882a593Smuzhiyun M.x86.R_ECX = in->e.ecx;
343*4882a593Smuzhiyun M.x86.R_EDX = in->e.edx;
344*4882a593Smuzhiyun M.x86.R_ESI = in->e.esi;
345*4882a593Smuzhiyun M.x86.R_EDI = in->e.edi;
346*4882a593Smuzhiyun M.x86.R_DS = sregs->ds;
347*4882a593Smuzhiyun M.x86.R_ES = sregs->es;
348*4882a593Smuzhiyun M.x86.R_FS = sregs->fs;
349*4882a593Smuzhiyun M.x86.R_GS = sregs->gs;
350*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4000] = 0xCD;
351*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4001] = (u8) intno;
352*4882a593Smuzhiyun ((u8 *) M.mem_base)[0x4002] = 0xF1;
353*4882a593Smuzhiyun M.x86.R_CS = SEG(0x04000);
354*4882a593Smuzhiyun M.x86.R_IP = OFF(0x04000);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun M.x86.R_SS = SEG(M.mem_size - 1);
357*4882a593Smuzhiyun M.x86.R_SP = OFF(M.mem_size - 1) - 1;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun X86EMU_exec();
360*4882a593Smuzhiyun out->e.cflag = M.x86.R_EFLG & F_CF;
361*4882a593Smuzhiyun out->e.eax = M.x86.R_EAX;
362*4882a593Smuzhiyun out->e.ebx = M.x86.R_EBX;
363*4882a593Smuzhiyun out->e.ecx = M.x86.R_ECX;
364*4882a593Smuzhiyun out->e.edx = M.x86.R_EDX;
365*4882a593Smuzhiyun out->e.esi = M.x86.R_ESI;
366*4882a593Smuzhiyun out->e.edi = M.x86.R_EDI;
367*4882a593Smuzhiyun sregs->ds = M.x86.R_DS;
368*4882a593Smuzhiyun sregs->es = M.x86.R_ES;
369*4882a593Smuzhiyun sregs->fs = M.x86.R_FS;
370*4882a593Smuzhiyun sregs->gs = M.x86.R_GS;
371*4882a593Smuzhiyun return out->x.ax;
372*4882a593Smuzhiyun }
373