svn commit: r197007 - in vendor-sys/x86emu: . dist
Xin LI
delphij at FreeBSD.org
Wed Sep 9 01:14:25 UTC 2009
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 ***
More information about the svn-src-all
mailing list