blob: e550c459d2f876d70dbd8a0f426fa89256c5956b [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/****************************************************************************
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
Martin Roth63373ed2013-07-08 16:24:19 -060038* uses these functions will most likely be overridden by the
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000039* user library.
40*
41****************************************************************************/
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000042
Uwe Hermann01ce6012010-03-05 10:03:50 +000043#include <arch/io.h>
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000044#include <x86emu/x86emu.h>
45#include <x86emu/regs.h>
Stefan Reinauer91f14232012-12-07 16:55:12 -080046#include <device/oprom/include/io.h>
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000047#include "debug.h"
48#include "prim_ops.h"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000049
50#ifdef IN_MODULE
51#include "xf86_ansic.h"
52#else
53#include <string.h>
54#endif
55/*------------------------- Global Variables ------------------------------*/
56
57X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
58X86EMU_intrFuncs _X86EMU_intrTab[256];
59
60/*----------------------------- Implementation ----------------------------*/
61
62/* compute a pointer. This replaces code scattered all over the place! */
Stefan Reinauer7110d402009-11-03 14:59:43 +000063static u8 *mem_ptr(u32 addr, int size)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000064{
65 u8 *retaddr = 0;
66
67 if (addr > M.mem_size - size) {
Uwe Hermann01ce6012010-03-05 10:03:50 +000068 DB(printf("mem_ptr: address %#x out of range!\n", addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000069 HALT_SYS();
70 }
71 if (addr < 0x200) {
Uwe Hermann01ce6012010-03-05 10:03:50 +000072 //printf("%x:%x updating int vector 0x%x\n",
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000073 // M.x86.R_CS, M.x86.R_IP, addr >> 2);
74 }
75 retaddr = (u8 *) (M.mem_base + addr);
76
77 return retaddr;
78}
79
80/****************************************************************************
81PARAMETERS:
82addr - Emulator memory address to read
83
84RETURNS:
85Byte value read from emulator memory.
86
87REMARKS:
Stefan Reinauer14e22772010-04-27 06:56:47 +000088Reads a byte value from the emulator memory.
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000089****************************************************************************/
90u8 X86API rdb(u32 addr)
91{
92 u8 val;
93 u8 *ptr;
94
95 ptr = mem_ptr(addr, 1);
96
97 val = *ptr;
98 DB(if (DEBUG_MEM_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +000099 printf("%#08x 1 -> %#x\n", addr, val);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000100 return val;
101}
102
103/****************************************************************************
104PARAMETERS:
105addr - Emulator memory address to read
106
107RETURNS:
108Word value read from emulator memory.
109
110REMARKS:
111Reads a word value from the emulator memory.
112****************************************************************************/
113u16 X86API rdw(u32 addr)
114{
115 u16 val = 0;
116 u8 *ptr;
117
118 ptr = mem_ptr(addr, 2);
119 val = *(u16 *) (ptr);
120
121 DB(if (DEBUG_MEM_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000122 printf("%#08x 2 -> %#x\n", addr, val);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000123 return val;
124}
125
126/****************************************************************************
127PARAMETERS:
128addr - Emulator memory address to read
129
130RETURNS:
131Long value read from emulator memory.
132REMARKS:
Stefan Reinauer14e22772010-04-27 06:56:47 +0000133Reads a long value from the emulator memory.
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000134****************************************************************************/
135u32 X86API rdl(u32 addr)
136{
137 u32 val = 0;
138 u8 *ptr;
139
140 ptr = mem_ptr(addr, 4);
141 val = *(u32 *) (ptr);
142
143 DB(if (DEBUG_MEM_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000144 printf("%#08x 4 -> %#x\n", addr, val);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000145 return val;
146}
147
148/****************************************************************************
149PARAMETERS:
150addr - Emulator memory address to read
151val - Value to store
152
153REMARKS:
154Writes a byte value to emulator memory.
155****************************************************************************/
156void X86API wrb(u32 addr, u8 val)
157{
158 u8 *ptr;
159
160 ptr = mem_ptr(addr, 1);
161 *(u8 *) (ptr) = val;
162
163 DB(if (DEBUG_MEM_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000164 printf("%#08x 1 <- %#x\n", addr, val);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000165}
166
167/****************************************************************************
168PARAMETERS:
169addr - Emulator memory address to read
170val - Value to store
171
172REMARKS:
173Writes a word value to emulator memory.
174****************************************************************************/
175void X86API wrw(u32 addr, u16 val)
176{
177 u8 *ptr;
178
179 ptr = mem_ptr(addr, 2);
180 *(u16 *) (ptr) = val;
181
182 DB(if (DEBUG_MEM_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000183 printf("%#08x 2 <- %#x\n", addr, val);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000184}
185
186/****************************************************************************
187PARAMETERS:
188addr - Emulator memory address to read
189val - Value to store
190
191REMARKS:
Stefan Reinauer14e22772010-04-27 06:56:47 +0000192Writes a long value to emulator memory.
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000193****************************************************************************/
194void X86API wrl(u32 addr, u32 val)
195{
196 u8 *ptr;
197
198 ptr = mem_ptr(addr, 4);
199 *(u32 *) (ptr) = val;
200
201 DB(if (DEBUG_MEM_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000202 printf("%#08x 4 <- %#x\n", addr, val);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000203
204
205}
206
207/****************************************************************************
208PARAMETERS:
209addr - PIO address to read
210RETURN:
2110
212REMARKS:
213Default PIO byte read function. Doesn't perform real inb.
214****************************************************************************/
215static u8 X86API p_inb(X86EMU_pioAddr addr)
216{
217 DB(if (DEBUG_IO_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000218 printf("inb %#04x \n", addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000219 return inb(addr);
220}
221
222/****************************************************************************
223PARAMETERS:
224addr - PIO address to read
225RETURN:
2260
227REMARKS:
228Default PIO word read function. Doesn't perform real inw.
229****************************************************************************/
230static u16 X86API p_inw(X86EMU_pioAddr addr)
231{
232 DB(if (DEBUG_IO_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000233 printf("inw %#04x \n", addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000234 return inw(addr);
235}
236
237/****************************************************************************
238PARAMETERS:
239addr - PIO address to read
240RETURN:
2410
242REMARKS:
243Default PIO long read function. Doesn't perform real inl.
244****************************************************************************/
245static u32 X86API p_inl(X86EMU_pioAddr addr)
246{
247 DB(if (DEBUG_IO_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000248 printf("inl %#04x \n", addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000249 return inl(addr);
250}
251
252/****************************************************************************
253PARAMETERS:
254addr - PIO address to write
255val - Value to store
256REMARKS:
257Default PIO byte write function. Doesn't perform real outb.
258****************************************************************************/
259static void X86API p_outb(X86EMU_pioAddr addr, u8 val)
260{
261 DB(if (DEBUG_IO_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000262 printf("outb %#02x -> %#04x \n", val, addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000263 outb(val, addr);
264 return;
265}
266
267/****************************************************************************
268PARAMETERS:
269addr - PIO address to write
270val - Value to store
271REMARKS:
272Default PIO word write function. Doesn't perform real outw.
273****************************************************************************/
274static void X86API p_outw(X86EMU_pioAddr addr, u16 val)
275{
276 DB(if (DEBUG_IO_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000277 printf("outw %#04x -> %#04x \n", val, addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000278 outw(val, addr);
279 return;
280}
281
282/****************************************************************************
283PARAMETERS:
284addr - PIO address to write
285val - Value to store
286REMARKS:
287Default PIO ;ong write function. Doesn't perform real outl.
288****************************************************************************/
289static void X86API p_outl(X86EMU_pioAddr addr, u32 val)
290{
291 DB(if (DEBUG_IO_TRACE())
Uwe Hermann01ce6012010-03-05 10:03:50 +0000292 printf("outl %#08x -> %#04x \n", val, addr);)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000293
294 outl(val, addr);
295 return;
296}
297
298/*------------------------- Global Variables ------------------------------*/
299
300u8(X86APIP sys_rdb) (u32 addr) = rdb;
301u16(X86APIP sys_rdw) (u32 addr) = rdw;
302u32(X86APIP sys_rdl) (u32 addr) = rdl;
303void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
304void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
305void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
306u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
307u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
308u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
309void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
310void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
311void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
312
313/*----------------------------- Setup -------------------------------------*/
314
315/****************************************************************************
316PARAMETERS:
317funcs - New memory function pointers to make active
318
319REMARKS:
320This function is used to set the pointers to functions which access
321memory space, allowing the user application to override these functions
322and hook them out as necessary for their application.
323****************************************************************************/
324void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
325{
326 sys_rdb = funcs->rdb;
327 sys_rdw = funcs->rdw;
328 sys_rdl = funcs->rdl;
329 sys_wrb = funcs->wrb;
330 sys_wrw = funcs->wrw;
331 sys_wrl = funcs->wrl;
332}
333
334/****************************************************************************
335PARAMETERS:
336funcs - New programmed I/O function pointers to make active
337
338REMARKS:
339This function is used to set the pointers to functions which access
340I/O space, allowing the user application to override these functions
341and hook them out as necessary for their application.
342****************************************************************************/
343void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
344{
345 sys_inb = funcs->inb;
346 sys_inw = funcs->inw;
347 sys_inl = funcs->inl;
348 sys_outb = funcs->outb;
349 sys_outw = funcs->outw;
350 sys_outl = funcs->outl;
351}
352
353/****************************************************************************
354PARAMETERS:
355funcs - New interrupt vector table to make active
356
357REMARKS:
358This function is used to set the pointers to functions which handle
359interrupt processing in the emulator, allowing the user application to
360hook interrupts as necessary for their application. Any interrupts that
361are not hooked by the user application, and reflected and handled internally
362in the emulator via the interrupt vector table. This allows the application
363to get control when the code being emulated executes specific software
364interrupts.
365****************************************************************************/
366void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
367{
368 int i;
369
370 for (i = 0; i < 256; i++)
371 _X86EMU_intrTab[i] = NULL;
372 if (funcs) {
373 for (i = 0; i < 256; i++)
374 _X86EMU_intrTab[i] = funcs[i];
375 }
376}
377
378/****************************************************************************
379PARAMETERS:
380int - New software interrupt to prepare for
381
382REMARKS:
Martin Roth63373ed2013-07-08 16:24:19 -0600383This function is used to set up the emulator state to execute a software
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000384interrupt. This can be used by the user application code to allow an
385interrupt to be hooked, examined and then reflected back to the emulator
386so that the code in the emulator will continue processing the software
387interrupt as per normal. This essentially allows system code to actively
388hook and handle certain software interrupts as necessary.
389****************************************************************************/
390void X86EMU_prepareForInt(int num)
391{
392 push_word((u16) M.x86.R_FLG);
393 CLEAR_FLAG(F_IF);
394 CLEAR_FLAG(F_TF);
395 push_word(M.x86.R_CS);
396 M.x86.R_CS = mem_access_word(num * 4 + 2);
397 push_word(M.x86.R_IP);
398 M.x86.R_IP = mem_access_word(num * 4);
399 M.x86.intr = 0;
400}
401
402void X86EMU_setMemBase(void *base, size_t size)
403{
404 M.mem_base = (unsigned long) base;
405 M.mem_size = size;
406}