Author: delphij
Date: Wed Sep  9 01:14:25 2009
New Revision: 197007
URL: http://svn.freebsd.org/changeset/base/197007

Log:
  Import x86emu from OpenBSD (src/sys/dev/x86emu).
  
  x86emu is a software emulator for the real mode x86 processor, originally
  written by SciTech Software, Inc. for XFree86 and has been later ported
  to NetBSD then OpenBSD.

Added:
  vendor-sys/x86emu/
  vendor-sys/x86emu/dist/
  vendor-sys/x86emu/dist/x86emu.c
  vendor-sys/x86emu/dist/x86emu.h
  vendor-sys/x86emu/dist/x86emu_regs.h
  vendor-sys/x86emu/dist/x86emu_util.c

Added: vendor-sys/x86emu/dist/x86emu.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ vendor-sys/x86emu/dist/x86emu.c     Wed Sep  9 01:14:25 2009        
(r197007)
@@ -0,0 +1,8341 @@
+/*     $OpenBSD: x86emu.c,v 1.4 2009/06/18 14:19:21 pirofti Exp $      */
+/*     $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */
+
+/*
+ *
+ *  Realmode X86 Emulator Library
+ *
+ *  Copyright (C) 1996-1999 SciTech Software, Inc.
+ *  Copyright (C) David Mosberger-Tang
+ *  Copyright (C) 1999 Egbert Eich
+ *  Copyright (C) 2007 Joerg Sonnenberger
+ *
+ *  ========================================================================
+ *
+ *  Permission to use, copy, modify, distribute, and sell this software and
+ *  its documentation for any purpose is hereby granted without fee,
+ *  provided that the above copyright notice appear in all copies and that
+ *  both that copyright notice and this permission notice appear in
+ *  supporting documentation, and that the name of the authors not be used
+ *  in advertising or publicity pertaining to distribution of the software
+ *  without specific, written prior permission.  The authors makes no
+ *  representations about the suitability of this software for any purpose.
+ *  It is provided "as is" without express or implied warranty.
+ *
+ *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ *  PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <dev/x86emu/x86emu.h>
+#include <dev/x86emu/x86emu_regs.h>
+
+static void    x86emu_intr_raise (struct x86emu *, uint8_t type);
+
+static void    x86emu_exec_one_byte(struct x86emu *);
+static void    x86emu_exec_two_byte(struct x86emu *);
+
+static void    fetch_decode_modrm (struct x86emu *);
+static uint8_t fetch_byte_imm (struct x86emu *);
+static uint16_t        fetch_word_imm (struct x86emu *);
+static uint32_t        fetch_long_imm (struct x86emu *);
+static uint8_t fetch_data_byte (struct x86emu *, uint32_t offset);
+static uint8_t fetch_byte (struct x86emu *, uint segment, uint32_t offset);
+static uint16_t        fetch_data_word (struct x86emu *, uint32_t offset);
+static uint16_t        fetch_word (struct x86emu *, uint32_t segment, uint32_t 
offset);
+static uint32_t        fetch_data_long (struct x86emu *, uint32_t offset);
+static uint32_t        fetch_long (struct x86emu *, uint32_t segment, uint32_t 
offset);
+static void    store_data_byte (struct x86emu *, uint32_t offset, uint8_t val);
+static void    store_byte (struct x86emu *, uint32_t segment, uint32_t offset, 
uint8_t val);
+static void    store_data_word (struct x86emu *, uint32_t offset, uint16_t 
val);
+static void    store_word (struct x86emu *, uint32_t segment, uint32_t offset, 
uint16_t val);
+static void    store_data_long (struct x86emu *, uint32_t offset, uint32_t 
val);
+static void    store_long (struct x86emu *, uint32_t segment, uint32_t offset, 
uint32_t val);
+static uint8_t*        decode_rl_byte_register(struct x86emu *);
+static uint16_t*       decode_rl_word_register(struct x86emu *);
+static uint32_t*       decode_rl_long_register(struct x86emu *);
+static uint8_t*        decode_rh_byte_register(struct x86emu *);
+static uint16_t*       decode_rh_word_register(struct x86emu *);
+static uint32_t*       decode_rh_long_register(struct x86emu *);
+static uint16_t*       decode_rh_seg_register(struct x86emu *);
+static uint32_t        decode_rl_address(struct x86emu *);
+
+static uint8_t         decode_and_fetch_byte(struct x86emu *);
+static uint16_t        decode_and_fetch_word(struct x86emu *);
+static uint32_t        decode_and_fetch_long(struct x86emu *);
+
+static uint8_t         decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *);
+static uint16_t        decode_and_fetch_word_imm8(struct x86emu *, uint8_t *);
+static uint32_t        decode_and_fetch_long_imm8(struct x86emu *, uint8_t *);
+
+static uint16_t        decode_and_fetch_word_disp(struct x86emu *, int16_t);
+static uint32_t        decode_and_fetch_long_disp(struct x86emu *, int16_t);
+
+static void    write_back_byte(struct x86emu *, uint8_t);
+static void    write_back_word(struct x86emu *, uint16_t);
+static void    write_back_long(struct x86emu *, uint32_t);
+
+static uint16_t        aaa_word (struct x86emu *, uint16_t d);
+static uint16_t        aas_word (struct x86emu *, uint16_t d);
+static uint16_t        aad_word (struct x86emu *, uint16_t d);
+static uint16_t        aam_word (struct x86emu *, uint8_t d);
+static uint8_t adc_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        adc_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        adc_long (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t add_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        add_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        add_long (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t and_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        and_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        and_long (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t cmp_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        cmp_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        cmp_long (struct x86emu *, uint32_t d, uint32_t s);
+static void    cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s);
+static void    cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s);
+static void    cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t daa_byte (struct x86emu *, uint8_t d);
+static uint8_t das_byte (struct x86emu *, uint8_t d);
+static uint8_t dec_byte (struct x86emu *, uint8_t d);
+static uint16_t        dec_word (struct x86emu *, uint16_t d);
+static uint32_t        dec_long (struct x86emu *, uint32_t d);
+static uint8_t inc_byte (struct x86emu *, uint8_t d);
+static uint16_t        inc_word (struct x86emu *, uint16_t d);
+static uint32_t        inc_long (struct x86emu *, uint32_t d);
+static uint8_t or_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        or_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        or_long (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t neg_byte (struct x86emu *, uint8_t s);
+static uint16_t        neg_word (struct x86emu *, uint16_t s);
+static uint32_t        neg_long (struct x86emu *, uint32_t s);
+static uint8_t rcl_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        rcl_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        rcl_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint8_t rcr_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        rcr_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        rcr_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint8_t rol_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        rol_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        rol_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint8_t ror_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        ror_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        ror_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint8_t shl_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        shl_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        shl_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint8_t shr_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        shr_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        shr_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint8_t sar_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        sar_word (struct x86emu *, uint16_t d, uint8_t s);
+static uint32_t        sar_long (struct x86emu *, uint32_t d, uint8_t s);
+static uint16_t        shld_word (struct x86emu *, uint16_t d, uint16_t fill, 
uint8_t s);
+static uint32_t        shld_long (struct x86emu *, uint32_t d, uint32_t fill, 
uint8_t s);
+static uint16_t        shrd_word (struct x86emu *, uint16_t d, uint16_t fill, 
uint8_t s);
+static uint32_t        shrd_long (struct x86emu *, uint32_t d, uint32_t fill, 
uint8_t s);
+static uint8_t sbb_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        sbb_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        sbb_long (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t sub_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        sub_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        sub_long (struct x86emu *, uint32_t d, uint32_t s);
+static void    test_byte (struct x86emu *, uint8_t d, uint8_t s);
+static void    test_word (struct x86emu *, uint16_t d, uint16_t s);
+static void    test_long (struct x86emu *, uint32_t d, uint32_t s);
+static uint8_t xor_byte (struct x86emu *, uint8_t d, uint8_t s);
+static uint16_t        xor_word (struct x86emu *, uint16_t d, uint16_t s);
+static uint32_t        xor_long (struct x86emu *, uint32_t d, uint32_t s);
+static void    imul_byte (struct x86emu *, uint8_t s);
+static void    imul_word (struct x86emu *, uint16_t s);
+static void    imul_long (struct x86emu *, uint32_t s);
+static void    mul_byte (struct x86emu *, uint8_t s);
+static void    mul_word (struct x86emu *, uint16_t s);
+static void    mul_long (struct x86emu *, uint32_t s);
+static void    idiv_byte (struct x86emu *, uint8_t s);
+static void    idiv_word (struct x86emu *, uint16_t s);
+static void    idiv_long (struct x86emu *, uint32_t s);
+static void    div_byte (struct x86emu *, uint8_t s);
+static void    div_word (struct x86emu *, uint16_t s);
+static void    div_long (struct x86emu *, uint32_t s);
+static void    ins (struct x86emu *, int size);
+static void    outs (struct x86emu *, int size);
+static void    push_word (struct x86emu *, uint16_t w);
+static void    push_long (struct x86emu *, uint32_t w);
+static uint16_t        pop_word (struct x86emu *);
+static uint32_t        pop_long (struct x86emu *);
+
+/*
+ * REMARKS:
+ * Handles any pending asychronous interrupts.
+ */
+static void
+x86emu_intr_dispatch(struct x86emu *emu, uint8_t intno)
+{
+       if (emu->_x86emu_intrTab[intno]) {
+               (*emu->_x86emu_intrTab[intno]) (emu, intno);
+       } else {
+               push_word(emu, (uint16_t) emu->x86.R_FLG);
+               CLEAR_FLAG(F_IF);
+               CLEAR_FLAG(F_TF);
+               push_word(emu, emu->x86.R_CS);
+               emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2);
+               push_word(emu, emu->x86.R_IP);
+               emu->x86.R_IP = fetch_word(emu, 0, intno * 4);
+       }
+}
+
+static void 
+x86emu_intr_handle(struct x86emu *emu)
+{
+       uint8_t intno;
+
+       if (emu->x86.intr & INTR_SYNCH) {
+               intno = emu->x86.intno;
+               emu->x86.intr = 0;
+               x86emu_intr_dispatch(emu, intno);
+       }
+}
+
+/*
+ * PARAMETERS:
+ * intrnum - Interrupt number to raise
+ * 
+ * REMARKS:
+ * Raise the specified interrupt to be handled before the execution of the
+ * next instruction.
+ */
+void 
+x86emu_intr_raise(struct x86emu *emu, uint8_t intrnum)
+{
+       emu->x86.intno = intrnum;
+       emu->x86.intr |= INTR_SYNCH;
+}
+
+/*
+ * REMARKS:
+ * Main execution loop for the emulator. We return from here when the system
+ * halts, which is normally caused by a stack fault when we return from the
+ * original real mode call.
+ */
+void 
+x86emu_exec(struct x86emu *emu)
+{
+       emu->x86.intr = 0;
+
+#ifdef _KERNEL
+       if (setjmp(&emu->exec_state))
+               return;
+#else
+       if (setjmp(emu->exec_state))
+               return;
+#endif
+
+       for (;;) {
+               if (emu->x86.intr) {
+                       if (((emu->x86.intr & INTR_SYNCH) && (emu->x86.intno == 
0 || emu->x86.intno == 2)) ||
+                           !ACCESS_FLAG(F_IF)) {
+                               x86emu_intr_handle(emu);
+                       }
+               }
+               if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
+                       return;
+               x86emu_exec_one_byte(emu);
+               ++emu->cur_cycles;
+       }
+}
+
+void
+x86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off)
+{
+       push_word(emu, 0);
+       push_word(emu, 0);
+       emu->x86.R_CS = seg;
+       emu->x86.R_IP = off;
+
+       x86emu_exec(emu);
+}
+
+void
+x86emu_exec_intr(struct x86emu *emu, uint8_t intr)
+{
+       push_word(emu, emu->x86.R_FLG);
+       CLEAR_FLAG(F_IF);
+       CLEAR_FLAG(F_TF);
+       push_word(emu, 0);
+       push_word(emu, 0);
+       emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
+       emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
+       emu->x86.intr = 0;
+
+       x86emu_exec(emu);
+}
+
+/*
+ * REMARKS:
+ * Halts the system by setting the halted system flag.
+ */
+void 
+x86emu_halt_sys(struct x86emu *emu)
+{
+#ifdef _KERNEL
+       longjmp(&emu->exec_state);
+#else
+       longjmp(emu->exec_state, 1);
+#endif
+}
+
+/*
+ * PARAMETERS:
+ * mod         - Mod value from decoded byte
+ * regh        - Reg h value from decoded byte
+ * regl        - Reg l value from decoded byte
+ * 
+ * REMARKS:
+ * Raise the specified interrupt to be handled before the execution of the
+ * next instruction.
+ * 
+ * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
+ */
+static void 
+fetch_decode_modrm(struct x86emu *emu)
+{
+       int fetched;
+
+       fetched = fetch_byte_imm(emu);
+       emu->cur_mod = (fetched >> 6) & 0x03;
+       emu->cur_rh = (fetched >> 3) & 0x07;
+       emu->cur_rl = (fetched >> 0) & 0x07;
+}
+
+/*
+ * RETURNS:
+ * Immediate byte value read from instruction queue
+ * 
+ * REMARKS:
+ * This function returns the immediate byte from the instruction queue, and
+ * moves the instruction pointer to the next value.
+ * 
+ * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
+ */
+static uint8_t 
+fetch_byte_imm(struct x86emu *emu)
+{
+       uint8_t fetched;
+
+       fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
+       emu->x86.R_IP++;
+       return fetched;
+}
+
+/*
+ * RETURNS:
+ * Immediate word value read from instruction queue
+ * 
+ * REMARKS:
+ * This function returns the immediate byte from the instruction queue, and
+ * moves the instruction pointer to the next value.
+ * 
+ * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
+ */
+static uint16_t 
+fetch_word_imm(struct x86emu *emu)
+{
+       uint16_t fetched;
+
+       fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
+       emu->x86.R_IP += 2;
+       return fetched;
+}
+
+/*
+ * RETURNS:
+ * Immediate lone value read from instruction queue
+ * 
+ * REMARKS:
+ * This function returns the immediate byte from the instruction queue, and
+ * moves the instruction pointer to the next value.
+ * 
+ * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
+ */
+static uint32_t 
+fetch_long_imm(struct x86emu *emu)
+{
+       uint32_t fetched;
+
+       fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
+       emu->x86.R_IP += 4;
+       return fetched;
+}
+
+/*
+ * RETURNS:
+ * Value of the default data segment
+ * 
+ * REMARKS:
+ * Inline function that returns the default data segment for the current
+ * instruction.
+ * 
+ * On the x86 processor, the default segment is not always DS if there is
+ * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
+ * addresses relative to SS (ie: on the stack). So, at the minimum, all
+ * decodings of addressing modes would have to set/clear a bit describing
+ * whether the access is relative to DS or SS.  That is the function of the
+ * cpu-state-varible emu->x86.mode. There are several potential states:
+ * 
+ *     repe prefix seen  (handled elsewhere)
+ *     repne prefix seen  (ditto)
+ * 
+ *     cs segment override
+ *     ds segment override
+ *     es segment override
+ *     fs segment override
+ *     gs segment override
+ *     ss segment override
+ * 
+ *     ds/ss select (in absense of override)
+ * 
+ * Each of the above 7 items are handled with a bit in the mode field.
+ */
+static uint32_t 
+get_data_segment(struct x86emu *emu)
+{
+       switch (emu->x86.mode & SYSMODE_SEGMASK) {
+       case 0:         /* default case: use ds register */
+       case SYSMODE_SEGOVR_DS:
+       case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
+               return emu->x86.R_DS;
+       case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */
+               return emu->x86.R_SS;
+       case SYSMODE_SEGOVR_CS:
+       case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
+               return emu->x86.R_CS;
+       case SYSMODE_SEGOVR_ES:
+       case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
+               return emu->x86.R_ES;
+       case SYSMODE_SEGOVR_FS:
+       case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
+               return emu->x86.R_FS;
+       case SYSMODE_SEGOVR_GS:
+       case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
+               return emu->x86.R_GS;
+       case SYSMODE_SEGOVR_SS:
+       case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
+               return emu->x86.R_SS;
+       }
+       x86emu_halt_sys(emu);
+}
+
+/*
+ * PARAMETERS:
+ * offset      - Offset to load data from
+ * 
+ * RETURNS:
+ * Byte value read from the absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
+ */
+static uint8_t 
+fetch_data_byte(struct x86emu *emu, uint32_t offset)
+{
+       return fetch_byte(emu, get_data_segment(emu), offset);
+}
+
+/*
+ * PARAMETERS:
+ * offset      - Offset to load data from
+ * 
+ * RETURNS:
+ * Word value read from the absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
+ */
+static uint16_t 
+fetch_data_word(struct x86emu *emu, uint32_t offset)
+{
+       return fetch_word(emu, get_data_segment(emu), offset);
+}
+
+/*
+ * PARAMETERS:
+ * offset      - Offset to load data from
+ * 
+ * RETURNS:
+ * Long value read from the absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
+ */
+static uint32_t 
+fetch_data_long(struct x86emu *emu, uint32_t offset)
+{
+       return fetch_long(emu, get_data_segment(emu), offset);
+}
+
+/*
+ * PARAMETERS:
+ * segment     - Segment to load data from
+ * offset      - Offset to load data from
+ * 
+ * RETURNS:
+ * Byte value read from the absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
+ */
+static uint8_t 
+fetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset)
+{
+       return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
+}
+
+/*
+ * PARAMETERS:
+ * segment     - Segment to load data from
+ * offset      - Offset to load data from
+ * 
+ * RETURNS:
+ * Word value read from the absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
+ */
+static uint16_t 
+fetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset)
+{
+       return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
+}
+
+/*
+ * PARAMETERS:
+ * segment     - Segment to load data from
+ * offset      - Offset to load data from
+ * 
+ * RETURNS:
+ * Long value read from the absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
+ */
+static uint32_t 
+fetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset)
+{
+       return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
+}
+
+/*
+ * PARAMETERS:
+ * offset      - Offset to store data at
+ * val         - Value to store
+ * 
+ * REMARKS:
+ * Writes a word value to an segmented memory location. The segment used is
+ * the current 'default' segment, which may have been overridden.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
+ */
+static void 
+store_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val)
+{
+       store_byte(emu, get_data_segment(emu), offset, val);
+}
+
+/*
+ * PARAMETERS:
+ * offset      - Offset to store data at
+ * val         - Value to store
+ * 
+ * REMARKS:
+ * Writes a word value to an segmented memory location. The segment used is
+ * the current 'default' segment, which may have been overridden.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
+ */
+static void 
+store_data_word(struct x86emu *emu, uint32_t offset, uint16_t val)
+{
+       store_word(emu, get_data_segment(emu), offset, val);
+}
+
+/*
+ * PARAMETERS:
+ * offset      - Offset to store data at
+ * val         - Value to store
+ * 
+ * REMARKS:
+ * Writes a long value to an segmented memory location. The segment used is
+ * the current 'default' segment, which may have been overridden.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
+ */
+static void 
+store_data_long(struct x86emu *emu, uint32_t offset, uint32_t val)
+{
+       store_long(emu, get_data_segment(emu), offset, val);
+}
+
+/*
+ * PARAMETERS:
+ * segment     - Segment to store data at
+ * offset      - Offset to store data at
+ * val         - Value to store
+ * 
+ * REMARKS:
+ * Writes a byte value to an absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
+ */
+static void 
+store_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val)
+{
+       (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
+}
+
+/*
+ * PARAMETERS:
+ * segment     - Segment to store data at
+ * offset      - Offset to store data at
+ * val         - Value to store
+ * 
+ * REMARKS:
+ * Writes a word value to an absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
+ */
+static void 
+store_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val)
+{
+       (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
+}
+
+/*
+ * PARAMETERS:
+ * segment     - Segment to store data at
+ * offset      - Offset to store data at
+ * val         - Value to store
+ * 
+ * REMARKS:
+ * Writes a long value to an absolute memory location.
+ * 
+ * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
+ */
+static void 
+store_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val)
+{
+       (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
+}
+
+/*
+ * PARAMETERS:
+ * reg - Register to decode
+ * 
+ * RETURNS:
+ * Pointer to the appropriate register
+ * 
+ * REMARKS:
+ * Return a pointer to the register given by the R/RM field of the
+ * modrm byte, for byte operands. Also enables the decoding of instructions.
+ */
+static uint8_t *
+decode_rm_byte_register(struct x86emu *emu, int reg)
+{
+       switch (reg) {
+       case 0:
+               return &emu->x86.R_AL;
+       case 1:
+               return &emu->x86.R_CL;
+       case 2:
+               return &emu->x86.R_DL;
+       case 3:
+               return &emu->x86.R_BL;
+       case 4:
+               return &emu->x86.R_AH;
+       case 5:
+               return &emu->x86.R_CH;
+       case 6:
+               return &emu->x86.R_DH;
+       case 7:
+               return &emu->x86.R_BH;
+       default:
+               x86emu_halt_sys(emu);
+       }
+}
+
+static uint8_t *
+decode_rl_byte_register(struct x86emu *emu)
+{
+       return decode_rm_byte_register(emu, emu->cur_rl);
+}
+
+static uint8_t *
+decode_rh_byte_register(struct x86emu *emu)
+{
+       return decode_rm_byte_register(emu, emu->cur_rh);
+}
+
+/*
+ * PARAMETERS:
+ * reg - Register to decode
+ * 
+ * RETURNS:
+ * Pointer to the appropriate register
+ * 
+ * REMARKS:
+ * Return a pointer to the register given by the R/RM field of the
+ * modrm byte, for word operands.  Also enables the decoding of instructions.
+ */
+static uint16_t *
+decode_rm_word_register(struct x86emu *emu, int reg)
+{
+       switch (reg) {
+       case 0:
+               return &emu->x86.R_AX;
+       case 1:
+               return &emu->x86.R_CX;
+       case 2:
+               return &emu->x86.R_DX;
+       case 3:
+               return &emu->x86.R_BX;
+       case 4:
+               return &emu->x86.R_SP;
+       case 5:
+               return &emu->x86.R_BP;
+       case 6:
+               return &emu->x86.R_SI;
+       case 7:
+               return &emu->x86.R_DI;
+       default:
+               x86emu_halt_sys(emu);
+       }
+}
+
+static uint16_t *
+decode_rl_word_register(struct x86emu *emu)
+{
+       return decode_rm_word_register(emu, emu->cur_rl);
+}
+
+static uint16_t *
+decode_rh_word_register(struct x86emu *emu)
+{
+       return decode_rm_word_register(emu, emu->cur_rh);
+}
+
+/*
+ * PARAMETERS:
+ * reg - Register to decode
+ * 
+ * RETURNS:
+ * Pointer to the appropriate register
+ * 
+ * REMARKS:
+ * Return a pointer to the register given by the R/RM field of the
+ * modrm byte, for dword operands.  Also enables the decoding of instructions.
+ */
+static uint32_t *
+decode_rm_long_register(struct x86emu *emu, int reg)
+{
+       switch (reg) {
+       case 0:
+               return &emu->x86.R_EAX;
+       case 1:
+               return &emu->x86.R_ECX;
+       case 2:
+               return &emu->x86.R_EDX;
+       case 3:
+               return &emu->x86.R_EBX;
+       case 4:
+               return &emu->x86.R_ESP;
+       case 5:
+               return &emu->x86.R_EBP;
+       case 6:
+               return &emu->x86.R_ESI;
+       case 7:
+               return &emu->x86.R_EDI;
+       default:
+               x86emu_halt_sys(emu);
+       }
+}
+
+static uint32_t *
+decode_rl_long_register(struct x86emu *emu)
+{
+       return decode_rm_long_register(emu, emu->cur_rl);
+}
+
+static uint32_t *
+decode_rh_long_register(struct x86emu *emu)
+{
+       return decode_rm_long_register(emu, emu->cur_rh);
+}
+
+
+/*
+ * PARAMETERS:
+ * reg - Register to decode
+ * 
+ * RETURNS:
+ * Pointer to the appropriate register
+ * 
+ * REMARKS:
+ * Return a pointer to the register given by the R/RM field of the
+ * modrm byte, for word operands, modified from above for the weirdo
+ * special case of segreg operands.  Also enables the decoding of instructions.
+ */
+static uint16_t *
+decode_rh_seg_register(struct x86emu *emu)
+{
+       switch (emu->cur_rh) {
+       case 0:
+               return &emu->x86.R_ES;
+       case 1:
+               return &emu->x86.R_CS;
+       case 2:
+               return &emu->x86.R_SS;
+       case 3:
+               return &emu->x86.R_DS;
+       case 4:
+               return &emu->x86.R_FS;
+       case 5:
+               return &emu->x86.R_GS;
+       default:
+               x86emu_halt_sys(emu);
+       }
+}
+/*
+ *
+ * return offset from the SIB Byte
+ */
+static uint32_t 
+decode_sib_address(struct x86emu *emu, int sib, int mod)
+{
+       uint32_t base = 0, i = 0, scale = 1;
+
+       switch (sib & 0x07) {
+       case 0:
+               base = emu->x86.R_EAX;
+               break;
+       case 1:
+               base = emu->x86.R_ECX;
+
+               break;
+       case 2:
+               base = emu->x86.R_EDX;
+               break;
+       case 3:
+               base = emu->x86.R_EBX;
+               break;
+       case 4:
+               base = emu->x86.R_ESP;
+               emu->x86.mode |= SYSMODE_SEG_DS_SS;
+               break;
+       case 5:
+               if (mod == 0) {
+                       base = fetch_long_imm(emu);
+               } else {
+                       base = emu->x86.R_EBP;
+                       emu->x86.mode |= SYSMODE_SEG_DS_SS;
+               }
+               break;
+       case 6:
+               base = emu->x86.R_ESI;
+               break;
+       case 7:
+               base = emu->x86.R_EDI;
+               break;
+       }
+       switch ((sib >> 3) & 0x07) {
+       case 0:
+               i = emu->x86.R_EAX;
+               break;
+       case 1:
+               i = emu->x86.R_ECX;
+               break;
+       case 2:
+               i = emu->x86.R_EDX;
+               break;
+       case 3:
+               i = emu->x86.R_EBX;
+               break;
+       case 4:
+               i = 0;
+               break;
+       case 5:
+               i = emu->x86.R_EBP;
+               break;
+       case 6:
+               i = emu->x86.R_ESI;
+               break;
+       case 7:
+               i = emu->x86.R_EDI;
+               break;
+       }
+       scale = 1 << ((sib >> 6) & 0x03);
+       return base + (i * scale);
+}
+
+/*
+ * PARAMETERS:
+ * rm  - RM value to decode
+ * 
+ * RETURNS:
+ * Offset in memory for the address decoding
+ * 
+ * REMARKS:
+ * Return the offset given by mod=00, mod=01 or mod=10 addressing.
+ * Also enables the decoding of instructions.
+ */
+static uint32_t
+decode_rl_address(struct x86emu *emu)
+{
+       if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
+               uint32_t offset, sib;
+               /* 32-bit addressing */
+               switch (emu->cur_rl) {
+               case 0:
+                       offset = emu->x86.R_EAX;
+                       break;
+               case 1:
+                       offset = emu->x86.R_ECX;
+                       break;
+               case 2:
+                       offset = emu->x86.R_EDX;
+                       break;
+               case 3:
+                       offset = emu->x86.R_EBX;
+                       break;
+               case 4:
+                       sib = fetch_byte_imm(emu);
+                       offset = decode_sib_address(emu, sib, 0);
+                       break;
+               case 5:
+                       if (emu->cur_mod == 0) {
+                               offset = fetch_long_imm(emu);
+                       } else {
+                               emu->x86.mode |= SYSMODE_SEG_DS_SS;
+                               offset = emu->x86.R_EBP;
+                       }
+                       break;
+               case 6:
+                       offset = emu->x86.R_ESI;
+                       break;
+               case 7:
+                       offset = emu->x86.R_EDI;
+                       break;
+               default:
+                       x86emu_halt_sys(emu);
+               }
+               if (emu->cur_mod == 1)
+                       offset += (int8_t)fetch_byte_imm(emu);
+               else if (emu->cur_mod == 2)
+                       offset += fetch_long_imm(emu);
+               return offset;
+       } else {
+               uint16_t offset;
+
+               /* 16-bit addressing */
+               switch (emu->cur_rl) {
+               case 0:
+                       offset = emu->x86.R_BX + emu->x86.R_SI;
+                       break;
+               case 1:
+                       offset = emu->x86.R_BX + emu->x86.R_DI;
+                       break;
+               case 2:
+                       emu->x86.mode |= SYSMODE_SEG_DS_SS;
+                       offset = emu->x86.R_BP + emu->x86.R_SI;
+                       break;
+               case 3:
+                       emu->x86.mode |= SYSMODE_SEG_DS_SS;
+                       offset = emu->x86.R_BP + emu->x86.R_DI;
+                       break;
+               case 4:
+                       offset = emu->x86.R_SI;
+                       break;
+               case 5:
+                       offset = emu->x86.R_DI;
+                       break;
+               case 6:
+                       if (emu->cur_mod == 0) {
+                               offset = fetch_word_imm(emu);
+                       } else {
+                               emu->x86.mode |= SYSMODE_SEG_DS_SS;
+                               offset = emu->x86.R_BP;
+                       }
+                       break;
+               case 7:
+                       offset = emu->x86.R_BX;
+                       break;
+               default:
+                       x86emu_halt_sys(emu);
+               }
+               if (emu->cur_mod == 1)
+                       offset += (int8_t)fetch_byte_imm(emu);
+               else if (emu->cur_mod == 2)
+                       offset += fetch_word_imm(emu);
+               return offset;
+       }
+}
+
+static uint8_t
+decode_and_fetch_byte(struct x86emu *emu)
+{
+       if (emu->cur_mod != 3) {
+               emu->cur_offset = decode_rl_address(emu);
+               return fetch_data_byte(emu, emu->cur_offset);
+       } else {
+               return *decode_rl_byte_register(emu);
+       }
+}
+
+static uint16_t
+decode_and_fetch_word_disp(struct x86emu *emu, int16_t disp)
+{
+       if (emu->cur_mod != 3) {
+               /* TODO: A20 gate emulation */
+               emu->cur_offset = decode_rl_address(emu) + disp;
+               if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to