xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

sys.c (15409B)


      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 overridden 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 
     52 #ifdef __GNUC__
     53 
     54 /* Define some packed structures to use with unaligned accesses */
     55 
     56 struct __una_u64 {
     57     u64 x __attribute__ ((packed));
     58 };
     59 struct __una_u32 {
     60     u32 x __attribute__ ((packed));
     61 };
     62 struct __una_u16 {
     63     u16 x __attribute__ ((packed));
     64 };
     65 
     66 /* Elemental unaligned loads */
     67 
     68 static __inline__ u64
     69 ldq_u(u64 * p)
     70 {
     71     const struct __una_u64 *ptr = (const struct __una_u64 *) p;
     72 
     73     return ptr->x;
     74 }
     75 
     76 static __inline__ u32
     77 ldl_u(u32 * p)
     78 {
     79     const struct __una_u32 *ptr = (const struct __una_u32 *) p;
     80 
     81     return ptr->x;
     82 }
     83 
     84 static __inline__ u16
     85 ldw_u(u16 * p)
     86 {
     87     const struct __una_u16 *ptr = (const struct __una_u16 *) p;
     88 
     89     return ptr->x;
     90 }
     91 
     92 /* Elemental unaligned stores */
     93 
     94 static __inline__ void
     95 stq_u(u64 val, u64 * p)
     96 {
     97     struct __una_u64 *ptr = (struct __una_u64 *) p;
     98 
     99     ptr->x = val;
    100 }
    101 
    102 static __inline__ void
    103 stl_u(u32 val, u32 * p)
    104 {
    105     struct __una_u32 *ptr = (struct __una_u32 *) p;
    106 
    107     ptr->x = val;
    108 }
    109 
    110 static __inline__ void
    111 stw_u(u16 val, u16 * p)
    112 {
    113     struct __una_u16 *ptr = (struct __una_u16 *) p;
    114 
    115     ptr->x = val;
    116 }
    117 #else                           /* !__GNUC__ */
    118 
    119 static __inline__ u64
    120 ldq_u(u64 * p)
    121 {
    122     u64 ret;
    123 
    124     memmove(&ret, p, sizeof(*p));
    125     return ret;
    126 }
    127 
    128 static __inline__ u32
    129 ldl_u(u32 * p)
    130 {
    131     u32 ret;
    132 
    133     memmove(&ret, p, sizeof(*p));
    134     return ret;
    135 }
    136 
    137 static __inline__ u16
    138 ldw_u(u16 * p)
    139 {
    140     u16 ret;
    141 
    142     memmove(&ret, p, sizeof(*p));
    143     return ret;
    144 }
    145 
    146 static __inline__ void
    147 stq_u(u64 val, u64 * p)
    148 {
    149     u64 tmp = val;
    150 
    151     memmove(p, &tmp, sizeof(*p));
    152 }
    153 
    154 static __inline__ void
    155 stl_u(u32 val, u32 * p)
    156 {
    157     u32 tmp = val;
    158 
    159     memmove(p, &tmp, sizeof(*p));
    160 }
    161 
    162 static __inline__ void
    163 stw_u(u16 val, u16 * p)
    164 {
    165     u16 tmp = val;
    166 
    167     memmove(p, &tmp, sizeof(*p));
    168 }
    169 
    170 #endif                          /* __GNUC__ */
    171 /*------------------------- Global Variables ------------------------------*/
    172 
    173 X86EMU_sysEnv _X86EMU_env;      /* Global emulator machine state */
    174 X86EMU_intrFuncs _X86EMU_intrTab[256];
    175 
    176 /*----------------------------- Implementation ----------------------------*/
    177 
    178 /****************************************************************************
    179 PARAMETERS:
    180 addr	- Emulator memory address to read
    181 
    182 RETURNS:
    183 Byte value read from emulator memory.
    184 
    185 REMARKS:
    186 Reads a byte value from the emulator memory.
    187 ****************************************************************************/
    188 u8 X86API
    189 rdb(u32 addr)
    190 {
    191     u8 val;
    192 
    193     if (addr > M.mem_size - 1) {
    194         DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
    195             )
    196             HALT_SYS();
    197     }
    198     val = *(u8 *) (M.mem_base + addr);
    199     DB(if (DEBUG_MEM_TRACE())
    200        printk("%#08x 1 -> %#x\n", addr, val);)
    201         return val;
    202 }
    203 
    204 /****************************************************************************
    205 PARAMETERS:
    206 addr	- Emulator memory address to read
    207 
    208 RETURNS:
    209 Word value read from emulator memory.
    210 
    211 REMARKS:
    212 Reads a word value from the emulator memory.
    213 ****************************************************************************/
    214 u16 X86API
    215 rdw(u32 addr)
    216 {
    217     u16 val = 0;
    218 
    219     if (addr > M.mem_size - 2) {
    220         DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
    221             )
    222             HALT_SYS();
    223     }
    224 #ifdef __BIG_ENDIAN__
    225     if (addr & 0x1) {
    226         val = (*(u8 *) (M.mem_base + addr) |
    227                (*(u8 *) (M.mem_base + addr + 1) << 8));
    228     }
    229     else
    230 #endif
    231         val = ldw_u((u16 *) (M.mem_base + addr));
    232     DB(if (DEBUG_MEM_TRACE())
    233        printk("%#08x 2 -> %#x\n", addr, val);)
    234         return val;
    235 }
    236 
    237 /****************************************************************************
    238 PARAMETERS:
    239 addr	- Emulator memory address to read
    240 
    241 RETURNS:
    242 Long value read from emulator memory.
    243 REMARKS:
    244 Reads a long value from the emulator memory.
    245 ****************************************************************************/
    246 u32 X86API
    247 rdl(u32 addr)
    248 {
    249     u32 val = 0;
    250 
    251     if (addr > M.mem_size - 4) {
    252         DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
    253             )
    254             HALT_SYS();
    255     }
    256 #ifdef __BIG_ENDIAN__
    257     if (addr & 0x3) {
    258         val = (*(u8 *) (M.mem_base + addr + 0) |
    259                (*(u8 *) (M.mem_base + addr + 1) << 8) |
    260                (*(u8 *) (M.mem_base + addr + 2) << 16) |
    261                (*(u8 *) (M.mem_base + addr + 3) << 24));
    262     }
    263     else
    264 #endif
    265         val = ldl_u((u32 *) (M.mem_base + addr));
    266     DB(if (DEBUG_MEM_TRACE())
    267        printk("%#08x 4 -> %#x\n", addr, val);)
    268         return val;
    269 }
    270 
    271 /****************************************************************************
    272 PARAMETERS:
    273 addr	- Emulator memory address to read
    274 val		- Value to store
    275 
    276 REMARKS:
    277 Writes a byte value to emulator memory.
    278 ****************************************************************************/
    279 void X86API
    280 wrb(u32 addr, u8 val)
    281 {
    282     DB(if (DEBUG_MEM_TRACE())
    283        printk("%#08x 1 <- %#x\n", addr, val);)
    284         if (addr > M.mem_size - 1) {
    285             DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
    286                 )
    287                 HALT_SYS();
    288         }
    289     *(u8 *) (M.mem_base + addr) = val;
    290 }
    291 
    292 /****************************************************************************
    293 PARAMETERS:
    294 addr	- Emulator memory address to read
    295 val		- Value to store
    296 
    297 REMARKS:
    298 Writes a word value to emulator memory.
    299 ****************************************************************************/
    300 void X86API
    301 wrw(u32 addr, u16 val)
    302 {
    303     DB(if (DEBUG_MEM_TRACE())
    304        printk("%#08x 2 <- %#x\n", addr, val);)
    305         if (addr > M.mem_size - 2) {
    306             DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
    307                 )
    308                 HALT_SYS();
    309         }
    310 #ifdef __BIG_ENDIAN__
    311     if (addr & 0x1) {
    312         *(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff;
    313         *(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff;
    314     }
    315     else
    316 #endif
    317         stw_u(val, (u16 *) (M.mem_base + addr));
    318 }
    319 
    320 /****************************************************************************
    321 PARAMETERS:
    322 addr	- Emulator memory address to read
    323 val		- Value to store
    324 
    325 REMARKS:
    326 Writes a long value to emulator memory.
    327 ****************************************************************************/
    328 void X86API
    329 wrl(u32 addr, u32 val)
    330 {
    331     DB(if (DEBUG_MEM_TRACE())
    332        printk("%#08x 4 <- %#x\n", addr, val);)
    333         if (addr > M.mem_size - 4) {
    334             DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
    335                 )
    336                 HALT_SYS();
    337         }
    338 #ifdef __BIG_ENDIAN__
    339     if (addr & 0x1) {
    340         *(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff;
    341         *(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff;
    342         *(u8 *) (M.mem_base + addr + 2) = (val >> 16) & 0xff;
    343         *(u8 *) (M.mem_base + addr + 3) = (val >> 24) & 0xff;
    344     }
    345     else
    346 #endif
    347         stl_u(val, (u32 *) (M.mem_base + addr));
    348 }
    349 
    350 /****************************************************************************
    351 PARAMETERS:
    352 addr	- PIO address to read
    353 RETURN:
    354 0
    355 REMARKS:
    356 Default PIO byte read function. Doesn't perform real inb.
    357 ****************************************************************************/
    358 static u8 X86API
    359 p_inb(X86EMU_pioAddr addr)
    360 {
    361     DB(if (DEBUG_IO_TRACE())
    362        printk("inb %#04x \n", addr);)
    363         return 0;
    364 }
    365 
    366 /****************************************************************************
    367 PARAMETERS:
    368 addr	- PIO address to read
    369 RETURN:
    370 0
    371 REMARKS:
    372 Default PIO word read function. Doesn't perform real inw.
    373 ****************************************************************************/
    374 static u16 X86API
    375 p_inw(X86EMU_pioAddr addr)
    376 {
    377     DB(if (DEBUG_IO_TRACE())
    378        printk("inw %#04x \n", addr);)
    379         return 0;
    380 }
    381 
    382 /****************************************************************************
    383 PARAMETERS:
    384 addr	- PIO address to read
    385 RETURN:
    386 0
    387 REMARKS:
    388 Default PIO long read function. Doesn't perform real inl.
    389 ****************************************************************************/
    390 static u32 X86API
    391 p_inl(X86EMU_pioAddr addr)
    392 {
    393     DB(if (DEBUG_IO_TRACE())
    394        printk("inl %#04x \n", addr);)
    395         return 0;
    396 }
    397 
    398 /****************************************************************************
    399 PARAMETERS:
    400 addr	- PIO address to write
    401 val     - Value to store
    402 REMARKS:
    403 Default PIO byte write function. Doesn't perform real outb.
    404 ****************************************************************************/
    405 static void X86API
    406 p_outb(X86EMU_pioAddr addr, u8 val)
    407 {
    408     DB(if (DEBUG_IO_TRACE())
    409        printk("outb %#02x -> %#04x \n", val, addr);)
    410         return;
    411 }
    412 
    413 /****************************************************************************
    414 PARAMETERS:
    415 addr	- PIO address to write
    416 val     - Value to store
    417 REMARKS:
    418 Default PIO word write function. Doesn't perform real outw.
    419 ****************************************************************************/
    420 static void X86API
    421 p_outw(X86EMU_pioAddr addr, u16 val)
    422 {
    423     DB(if (DEBUG_IO_TRACE())
    424        printk("outw %#04x -> %#04x \n", val, addr);)
    425         return;
    426 }
    427 
    428 /****************************************************************************
    429 PARAMETERS:
    430 addr	- PIO address to write
    431 val     - Value to store
    432 REMARKS:
    433 Default PIO ;ong write function. Doesn't perform real outl.
    434 ****************************************************************************/
    435 static void X86API
    436 p_outl(X86EMU_pioAddr addr, u32 val)
    437 {
    438     DB(if (DEBUG_IO_TRACE())
    439        printk("outl %#08x -> %#04x \n", val, addr);)
    440         return;
    441 }
    442 
    443 /*------------------------- Global Variables ------------------------------*/
    444 
    445 u8(X86APIP sys_rdb) (u32 addr) = rdb;
    446 u16(X86APIP sys_rdw) (u32 addr) = rdw;
    447 u32(X86APIP sys_rdl) (u32 addr) = rdl;
    448 void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
    449 void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
    450 void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
    451 
    452 u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
    453 u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
    454 u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
    455 void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
    456 void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
    457 void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
    458 
    459 /*----------------------------- Setup -------------------------------------*/
    460 
    461 /****************************************************************************
    462 PARAMETERS:
    463 funcs	- New memory function pointers to make active
    464 
    465 REMARKS:
    466 This function is used to set the pointers to functions which access
    467 memory space, allowing the user application to override these functions
    468 and hook them out as necessary for their application.
    469 ****************************************************************************/
    470 void
    471 X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
    472 {
    473     sys_rdb = funcs->rdb;
    474     sys_rdw = funcs->rdw;
    475     sys_rdl = funcs->rdl;
    476     sys_wrb = funcs->wrb;
    477     sys_wrw = funcs->wrw;
    478     sys_wrl = funcs->wrl;
    479 }
    480 
    481 /****************************************************************************
    482 PARAMETERS:
    483 funcs	- New programmed I/O function pointers to make active
    484 
    485 REMARKS:
    486 This function is used to set the pointers to functions which access
    487 I/O space, allowing the user application to override these functions
    488 and hook them out as necessary for their application.
    489 ****************************************************************************/
    490 void
    491 X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
    492 {
    493     sys_inb = funcs->inb;
    494     sys_inw = funcs->inw;
    495     sys_inl = funcs->inl;
    496     sys_outb = funcs->outb;
    497     sys_outw = funcs->outw;
    498     sys_outl = funcs->outl;
    499 }
    500 
    501 /****************************************************************************
    502 PARAMETERS:
    503 funcs	- New interrupt vector table to make active
    504 
    505 REMARKS:
    506 This function is used to set the pointers to functions which handle
    507 interrupt processing in the emulator, allowing the user application to
    508 hook interrupts as necessary for their application. Any interrupts that
    509 are not hooked by the user application, and reflected and handled internally
    510 in the emulator via the interrupt vector table. This allows the application
    511 to get control when the code being emulated executes specific software
    512 interrupts.
    513 ****************************************************************************/
    514 void
    515 X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
    516 {
    517     int i;
    518 
    519     for (i = 0; i < 256; i++)
    520         _X86EMU_intrTab[i] = NULL;
    521     if (funcs) {
    522         for (i = 0; i < 256; i++)
    523             _X86EMU_intrTab[i] = funcs[i];
    524     }
    525 }
    526 
    527 /****************************************************************************
    528 PARAMETERS:
    529 int	- New software interrupt to prepare for
    530 
    531 REMARKS:
    532 This function is used to set up the emulator state to execute a software
    533 interrupt. This can be used by the user application code to allow an
    534 interrupt to be hooked, examined and then reflected back to the emulator
    535 so that the code in the emulator will continue processing the software
    536 interrupt as per normal. This essentially allows system code to actively
    537 hook and handle certain software interrupts as necessary.
    538 ****************************************************************************/
    539 void
    540 X86EMU_prepareForInt(int num)
    541 {
    542     push_word((u16) M.x86.R_FLG);
    543     CLEAR_FLAG(F_IF);
    544     CLEAR_FLAG(F_TF);
    545     push_word(M.x86.R_CS);
    546     M.x86.R_CS = mem_access_word(num * 4 + 2);
    547     push_word(M.x86.R_IP);
    548     M.x86.R_IP = mem_access_word(num * 4);
    549     M.x86.intr = 0;
    550 }