GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / x86emu / sys.c
blobf80d75506353a1547d45f3a68bd7edb102d1cd54
1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1996-1999 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
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.
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.
29 * ========================================================================
31 * Language: ANSI C
32 * Environment: Any
33 * Developer: Kendall Bennett
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.
41 ****************************************************************************/
42 /* $XFree86: xc/extras/x86emu/src/x86emu/sys.c,v 1.5 2000/08/23 22:10:01 tsi Exp $ */
44 #include "x86emu.h"
45 #include "x86emu/regs.h"
46 #include "x86emu/debug.h"
47 #include "x86emu/prim_ops.h"
48 #ifdef IN_MODULE
49 #include "xf86_ansic.h"
50 #else
51 /*#include <string.h> */
52 #define NULL 0
53 #endif
54 /*------------------------- Global Variables ------------------------------*/
56 X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
57 X86EMU_intrFuncs _X86EMU_intrTab[256];
59 /*----------------------------- Implementation ----------------------------*/
60 #if defined(__alpha__) || defined(__alpha)
61 /* to cope with broken egcs-1.1.2 :-(((( */
64 * inline functions to do unaligned accesses
65 * from linux/include/asm-alpha/unaligned.h
69 * EGCS 1.1 knows about arbitrary unaligned loads. Define some
70 * packed structures to talk about such things with.
73 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
74 struct __una_u64 { unsigned long x __attribute__((packed)); };
75 struct __una_u32 { unsigned int x __attribute__((packed)); };
76 struct __una_u16 { unsigned short x __attribute__((packed)); };
77 #endif
79 static __inline__ unsigned long ldq_u(unsigned long * r11)
81 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
82 const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
83 return ptr->x;
84 #else
85 unsigned long r1,r2;
86 __asm__("ldq_u %0,%3\n\t"
87 "ldq_u %1,%4\n\t"
88 "extql %0,%2,%0\n\t"
89 "extqh %1,%2,%1"
90 :"=&r" (r1), "=&r" (r2)
91 :"r" (r11),
92 "m" (*r11),
93 "m" (*(const unsigned long *)(7+(char *) r11)));
94 return r1 | r2;
95 #endif
98 static __inline__ unsigned long ldl_u(unsigned int * r11)
100 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
101 const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
102 return ptr->x;
103 #else
104 unsigned long r1,r2;
105 __asm__("ldq_u %0,%3\n\t"
106 "ldq_u %1,%4\n\t"
107 "extll %0,%2,%0\n\t"
108 "extlh %1,%2,%1"
109 :"=&r" (r1), "=&r" (r2)
110 :"r" (r11),
111 "m" (*r11),
112 "m" (*(const unsigned long *)(3+(char *) r11)));
113 return r1 | r2;
114 #endif
117 static __inline__ unsigned long ldw_u(unsigned short * r11)
119 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
120 const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
121 return ptr->x;
122 #else
123 unsigned long r1,r2;
124 __asm__("ldq_u %0,%3\n\t"
125 "ldq_u %1,%4\n\t"
126 "extwl %0,%2,%0\n\t"
127 "extwh %1,%2,%1"
128 :"=&r" (r1), "=&r" (r2)
129 :"r" (r11),
130 "m" (*r11),
131 "m" (*(const unsigned long *)(1+(char *) r11)));
132 return r1 | r2;
133 #endif
137 * Elemental unaligned stores
140 static __inline__ void stq_u(unsigned long r5, unsigned long * r11)
142 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
143 struct __una_u64 *ptr = (struct __una_u64 *) r11;
144 ptr->x = r5;
145 #else
146 unsigned long r1,r2,r3,r4;
148 __asm__("ldq_u %3,%1\n\t"
149 "ldq_u %2,%0\n\t"
150 "insqh %6,%7,%5\n\t"
151 "insql %6,%7,%4\n\t"
152 "mskqh %3,%7,%3\n\t"
153 "mskql %2,%7,%2\n\t"
154 "bis %3,%5,%3\n\t"
155 "bis %2,%4,%2\n\t"
156 "stq_u %3,%1\n\t"
157 "stq_u %2,%0"
158 :"=m" (*r11),
159 "=m" (*(unsigned long *)(7+(char *) r11)),
160 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
161 :"r" (r5), "r" (r11));
162 #endif
165 static __inline__ void stl_u(unsigned long r5, unsigned int * r11)
167 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
168 struct __una_u32 *ptr = (struct __una_u32 *) r11;
169 ptr->x = r5;
170 #else
171 unsigned long r1,r2,r3,r4;
173 __asm__("ldq_u %3,%1\n\t"
174 "ldq_u %2,%0\n\t"
175 "inslh %6,%7,%5\n\t"
176 "insll %6,%7,%4\n\t"
177 "msklh %3,%7,%3\n\t"
178 "mskll %2,%7,%2\n\t"
179 "bis %3,%5,%3\n\t"
180 "bis %2,%4,%2\n\t"
181 "stq_u %3,%1\n\t"
182 "stq_u %2,%0"
183 :"=m" (*r11),
184 "=m" (*(unsigned long *)(3+(char *) r11)),
185 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
186 :"r" (r5), "r" (r11));
187 #endif
190 static __inline__ void stw_u(unsigned long r5, unsigned short * r11)
192 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
193 struct __una_u16 *ptr = (struct __una_u16 *) r11;
194 ptr->x = r5;
195 #else
196 unsigned long r1,r2,r3,r4;
198 __asm__("ldq_u %3,%1\n\t"
199 "ldq_u %2,%0\n\t"
200 "inswh %6,%7,%5\n\t"
201 "inswl %6,%7,%4\n\t"
202 "mskwh %3,%7,%3\n\t"
203 "mskwl %2,%7,%2\n\t"
204 "bis %3,%5,%3\n\t"
205 "bis %2,%4,%2\n\t"
206 "stq_u %3,%1\n\t"
207 "stq_u %2,%0"
208 :"=m" (*r11),
209 "=m" (*(unsigned long *)(1+(char *) r11)),
210 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
211 :"r" (r5), "r" (r11));
212 #endif
214 #endif
216 /****************************************************************************
217 PARAMETERS:
218 addr - Emulator memory address to read
220 RETURNS:
221 Byte value read from emulator memory.
223 REMARKS:
224 Reads a byte value from the emulator memory.
225 ****************************************************************************/
226 u8 X86API rdb(
227 u32 addr)
229 u8 val;
231 if (addr > M.mem_size - 1) {
232 DB(printk("mem_read: address %#lx out of range!\n", addr);)
233 HALT_SYS();
235 val = *(u8*)(M.mem_base + addr);
236 DB( if (DEBUG_MEM_TRACE())
237 printk("%#08x 1 -> %#x\n", addr, val);)
238 return val;
241 /****************************************************************************
242 PARAMETERS:
243 addr - Emulator memory address to read
245 RETURNS:
246 Word value read from emulator memory.
248 REMARKS:
249 Reads a word value from the emulator memory.
250 ****************************************************************************/
251 u16 X86API rdw(
252 u32 addr)
254 u16 val = 0;
256 if (addr > M.mem_size - 2) {
257 DB(printk("mem_read: address %#lx out of range!\n", addr);)
258 HALT_SYS();
260 #ifdef __BIG_ENDIAN__
261 if (addr & 0x1) {
262 val = (*(u8*)(M.mem_base + addr) |
263 (*(u8*)(M.mem_base + addr + 1) << 8));
265 else
266 #endif
267 #if defined(__alpha__) || defined(__alpha)
268 val = ldw_u((u16*)(M.mem_base + addr));
269 #else
270 val = *(u16*)(M.mem_base + addr);
271 #endif
272 DB( if (DEBUG_MEM_TRACE())
273 printk("%#08x 2 -> %#x\n", addr, val);)
274 return val;
277 /****************************************************************************
278 PARAMETERS:
279 addr - Emulator memory address to read
281 RETURNS:
282 Long value read from emulator memory.
283 REMARKS:
284 Reads a long value from the emulator memory.
285 ****************************************************************************/
286 u32 X86API rdl(
287 u32 addr)
289 u32 val = 0;
291 if (addr > M.mem_size - 4) {
292 DB(printk("mem_read: address %#lx out of range!\n", addr);)
293 HALT_SYS();
295 #ifdef __BIG_ENDIAN__
296 if (addr & 0x3) {
297 val = (*(u8*)(M.mem_base + addr + 0) |
298 (*(u8*)(M.mem_base + addr + 1) << 8) |
299 (*(u8*)(M.mem_base + addr + 2) << 16) |
300 (*(u8*)(M.mem_base + addr + 3) << 24));
302 else
303 #endif
304 #if defined(__alpha__) || defined(__alpha)
305 val = ldl_u((u32*)(M.mem_base + addr));
306 #else
307 val = *(u32*)(M.mem_base + addr);
308 #endif
309 DB( if (DEBUG_MEM_TRACE())
310 printk("%#08x 4 -> %#x\n", addr, val);)
311 return val;
314 /****************************************************************************
315 PARAMETERS:
316 addr - Emulator memory address to read
317 val - Value to store
319 REMARKS:
320 Writes a byte value to emulator memory.
321 ****************************************************************************/
322 void X86API wrb(
323 u32 addr,
324 u8 val)
326 DB( if (DEBUG_MEM_TRACE())
327 printk("%#08x 1 <- %#x\n", addr, val);)
328 if (addr > M.mem_size - 1) {
329 DB(printk("mem_write: address %#lx out of range!\n", addr);)
330 HALT_SYS();
332 *(u8*)(M.mem_base + addr) = val;
335 /****************************************************************************
336 PARAMETERS:
337 addr - Emulator memory address to read
338 val - Value to store
340 REMARKS:
341 Writes a word value to emulator memory.
342 ****************************************************************************/
343 void X86API wrw(
344 u32 addr,
345 u16 val)
347 DB( if (DEBUG_MEM_TRACE())
348 printk("%#08x 2 <- %#x\n", addr, val);)
349 if (addr > M.mem_size - 2) {
350 DB(printk("mem_write: address %#lx out of range!\n", addr);)
351 HALT_SYS();
353 #ifdef __BIG_ENDIAN__
354 if (addr & 0x1) {
355 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
356 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
358 else
359 #endif
360 #if defined(__alpha__) || defined(__alpha)
361 stw_u(val,(u16*)(M.mem_base + addr));
362 #else
363 *(u16*)(M.mem_base + addr) = val;
364 #endif
367 /****************************************************************************
368 PARAMETERS:
369 addr - Emulator memory address to read
370 val - Value to store
372 REMARKS:
373 Writes a long value to emulator memory.
374 ****************************************************************************/
375 void X86API wrl(
376 u32 addr,
377 u32 val)
379 DB( if (DEBUG_MEM_TRACE())
380 printk("%#08x 4 <- %#x\n", addr, val);)
381 if (addr > M.mem_size - 4) {
382 DB(printk("mem_write: address %#lx out of range!\n", addr);)
383 HALT_SYS();
385 #ifdef __BIG_ENDIAN__
386 if (addr & 0x1) {
387 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
388 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
389 *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
390 *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
392 else
393 #endif
394 #if defined(__alpha__) || defined(__alpha)
395 stl_u(val,(u32*)(M.mem_base + addr));
396 #else
397 *(u32*)(M.mem_base + addr) = val;
398 #endif
401 /****************************************************************************
402 PARAMETERS:
403 addr - PIO address to read
404 RETURN:
406 REMARKS:
407 Default PIO byte read function. Doesn't perform real inb.
408 ****************************************************************************/
409 static u8 X86API p_inb(
410 X86EMU_pioAddr addr)
412 DB( if (DEBUG_IO_TRACE())
413 printk("inb %#04x \n", addr);)
414 return 0;
417 /****************************************************************************
418 PARAMETERS:
419 addr - PIO address to read
420 RETURN:
422 REMARKS:
423 Default PIO word read function. Doesn't perform real inw.
424 ****************************************************************************/
425 static u16 X86API p_inw(
426 X86EMU_pioAddr addr)
428 DB( if (DEBUG_IO_TRACE())
429 printk("inw %#04x \n", addr);)
430 return 0;
433 /****************************************************************************
434 PARAMETERS:
435 addr - PIO address to read
436 RETURN:
438 REMARKS:
439 Default PIO long read function. Doesn't perform real inl.
440 ****************************************************************************/
441 static u32 X86API p_inl(
442 X86EMU_pioAddr addr)
444 DB( if (DEBUG_IO_TRACE())
445 printk("inl %#04x \n", addr);)
446 return 0;
449 /****************************************************************************
450 PARAMETERS:
451 addr - PIO address to write
452 val - Value to store
453 REMARKS:
454 Default PIO byte write function. Doesn't perform real outb.
455 ****************************************************************************/
456 static void X86API p_outb(
457 X86EMU_pioAddr addr,
458 u8 val)
460 DB( if (DEBUG_IO_TRACE())
461 printk("outb %#02x -> %#04x \n", val, addr);)
462 return;
465 /****************************************************************************
466 PARAMETERS:
467 addr - PIO address to write
468 val - Value to store
469 REMARKS:
470 Default PIO word write function. Doesn't perform real outw.
471 ****************************************************************************/
472 static void X86API p_outw(
473 X86EMU_pioAddr addr,
474 u16 val)
476 DB( if (DEBUG_IO_TRACE())
477 printk("outw %#04x -> %#04x \n", val, addr);)
478 return;
481 /****************************************************************************
482 PARAMETERS:
483 addr - PIO address to write
484 val - Value to store
485 REMARKS:
486 Default PIO ;ong write function. Doesn't perform real outl.
487 ****************************************************************************/
488 static void X86API p_outl(
489 X86EMU_pioAddr addr,
490 u32 val)
492 DB( if (DEBUG_IO_TRACE())
493 printk("outl %#08x -> %#04x \n", val, addr);)
494 return;
497 /*------------------------- Global Variables ------------------------------*/
499 u8 (X86APIP sys_rdb)(u32 addr) = rdb;
500 u16 (X86APIP sys_rdw)(u32 addr) = rdw;
501 u32 (X86APIP sys_rdl)(u32 addr) = rdl;
502 void (X86APIP sys_wrb)(u32 addr,u8 val) = wrb;
503 void (X86APIP sys_wrw)(u32 addr,u16 val) = wrw;
504 void (X86APIP sys_wrl)(u32 addr,u32 val) = wrl;
505 u8 (X86APIP sys_inb)(X86EMU_pioAddr addr) = p_inb;
506 u16 (X86APIP sys_inw)(X86EMU_pioAddr addr) = p_inw;
507 u32 (X86APIP sys_inl)(X86EMU_pioAddr addr) = p_inl;
508 void (X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) = p_outb;
509 void (X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val) = p_outw;
510 void (X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val) = p_outl;
512 /*----------------------------- Setup -------------------------------------*/
514 /****************************************************************************
515 PARAMETERS:
516 funcs - New memory function pointers to make active
518 REMARKS:
519 This function is used to set the pointers to functions which access
520 memory space, allowing the user application to override these functions
521 and hook them out as necessary for their application.
522 ****************************************************************************/
523 void X86EMU_setupMemFuncs(
524 X86EMU_memFuncs *funcs)
526 sys_rdb = funcs->rdb;
527 sys_rdw = funcs->rdw;
528 sys_rdl = funcs->rdl;
529 sys_wrb = funcs->wrb;
530 sys_wrw = funcs->wrw;
531 sys_wrl = funcs->wrl;
534 /****************************************************************************
535 PARAMETERS:
536 funcs - New programmed I/O function pointers to make active
538 REMARKS:
539 This function is used to set the pointers to functions which access
540 I/O space, allowing the user application to override these functions
541 and hook them out as necessary for their application.
542 ****************************************************************************/
543 void X86EMU_setupPioFuncs(
544 X86EMU_pioFuncs *funcs)
546 sys_inb = funcs->inb;
547 sys_inw = funcs->inw;
548 sys_inl = funcs->inl;
549 sys_outb = funcs->outb;
550 sys_outw = funcs->outw;
551 sys_outl = funcs->outl;
554 /****************************************************************************
555 PARAMETERS:
556 funcs - New interrupt vector table to make active
558 REMARKS:
559 This function is used to set the pointers to functions which handle
560 interrupt processing in the emulator, allowing the user application to
561 hook interrupts as necessary for their application. Any interrupts that
562 are not hooked by the user application, and reflected and handled internally
563 in the emulator via the interrupt vector table. This allows the application
564 to get control when the code being emulated executes specific software
565 interrupts.
566 ****************************************************************************/
567 void X86EMU_setupIntrFuncs(
568 X86EMU_intrFuncs funcs[])
570 int i;
572 for (i=0; i < 256; i++)
573 _X86EMU_intrTab[i] = NULL;
574 if (funcs) {
575 for (i = 0; i < 256; i++)
576 _X86EMU_intrTab[i] = funcs[i];
580 /****************************************************************************
581 PARAMETERS:
582 int - New software interrupt to prepare for
584 REMARKS:
585 This function is used to set up the emulator state to exceute a software
586 interrupt. This can be used by the user application code to allow an
587 interrupt to be hooked, examined and then reflected back to the emulator
588 so that the code in the emulator will continue processing the software
589 interrupt as per normal. This essentially allows system code to actively
590 hook and handle certain software interrupts as necessary.
591 ****************************************************************************/
592 void X86EMU_prepareForInt(
593 int num)
595 push_word((u16)M.x86.R_FLG);
596 CLEAR_FLAG(F_IF);
597 CLEAR_FLAG(F_TF);
598 push_word(M.x86.R_CS);
599 M.x86.R_CS = mem_access_word(num * 4 + 2);
600 push_word(M.x86.R_IP);
601 M.x86.R_IP = mem_access_word(num * 4);
602 M.x86.intr = 0;