1/****************************************************************************
2*
3*						Realmode X86 Emulator Library
4*
5*            	Copyright (C) 1996-1999 SciTech Software, Inc.
6* 				     Copyright (C) David Mosberger-Tang
7* 					   Copyright (C) 1999 Egbert Eich
8*
9*  ========================================================================
10*
11*  Permission to use, copy, modify, distribute, and sell this software and
12*  its documentation for any purpose is hereby granted without fee,
13*  provided that the above copyright notice appear in all copies and that
14*  both that copyright notice and this permission notice appear in
15*  supporting documentation, and that the name of the authors not be used
16*  in advertising or publicity pertaining to distribution of the software
17*  without specific, written prior permission.  The authors makes no
18*  representations about the suitability of this software for any purpose.
19*  It is provided "as is" without express or implied warranty.
20*
21*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27*  PERFORMANCE OF THIS SOFTWARE.
28*
29*  ========================================================================
30*
31* Language:		ANSI C
32* Environment:	Any
33* Developer:    Kendall Bennett
34*
35* Description:  This file includes subroutines which are related to
36*				programmed I/O and memory access. Included in this module
37*				are default functions with limited usefulness. For real
38*				uses these functions will most likely be overriden by the
39*				user library.
40*
41****************************************************************************/
42
43#include "x86emu.h"
44#include "x86emu/x86emui.h"
45#include "x86emu/regs.h"
46#include "x86emu/debug.h"
47#include "x86emu/prim_ops.h"
48#ifndef NO_SYS_HEADERS
49#include <string.h>
50#endif
51/*------------------------- Global Variables ------------------------------*/
52
53X86EMU_sysEnv		_X86EMU_env;		/* Global emulator machine state */
54X86EMU_intrFuncs	_X86EMU_intrTab[256];
55
56
57/****************************************************************************
58PARAMETERS:
59addr	- Emulator memory address to read
60
61RETURNS:
62Byte value read from emulator memory.
63
64REMARKS:
65Reads a byte value from the emulator memory.
66****************************************************************************/
67u8 X86API rdb(
68    u32 addr)
69{
70	u8 val;
71
72	if (addr > M.mem_size - 1) {
73		DB(printk("mem_read: address %#lx out of range!\n", addr);)
74		HALT_SYS();
75		}
76	val = *(u8*)(M.mem_base + addr);
77DB(	if (DEBUG_MEM_TRACE())
78		printk("%#08x 1 -> %#x\n", addr, val);)
79	return val;
80}
81
82/****************************************************************************
83PARAMETERS:
84addr	- Emulator memory address to read
85
86RETURNS:
87Word value read from emulator memory.
88
89REMARKS:
90Reads a word value from the emulator memory.
91****************************************************************************/
92u16 X86API rdw(
93	u32 addr)
94{
95	u16 val = 0;
96
97	if (addr > M.mem_size - 2) {
98		DB(printk("mem_read: address %#lx out of range!\n", addr);)
99		HALT_SYS();
100		}
101#ifdef __BIG_ENDIAN__
102	if (addr & 0x1) {
103		val = (*(u8*)(M.mem_base + addr) |
104			  (*(u8*)(M.mem_base + addr + 1) << 8));
105		}
106	else
107#endif
108		val = *(u16*)(M.mem_base + addr);
109		DB(	if (DEBUG_MEM_TRACE())
110		printk("%#08x 2 -> %#x\n", addr, val);)
111    return val;
112}
113
114/****************************************************************************
115PARAMETERS:
116addr	- Emulator memory address to read
117
118RETURNS:
119Long value read from emulator memory.
120REMARKS:
121Reads a long value from the emulator memory.
122****************************************************************************/
123u32 X86API rdl(
124	u32 addr)
125{
126	u32 val = 0;
127
128	if (addr > M.mem_size - 4) {
129		DB(printk("mem_read: address %#lx out of range!\n", addr);)
130		HALT_SYS();
131		}
132#ifdef __BIG_ENDIAN__
133	if (addr & 0x3) {
134		val = (*(u8*)(M.mem_base + addr + 0) |
135			  (*(u8*)(M.mem_base + addr + 1) << 8) |
136			  (*(u8*)(M.mem_base + addr + 2) << 16) |
137			  (*(u8*)(M.mem_base + addr + 3) << 24));
138		}
139	else
140#endif
141		val = *(u32*)(M.mem_base + addr);
142DB(	if (DEBUG_MEM_TRACE())
143		printk("%#08x 4 -> %#x\n", addr, val);)
144	return val;
145}
146
147/****************************************************************************
148PARAMETERS:
149addr	- Emulator memory address to read
150val		- Value to store
151
152REMARKS:
153Writes a byte value to emulator memory.
154****************************************************************************/
155void X86API wrb(
156	u32 addr,
157	u8 val)
158{
159DB(	if (DEBUG_MEM_TRACE())
160		printk("%#08x 1 <- %#x\n", addr, val);)
161    if (addr > M.mem_size - 1) {
162		DB(printk("mem_write: address %#lx out of range!\n", addr);)
163		HALT_SYS();
164		}
165	*(u8*)(M.mem_base + addr) = val;
166}
167
168/****************************************************************************
169PARAMETERS:
170addr	- Emulator memory address to read
171val		- Value to store
172
173REMARKS:
174Writes a word value to emulator memory.
175****************************************************************************/
176void X86API wrw(
177	u32 addr,
178	u16 val)
179{
180DB(	if (DEBUG_MEM_TRACE())
181		printk("%#08x 2 <- %#x\n", addr, val);)
182	if (addr > M.mem_size - 2) {
183		DB(printk("mem_write: address %#lx out of range!\n", addr);)
184		HALT_SYS();
185		}
186#ifdef __BIG_ENDIAN__
187	if (addr & 0x1) {
188		*(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
189		*(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
190		}
191	else
192#endif
193	 *(u16*)(M.mem_base + addr) = val;
194}
195
196/****************************************************************************
197PARAMETERS:
198addr	- Emulator memory address to read
199val		- Value to store
200
201REMARKS:
202Writes a long value to emulator memory.
203****************************************************************************/
204void X86API wrl(
205	u32 addr,
206	u32 val)
207{
208DB(	if (DEBUG_MEM_TRACE())
209		printk("%#08x 4 <- %#x\n", addr, val);)
210	if (addr > M.mem_size - 4) {
211		DB(printk("mem_write: address %#lx out of range!\n", addr);)
212		HALT_SYS();
213        return;
214		}
215#ifdef __BIG_ENDIAN__
216	if (addr & 0x1) {
217		*(u8*)(M.mem_base + addr + 0) = (val >>  0) & 0xff;
218		*(u8*)(M.mem_base + addr + 1) = (val >>  8) & 0xff;
219		*(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
220		*(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
221		}
222	else
223#endif
224	 *(u32*)(M.mem_base + addr) = val;
225}
226
227/****************************************************************************
228PARAMETERS:
229addr	- PIO address to read
230RETURN:
2310
232REMARKS:
233Default PIO byte read function. Doesn't perform real inb.
234****************************************************************************/
235static u8 X86API p_inb(
236	X86EMU_pioAddr addr)
237{
238DB(	if (DEBUG_IO_TRACE())
239		printk("inb %#04x \n", addr);)
240	return 0;
241}
242
243/****************************************************************************
244PARAMETERS:
245addr	- PIO address to read
246RETURN:
2470
248REMARKS:
249Default PIO word read function. Doesn't perform real inw.
250****************************************************************************/
251static u16 X86API p_inw(
252	X86EMU_pioAddr addr)
253{
254DB(	if (DEBUG_IO_TRACE())
255		printk("inw %#04x \n", addr);)
256	return 0;
257}
258
259/****************************************************************************
260PARAMETERS:
261addr	- PIO address to read
262RETURN:
2630
264REMARKS:
265Default PIO long read function. Doesn't perform real inl.
266****************************************************************************/
267static u32 X86API p_inl(
268	X86EMU_pioAddr addr)
269{
270DB(	if (DEBUG_IO_TRACE())
271		printk("inl %#04x \n", addr);)
272	return 0;
273}
274
275/****************************************************************************
276PARAMETERS:
277addr	- PIO address to write
278val     - Value to store
279REMARKS:
280Default PIO byte write function. Doesn't perform real outb.
281****************************************************************************/
282static void X86API p_outb(
283	X86EMU_pioAddr addr,
284	u8 val)
285{
286DB(	if (DEBUG_IO_TRACE())
287		printk("outb %#02x -> %#04x \n", val, addr);)
288    return;
289}
290
291/****************************************************************************
292PARAMETERS:
293addr	- PIO address to write
294val     - Value to store
295REMARKS:
296Default PIO word write function. Doesn't perform real outw.
297****************************************************************************/
298static void X86API p_outw(
299	X86EMU_pioAddr addr,
300	u16 val)
301{
302DB(	if (DEBUG_IO_TRACE())
303		printk("outw %#04x -> %#04x \n", val, addr);)
304	return;
305}
306
307/****************************************************************************
308PARAMETERS:
309addr	- PIO address to write
310val     - Value to store
311REMARKS:
312Default PIO ;ong write function. Doesn't perform real outl.
313****************************************************************************/
314static void X86API p_outl(
315	X86EMU_pioAddr addr,
316	u32 val)
317{
318DB(	if (DEBUG_IO_TRACE())
319		printk("outl %#08x -> %#04x \n", val, addr);)
320    return;
321}
322
323/*------------------------- Global Variables ------------------------------*/
324
325u8  	(X86APIP sys_rdb)(u32 addr) 			            = rdb;
326u16 	(X86APIP sys_rdw)(u32 addr) 			            = rdw;
327u32 	(X86APIP sys_rdl)(u32 addr) 			            = rdl;
328void 	(X86APIP sys_wrb)(u32 addr,u8 val) 		            = wrb;
329void 	(X86APIP sys_wrw)(u32 addr,u16 val) 	            = wrw;
330void 	(X86APIP sys_wrl)(u32 addr,u32 val) 	            = wrl;
331u8  	(X86APIP sys_inb)(X86EMU_pioAddr addr)	            = p_inb;
332u16 	(X86APIP sys_inw)(X86EMU_pioAddr addr)	            = p_inw;
333u32 	(X86APIP sys_inl)(X86EMU_pioAddr addr)              = p_inl;
334void 	(X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) 	= p_outb;
335void 	(X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val)	= p_outw;
336void 	(X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val)	= p_outl;
337
338/*----------------------------- Setup -------------------------------------*/
339
340/****************************************************************************
341PARAMETERS:
342funcs	- New memory function pointers to make active
343
344REMARKS:
345This function is used to set the pointers to functions which access
346memory space, allowing the user application to override these functions
347and hook them out as necessary for their application.
348****************************************************************************/
349void X86EMU_setupMemFuncs(
350	X86EMU_memFuncs *funcs)
351{
352    sys_rdb = funcs->rdb;
353    sys_rdw = funcs->rdw;
354    sys_rdl = funcs->rdl;
355    sys_wrb = funcs->wrb;
356    sys_wrw = funcs->wrw;
357    sys_wrl = funcs->wrl;
358}
359
360/****************************************************************************
361PARAMETERS:
362funcs	- New programmed I/O function pointers to make active
363
364REMARKS:
365This function is used to set the pointers to functions which access
366I/O space, allowing the user application to override these functions
367and hook them out as necessary for their application.
368****************************************************************************/
369void X86EMU_setupPioFuncs(
370	X86EMU_pioFuncs *funcs)
371{
372    sys_inb = funcs->inb;
373    sys_inw = funcs->inw;
374    sys_inl = funcs->inl;
375    sys_outb = funcs->outb;
376    sys_outw = funcs->outw;
377    sys_outl = funcs->outl;
378}
379
380/****************************************************************************
381PARAMETERS:
382funcs	- New interrupt vector table to make active
383
384REMARKS:
385This function is used to set the pointers to functions which handle
386interrupt processing in the emulator, allowing the user application to
387hook interrupts as necessary for their application. Any interrupts that
388are not hooked by the user application, and reflected and handled internally
389in the emulator via the interrupt vector table. This allows the application
390to get control when the code being emulated executes specific software
391interrupts.
392****************************************************************************/
393void X86EMU_setupIntrFuncs(
394	X86EMU_intrFuncs funcs[])
395{
396    int i;
397
398	for (i=0; i < 256; i++)
399		_X86EMU_intrTab[i] = NULL;
400	if (funcs) {
401		for (i = 0; i < 256; i++)
402			_X86EMU_intrTab[i] = funcs[i];
403		}
404}
405
406/****************************************************************************
407PARAMETERS:
408int	- New software interrupt to prepare for
409
410REMARKS:
411This function is used to set up the emulator state to exceute a software
412interrupt. This can be used by the user application code to allow an
413interrupt to be hooked, examined and then reflected back to the emulator
414so that the code in the emulator will continue processing the software
415interrupt as per normal. This essentially allows system code to actively
416hook and handle certain software interrupts as necessary.
417****************************************************************************/
418void X86EMU_prepareForInt(
419	int num)
420{
421    push_word((u16)M.x86.R_FLG);
422    CLEAR_FLAG(F_IF);
423    CLEAR_FLAG(F_TF);
424    push_word(M.x86.R_CS);
425    M.x86.R_CS = mem_access_word(num * 4 + 2);
426    push_word(M.x86.R_IP);
427    M.x86.R_IP = mem_access_word(num * 4);
428	M.x86.intr = 0;
429}
430