Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Sep 2009 01:14:25 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r197007 - in vendor-sys/x86emu: . dist
Message-ID:  <200909090114.n891EPnm067855@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909090114.n891EPnm067855>