Coding style cleanup
[platform/kernel/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 }