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