]> git.ipfire.org Git - u-boot.git/blob - board/MAI/bios_emulator/scitech/src/x86emu/sys.c
* Code cleanup:
[u-boot.git] / board / MAI / bios_emulator / scitech / src / x86emu / sys.c
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/regs.h"
45 #include "x86emu/debug.h"
46 #include "x86emu/prim_ops.h"
47 #include <string.h>
48
49 /*------------------------- Global Variables ------------------------------*/
50
51 X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
52 X86EMU_intrFuncs _X86EMU_intrTab[256];
53
54 /*----------------------------- Implementation ----------------------------*/
55 #ifdef __alpha__
56 /* to cope with broken egcs-1.1.2 :-(((( */
57
58 /*
59 * inline functions to do unaligned accesses
60 * from linux/include/asm-alpha/unaligned.h
61 */
62
63 /*
64 * EGCS 1.1 knows about arbitrary unaligned loads. Define some
65 * packed structures to talk about such things with.
66 */
67
68 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
69 struct __una_u64 { unsigned long x __attribute__((packed)); };
70 struct __una_u32 { unsigned int x __attribute__((packed)); };
71 struct __una_u16 { unsigned short x __attribute__((packed)); };
72 #endif
73
74 static __inline__ unsigned long ldq_u(unsigned long * r11)
75 {
76 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
77 const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
78 return ptr->x;
79 #else
80 unsigned long r1,r2;
81 __asm__("ldq_u %0,%3\n\t"
82 "ldq_u %1,%4\n\t"
83 "extql %0,%2,%0\n\t"
84 "extqh %1,%2,%1"
85 :"=&r" (r1), "=&r" (r2)
86 :"r" (r11),
87 "m" (*r11),
88 "m" (*(const unsigned long *)(7+(char *) r11)));
89 return r1 | r2;
90 #endif
91 }
92
93 static __inline__ unsigned long ldl_u(unsigned int * r11)
94 {
95 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
96 const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
97 return ptr->x;
98 #else
99 unsigned long r1,r2;
100 __asm__("ldq_u %0,%3\n\t"
101 "ldq_u %1,%4\n\t"
102 "extll %0,%2,%0\n\t"
103 "extlh %1,%2,%1"
104 :"=&r" (r1), "=&r" (r2)
105 :"r" (r11),
106 "m" (*r11),
107 "m" (*(const unsigned long *)(3+(char *) r11)));
108 return r1 | r2;
109 #endif
110 }
111
112 static __inline__ unsigned long ldw_u(unsigned short * r11)
113 {
114 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
115 const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
116 return ptr->x;
117 #else
118 unsigned long r1,r2;
119 __asm__("ldq_u %0,%3\n\t"
120 "ldq_u %1,%4\n\t"
121 "extwl %0,%2,%0\n\t"
122 "extwh %1,%2,%1"
123 :"=&r" (r1), "=&r" (r2)
124 :"r" (r11),
125 "m" (*r11),
126 "m" (*(const unsigned long *)(1+(char *) r11)));
127 return r1 | r2;
128 #endif
129 }
130
131 /*
132 * Elemental unaligned stores
133 */
134
135 static __inline__ void stq_u(unsigned long r5, unsigned long * r11)
136 {
137 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
138 struct __una_u64 *ptr = (struct __una_u64 *) r11;
139 ptr->x = r5;
140 #else
141 unsigned long r1,r2,r3,r4;
142
143 __asm__("ldq_u %3,%1\n\t"
144 "ldq_u %2,%0\n\t"
145 "insqh %6,%7,%5\n\t"
146 "insql %6,%7,%4\n\t"
147 "mskqh %3,%7,%3\n\t"
148 "mskql %2,%7,%2\n\t"
149 "bis %3,%5,%3\n\t"
150 "bis %2,%4,%2\n\t"
151 "stq_u %3,%1\n\t"
152 "stq_u %2,%0"
153 :"=m" (*r11),
154 "=m" (*(unsigned long *)(7+(char *) r11)),
155 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
156 :"r" (r5), "r" (r11));
157 #endif
158 }
159
160 static __inline__ void stl_u(unsigned long r5, unsigned int * r11)
161 {
162 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
163 struct __una_u32 *ptr = (struct __una_u32 *) r11;
164 ptr->x = r5;
165 #else
166 unsigned long r1,r2,r3,r4;
167
168 __asm__("ldq_u %3,%1\n\t"
169 "ldq_u %2,%0\n\t"
170 "inslh %6,%7,%5\n\t"
171 "insll %6,%7,%4\n\t"
172 "msklh %3,%7,%3\n\t"
173 "mskll %2,%7,%2\n\t"
174 "bis %3,%5,%3\n\t"
175 "bis %2,%4,%2\n\t"
176 "stq_u %3,%1\n\t"
177 "stq_u %2,%0"
178 :"=m" (*r11),
179 "=m" (*(unsigned long *)(3+(char *) r11)),
180 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
181 :"r" (r5), "r" (r11));
182 #endif
183 }
184
185 static __inline__ void stw_u(unsigned long r5, unsigned short * r11)
186 {
187 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
188 struct __una_u16 *ptr = (struct __una_u16 *) r11;
189 ptr->x = r5;
190 #else
191 unsigned long r1,r2,r3,r4;
192
193 __asm__("ldq_u %3,%1\n\t"
194 "ldq_u %2,%0\n\t"
195 "inswh %6,%7,%5\n\t"
196 "inswl %6,%7,%4\n\t"
197 "mskwh %3,%7,%3\n\t"
198 "mskwl %2,%7,%2\n\t"
199 "bis %3,%5,%3\n\t"
200 "bis %2,%4,%2\n\t"
201 "stq_u %3,%1\n\t"
202 "stq_u %2,%0"
203 :"=m" (*r11),
204 "=m" (*(unsigned long *)(1+(char *) r11)),
205 "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
206 :"r" (r5), "r" (r11));
207 #endif
208 }
209
210 #elif defined (__ia64__)
211 /*
212 * EGCS 1.1 knows about arbitrary unaligned loads. Define some
213 * packed structures to talk about such things with.
214 */
215 struct __una_u64 { unsigned long x __attribute__((packed)); };
216 struct __una_u32 { unsigned int x __attribute__((packed)); };
217 struct __una_u16 { unsigned short x __attribute__((packed)); };
218
219 static __inline__ unsigned long
220 __uldq (const unsigned long * r11)
221 {
222 const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
223 return ptr->x;
224 }
225
226 static __inline__ unsigned long
227 uldl (const unsigned int * r11)
228 {
229 const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
230 return ptr->x;
231 }
232
233 static __inline__ unsigned long
234 uldw (const unsigned short * r11)
235 {
236 const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
237 return ptr->x;
238 }
239
240 static __inline__ void
241 ustq (unsigned long r5, unsigned long * r11)
242 {
243 struct __una_u64 *ptr = (struct __una_u64 *) r11;
244 ptr->x = r5;
245 }
246
247 static __inline__ void
248 ustl (unsigned long r5, unsigned int * r11)
249 {
250 struct __una_u32 *ptr = (struct __una_u32 *) r11;
251 ptr->x = r5;
252 }
253
254 static __inline__ void
255 ustw (unsigned long r5, unsigned short * r11)
256 {
257 struct __una_u16 *ptr = (struct __una_u16 *) r11;
258 ptr->x = r5;
259 }
260
261 #endif
262
263 /****************************************************************************
264 PARAMETERS:
265 addr - Emulator memory address to read
266
267 RETURNS:
268 Byte value read from emulator memory.
269
270 REMARKS:
271 Reads a byte value from the emulator memory.
272 ****************************************************************************/
273 u8 X86API rdb(
274 u32 addr)
275 {
276 u8 val;
277
278 if (addr > M.mem_size - 1) {
279 DB(printk("mem_read: address %#lx out of range!\n", addr);)
280 HALT_SYS();
281 }
282 val = *(u8*)(M.mem_base + addr);
283 DB( if (DEBUG_MEM_TRACE())
284 printk("%#08x 1 -> %#x\n", addr, val);)
285 return val;
286 }
287
288 /****************************************************************************
289 PARAMETERS:
290 addr - Emulator memory address to read
291
292 RETURNS:
293 Word value read from emulator memory.
294
295 REMARKS:
296 Reads a word value from the emulator memory.
297 ****************************************************************************/
298 u16 X86API rdw(
299 u32 addr)
300 {
301 u16 val = 0;
302
303 if (addr > M.mem_size - 2) {
304 DB(printk("mem_read: address %#lx out of range!\n", addr);)
305 HALT_SYS();
306 }
307 #ifdef __BIG_ENDIAN__
308 if (addr & 0x1) {
309 val = (*(u8*)(M.mem_base + addr) |
310 (*(u8*)(M.mem_base + addr + 1) << 8));
311 }
312 else
313 #endif
314 #ifdef __alpha__
315 val = ldw_u((u16*)(M.mem_base + addr));
316 #elif defined (__ia64__)
317 val = uldw((u16*)(M.mem_base + addr));
318 #else
319 val = *(u16*)(M.mem_base + addr);
320 #endif
321 DB( if (DEBUG_MEM_TRACE())
322 printk("%#08x 2 -> %#x\n", addr, val);)
323 return val;
324 }
325
326 /****************************************************************************
327 PARAMETERS:
328 addr - Emulator memory address to read
329
330 RETURNS:
331 Long value read from emulator memory.
332 REMARKS:
333 Reads a long value from the emulator memory.
334 ****************************************************************************/
335 u32 X86API rdl(
336 u32 addr)
337 {
338 u32 val = 0;
339
340 if (addr > M.mem_size - 4) {
341 DB(printk("mem_read: address %#lx out of range!\n", addr);)
342 HALT_SYS();
343 }
344 #ifdef __BIG_ENDIAN__
345 if (addr & 0x3) {
346 val = (*(u8*)(M.mem_base + addr + 0) |
347 (*(u8*)(M.mem_base + addr + 1) << 8) |
348 (*(u8*)(M.mem_base + addr + 2) << 16) |
349 (*(u8*)(M.mem_base + addr + 3) << 24));
350 }
351 else
352 #endif
353 #ifdef __alpha__
354 val = ldl_u((u32*)(M.mem_base + addr));
355 #elif defined (__ia64__)
356 val = uldl((u32*)(M.mem_base + addr));
357 #else
358 val = *(u32*)(M.mem_base + addr);
359 #endif
360 DB( if (DEBUG_MEM_TRACE())
361 printk("%#08x 4 -> %#x\n", addr, val);)
362 return val;
363 }
364
365 /****************************************************************************
366 PARAMETERS:
367 addr - Emulator memory address to read
368 val - Value to store
369
370 REMARKS:
371 Writes a byte value to emulator memory.
372 ****************************************************************************/
373 void X86API wrb(
374 u32 addr,
375 u8 val)
376 {
377 DB( if (DEBUG_MEM_TRACE())
378 printk("%#08x 1 <- %#x\n", addr, val);)
379 if (addr > M.mem_size - 1) {
380 DB(printk("mem_write: address %#lx out of range!\n", addr);)
381 HALT_SYS();
382 }
383 *(u8*)(M.mem_base + addr) = val;
384 }
385
386 /****************************************************************************
387 PARAMETERS:
388 addr - Emulator memory address to read
389 val - Value to store
390
391 REMARKS:
392 Writes a word value to emulator memory.
393 ****************************************************************************/
394 void X86API wrw(
395 u32 addr,
396 u16 val)
397 {
398 DB( if (DEBUG_MEM_TRACE())
399 printk("%#08x 2 <- %#x\n", addr, val);)
400 if (addr > M.mem_size - 2) {
401 DB(printk("mem_write: address %#lx out of range!\n", addr);)
402 HALT_SYS();
403 }
404 #ifdef __BIG_ENDIAN__
405 if (addr & 0x1) {
406 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
407 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
408 }
409 else
410 #endif
411 #ifdef __alpha__
412 stw_u(val,(u16*)(M.mem_base + addr));
413 #elif defined (__ia64__)
414 ustw(val,(u16*)(M.mem_base + addr));
415 #else
416 *(u16*)(M.mem_base + addr) = val;
417 #endif
418 }
419
420 /****************************************************************************
421 PARAMETERS:
422 addr - Emulator memory address to read
423 val - Value to store
424
425 REMARKS:
426 Writes a long value to emulator memory.
427 ****************************************************************************/
428 void X86API wrl(
429 u32 addr,
430 u32 val)
431 {
432 DB( if (DEBUG_MEM_TRACE())
433 printk("%#08x 4 <- %#x\n", addr, val);)
434 if (addr > M.mem_size - 4) {
435 DB(printk("mem_write: address %#lx out of range!\n", addr);)
436 HALT_SYS();
437 }
438 #ifdef __BIG_ENDIAN__
439 if (addr & 0x1) {
440 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
441 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
442 *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
443 *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
444 }
445 else
446 #endif
447 #ifdef __alpha__
448 stl_u(val,(u32*)(M.mem_base + addr));
449 #elif defined (__ia64__)
450 ustl(val,(u32*)(M.mem_base + addr));
451 #else
452 *(u32*)(M.mem_base + addr) = val;
453 #endif
454 }
455
456 /****************************************************************************
457 PARAMETERS:
458 addr - PIO address to read
459 RETURN:
460 0
461 REMARKS:
462 Default PIO byte read function. Doesn't perform real inb.
463 ****************************************************************************/
464 static u8 X86API p_inb(
465 X86EMU_pioAddr addr)
466 {
467 DB( if (DEBUG_IO_TRACE())
468 printk("inb %#04x \n", addr);)
469 return 0;
470 }
471
472 /****************************************************************************
473 PARAMETERS:
474 addr - PIO address to read
475 RETURN:
476 0
477 REMARKS:
478 Default PIO word read function. Doesn't perform real inw.
479 ****************************************************************************/
480 static u16 X86API p_inw(
481 X86EMU_pioAddr addr)
482 {
483 DB( if (DEBUG_IO_TRACE())
484 printk("inw %#04x \n", addr);)
485 return 0;
486 }
487
488 /****************************************************************************
489 PARAMETERS:
490 addr - PIO address to read
491 RETURN:
492 0
493 REMARKS:
494 Default PIO long read function. Doesn't perform real inl.
495 ****************************************************************************/
496 static u32 X86API p_inl(
497 X86EMU_pioAddr addr)
498 {
499 DB( if (DEBUG_IO_TRACE())
500 printk("inl %#04x \n", addr);)
501 return 0;
502 }
503
504 /****************************************************************************
505 PARAMETERS:
506 addr - PIO address to write
507 val - Value to store
508 REMARKS:
509 Default PIO byte write function. Doesn't perform real outb.
510 ****************************************************************************/
511 static void X86API p_outb(
512 X86EMU_pioAddr addr,
513 u8 val)
514 {
515 DB( if (DEBUG_IO_TRACE())
516 printk("outb %#02x -> %#04x \n", val, addr);)
517 return;
518 }
519
520 /****************************************************************************
521 PARAMETERS:
522 addr - PIO address to write
523 val - Value to store
524 REMARKS:
525 Default PIO word write function. Doesn't perform real outw.
526 ****************************************************************************/
527 static void X86API p_outw(
528 X86EMU_pioAddr addr,
529 u16 val)
530 {
531 DB( if (DEBUG_IO_TRACE())
532 printk("outw %#04x -> %#04x \n", val, addr);)
533 return;
534 }
535
536 /****************************************************************************
537 PARAMETERS:
538 addr - PIO address to write
539 val - Value to store
540 REMARKS:
541 Default PIO ;ong write function. Doesn't perform real outl.
542 ****************************************************************************/
543 static void X86API p_outl(
544 X86EMU_pioAddr addr,
545 u32 val)
546 {
547 DB( if (DEBUG_IO_TRACE())
548 printk("outl %#08x -> %#04x \n", val, addr);)
549 return;
550 }
551
552 /*------------------------- Global Variables ------------------------------*/
553
554 u8 (X86APIP sys_rdb)(u32 addr) = rdb;
555 u16 (X86APIP sys_rdw)(u32 addr) = rdw;
556 u32 (X86APIP sys_rdl)(u32 addr) = rdl;
557 void (X86APIP sys_wrb)(u32 addr,u8 val) = wrb;
558 void (X86APIP sys_wrw)(u32 addr,u16 val) = wrw;
559 void (X86APIP sys_wrl)(u32 addr,u32 val) = wrl;
560 u8 (X86APIP sys_inb)(X86EMU_pioAddr addr) = p_inb;
561 u16 (X86APIP sys_inw)(X86EMU_pioAddr addr) = p_inw;
562 u32 (X86APIP sys_inl)(X86EMU_pioAddr addr) = p_inl;
563 void (X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) = p_outb;
564 void (X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val) = p_outw;
565 void (X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val) = p_outl;
566
567 /*----------------------------- Setup -------------------------------------*/
568
569 /****************************************************************************
570 PARAMETERS:
571 funcs - New memory function pointers to make active
572
573 REMARKS:
574 This function is used to set the pointers to functions which access
575 memory space, allowing the user application to override these functions
576 and hook them out as necessary for their application.
577 ****************************************************************************/
578 void X86EMU_setupMemFuncs(
579 X86EMU_memFuncs *funcs)
580 {
581 sys_rdb = funcs->rdb;
582 sys_rdw = funcs->rdw;
583 sys_rdl = funcs->rdl;
584 sys_wrb = funcs->wrb;
585 sys_wrw = funcs->wrw;
586 sys_wrl = funcs->wrl;
587 }
588
589 /****************************************************************************
590 PARAMETERS:
591 funcs - New programmed I/O function pointers to make active
592
593 REMARKS:
594 This function is used to set the pointers to functions which access
595 I/O space, allowing the user application to override these functions
596 and hook them out as necessary for their application.
597 ****************************************************************************/
598 void X86EMU_setupPioFuncs(
599 X86EMU_pioFuncs *funcs)
600 {
601 sys_inb = funcs->inb;
602 sys_inw = funcs->inw;
603 sys_inl = funcs->inl;
604 sys_outb = funcs->outb;
605 sys_outw = funcs->outw;
606 sys_outl = funcs->outl;
607 }
608
609 /****************************************************************************
610 PARAMETERS:
611 funcs - New interrupt vector table to make active
612
613 REMARKS:
614 This function is used to set the pointers to functions which handle
615 interrupt processing in the emulator, allowing the user application to
616 hook interrupts as necessary for their application. Any interrupts that
617 are not hooked by the user application, and reflected and handled internally
618 in the emulator via the interrupt vector table. This allows the application
619 to get control when the code being emulated executes specific software
620 interrupts.
621 ****************************************************************************/
622 void X86EMU_setupIntrFuncs(
623 X86EMU_intrFuncs funcs[])
624 {
625 int i;
626
627 for (i=0; i < 256; i++)
628 _X86EMU_intrTab[i] = NULL;
629 if (funcs) {
630 for (i = 0; i < 256; i++)
631 _X86EMU_intrTab[i] = funcs[i];
632 }
633 }
634
635 /****************************************************************************
636 PARAMETERS:
637 int - New software interrupt to prepare for
638
639 REMARKS:
640 This function is used to set up the emulator state to exceute a software
641 interrupt. This can be used by the user application code to allow an
642 interrupt to be hooked, examined and then reflected back to the emulator
643 so that the code in the emulator will continue processing the software
644 interrupt as per normal. This essentially allows system code to actively
645 hook and handle certain software interrupts as necessary.
646 ****************************************************************************/
647 void X86EMU_prepareForInt(
648 int num)
649 {
650 push_word((u16)M.x86.R_FLG);
651 CLEAR_FLAG(F_IF);
652 CLEAR_FLAG(F_TF);
653 push_word(M.x86.R_CS);
654 M.x86.R_CS = mem_access_word(num * 4 + 2);
655 push_word(M.x86.R_IP);
656 M.x86.R_IP = mem_access_word(num * 4);
657 M.x86.intr = 0;
658 }