pax_global_header00006660000000000000000000000064115320173130014506gustar00rootroot0000000000000052 comment=e3bde5d9d4e433c4f8ccd2c7020d36e66712a835 v86d-0.1.10/000077500000000000000000000000001153201731300123545ustar00rootroot00000000000000v86d-0.1.10/.gitignore000066400000000000000000000000701153201731300143410ustar00rootroot00000000000000libs/x86emu/libx86emu.a kernel config.h helper v86d *.o v86d-0.1.10/AUTHORS000066400000000000000000000002531153201731300134240ustar00rootroot00000000000000v86d (c) 2007, Michal Januszewski LRMI (c) Josh Vanderhoof et al., see libs/lrmi-0.10/README x86emu (c) SciTech Software, Inc, see libs/x86emu/LICENSE v86d-0.1.10/ChangeLog000066400000000000000000000032171153201731300141310ustar00rootroot000000000000002008-10-04 * 0.1.9 - Fix a off-by-one error in the VBE string copy function. - Fix concurrent build. - Don't map memory with PROT_EXEC for x86emu. - Remove dynamically generated code from LRMI. 2008-09-21 * 0.1.8 - Fix PaX compatibility (patch by the PaX team). - Fix a bug where lrmi would not map the last segment of low RAM (patch by PaX team). 2008-09-14 * 0.1.7 - Map the VRAM and Video ROM/System ROM seperately in lrmi (should fix PaX/NX-related problems). - Map 0xe0000-0xfffff instead of 0xf0000-0xfffff. 2008-07-26 * 0.1.6 - Add support for BSWAP and CPUID in x86emu. - Add support for SMSW and fix a bug in INS/OUTS (patch by Mark Karpeles ). - Properly map the BIOS and Video BIOS memory segments. Try to find and map the EBDA (x86emu). 2008-07-16 * 0.1.5.2 - Fix compatibility with NX and PaX. 2008-07-15 * 0.1.5.1 - Make LRMI compile with 2.6.26 kernel headers. 2008-05-01 * 0.1.5 - Don't map memory beyond 0x10000 (this fixes the problem with devmem_is_allowed() denying access to /dev/mem in recent kernels). 2008-04-19 * 0.1.4 - Fix error handling in the case of a failed v86 memory allocation. 2007-12-03 * 0.1.3 - Fix the VBE Info Block retrieval from the Video ROM. 2007-11-04 * 0.1.2 - Info display formatting changes in testvbe. - Add the '--with-debug' configure option. 2007-10-22 * 0.1.1 - LRMI bugfix: map the IVTBDA as shared memory. - Update testvbe to display basic information about the Video BIOS. 2007-09-04 * 0.1 - No changes since 0.1-rc5. 2007-08-07 * 0.1-rc5 - Change the v86 memory access functions so that they no longer require mapping files into the first 1 MB of the address space. v86d-0.1.10/Makefile000066400000000000000000000027371153201731300140250ustar00rootroot00000000000000config_opt = $(shell if [ -e config.h -a -n "`egrep '^\#define[[:space:]]+$(1)([[:space:]]+|$$)' config.h 2>/dev/null`" ]; then echo true ; fi) .PHONY: clean install install_testvbe x86emu lrmi INSTALL = install KDIR ?= /lib/modules/$(shell uname -r)/source ifeq ($(call config_opt,CONFIG_KLIBC),true) export CC = klcc endif CFLAGS ?= -Wall -g -O2 CFLAGS += -I$(KDIR)/include ifeq ($(call config_opt,CONFIG_X86EMU),true) CFLAGS += -Ilibs/x86emu LDFLAGS += -Llibs/x86emu LDLIBS += -lx86emu V86OBJS = v86_x86emu.o v86_mem.o v86_common.o V86LIB = x86emu else CFLAGS += -Ilibs/lrmi-0.10 LDFLAGS += -Llibs/lrmi-0.10 -static -Wl,--section-start,vm86_ret=0x9000 LDLIBS += -llrmi V86OBJS = v86_lrmi.o v86_common.o V86LIB = lrmi endif DEBUG_BUILD = DEBUG_INSTALL = ifeq ($(call config_opt,CONFIG_DEBUG),true) DEBUG_BUILD += testvbe DEBUG_INSTALL += install_testvbe endif all: $(V86LIB) v86d $(DEBUG_BUILD) %.o: %.c v86.h $(CC) $(CFLAGS) -c -o $@ $< v86d: $(V86OBJS) $(V86LIB) v86.o $(CC) $(LDFLAGS) $(V86OBJS) v86.o $(LDLIBS) -o $@ testvbe: $(V86OBJS) $(V86LIB) testvbe.o $(CC) $(LDFLAGS) $(V86OBJS) testvbe.o $(LDLIBS) -o $@ x86emu: $(MAKE) -w -C libs/x86emu lrmi: $(MAKE) -e -w -C libs/lrmi-0.10 liblrmi.a clean: rm -rf *.o v86d testvbe $(MAKE) -w -C libs/lrmi-0.10 clean $(MAKE) -w -C libs/x86emu clean distclean: clean rm -rf config.h install: $(DEBUG_INSTALL) $(INSTALL) -D v86d $(DESTDIR)/sbin/v86d install_testvbe: $(INSTALL) -D testvbe $(DESTDIR)/sbin/testvbe v86d-0.1.10/README000066400000000000000000000040601153201731300132340ustar00rootroot00000000000000v86d -- A x86 Emulation Daemon ------------------------------ 1. Purpose ---------- v86d provides a backend for kernel drivers that need to execute x86 BIOS code. The code is executed in a controlled environment and the results are passed back to the kernel via the netlink interface. 2. Suported architectures ------------------------- This version of v86d supports the following architectures: x86, x86-64 (amd64). 3. Configuration ---------------- 3.1. The C library ------------------ v86d can be compiled against two different C libraries: glibc and klibc, glibc being the default. Compiling against glibc will result in a dynamically linked executable that is not suitable for inclusion in initrds. Compiling against klibc will result in a relatively small, statically linked binary, which can be included in an initrd. To compile v86d against klibc, run ./configure --with-klibc after making sure that a recent (1.4 or newer) version of klibc is installed on your system. 3.2. The emulator backend ------------------------- On x86, the code executed by v86d can be run either in a fully software-emulated environment (x86emu) or a virtualized environment (vm86) supported by the CPU. On other arches or 64-bit systems, the code is always run by x86emu. To choose the x86emu backend on a x86 system, run ./configure --with-x86emu. 4. Installation & Usage ----------------------- To configure, build and install v86d with the default settings, run: # ./configure --default # make # make install If the kernel that you're currently running doesn't provide uvesafb, you can use the KDIR variable to point make to a different kernel tree (e.g. `make KDIR=/usr/src/linux`). v86d isn't meant to be used in an interactive way. It should be started and called by the kernel. If you want to see it in action, build and load the uvesafb kernel module. If you want to include v86d into an initramfs image, misc/initramfs provides a minimal config file parsable by gen_init_cpio. 5. Licensing ------------ v86d is licensed under GPL v2. -- Michal Januszewski v86d-0.1.10/TODO000066400000000000000000000002531153201731300130440ustar00rootroot00000000000000general: - printing to tty1 from v86d causes a hang (to be expected due to how the console sem is handled in the kernel) x86emu: - switch to Paulo Marques' version (?) v86d-0.1.10/configure000077500000000000000000000051221153201731300142630ustar00rootroot00000000000000#!/bin/bash # # ./configure -- A very simple configure script for v86d. # # (c) 2006-2007, Michal Januszewski # # In time, it will be replaced by a fully-fledged version. # copt_klibc=CONFIG_KLIBC copt_klibc_desc="Link statically against klibc" copt_klibc_type="bool" copt_klibc_def=n copt_debug=CONFIG_DEBUG copt_debug_desc="Use additional debugging features" copt_debug_type="bool" copt_debug_def=n copt_x86emu=CONFIG_X86EMU copt_x86emu_desc="Use x86emu for BIOS calls" copt_x86emu_type="bool" copt_x86emu_def=auto copt_x86emu_test() { local m=`uname -m` if [ "$m" = "i686" -o "$m" = "i586" -o "$m" = "i486" -o "$m" = "i386" ]; then echo "n"; elif [ "$m" = "x86_64" ]; then echo "y"; else echo "It looks like your architecture '$m' isn't supported by this version of v86d." >&2 exit 1 fi } options=`set | grep '^copt_' | sed -re 's/copt_([^_=]+)[_=].*/\1/' | uniq` write_conf() { echo -n > config.h for i in ${options} ; do eval vval=\$copt_$i\_val eval vtype=\$copt_$i\_type eval vname=\$copt_$i if [[ "$vtype" == "bool" ]]; then if [[ "$vval" == "y" ]]; then echo "#define $vname" >> config.h else echo "#undef $vname" >> config.h fi else echo "#define $vname \"$vval\"" >> config.h fi done echo "config.h successfully created." echo "You can run \`make\` now." } usage() { cat <&2 exit fi eval vtype=\$copt_${optname}_type if [[ "$vtype" == "bool" ]]; then eval copt_${optname}_val=${with} else eval copt_${optname}_val=${optval} fi done write_conf exit v86d-0.1.10/libs/000077500000000000000000000000001153201731300133055ustar00rootroot00000000000000v86d-0.1.10/libs/lrmi-0.10/000077500000000000000000000000001153201731300146245ustar00rootroot00000000000000v86d-0.1.10/libs/lrmi-0.10/Makefile000066400000000000000000000025161153201731300162700ustar00rootroot00000000000000LIBDIR ?= /usr/local/lib INCDIR ?= /usr/local/include CFLAGS = -g -Wall sources = lrmi.c objects = lrmi.o pic_objects = lrmi.lo all = liblrmi.a liblrmi.so vbetest MAJOR = 0 MINOR = 10 VERSION = $(MAJOR).$(MINOR) LIBNAME = liblrmi %.o: %.c $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< %.lo: %.c $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ $< all: $(all) liblrmi.a: $(objects) $(AR) -rs $@ $^ liblrmi.so: $(pic_objects) # $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -shared -o $@ $^ $(CC) $(CPPFLAGS) $(CFLAGS) -Wl,-soname,$(LIBNAME).so.$(MAJOR) -Wl,--section-start,vm86_ret=0x9000 -fPIC -shared -o $(LIBNAME).so.$(VERSION) $^ ln -sf $(LIBNAME).so.$(VERSION) $(LIBNAME).so.$(MAJOR) ln -sf $(LIBNAME).so.$(MAJOR) $(LIBNAME).so vbetest: vbetest.c liblrmi.a $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ install: mkdir -p $(LIBDIR) install -m 755 -s -p $(LIBNAME).so.$(VERSION) $(LIBDIR)/$(LIBNAME).so.$(VERSION) rm -f $(LIBDIR)/$(LIBNAME).so ln -sf $(LIBNAME).so.$(VERSION) $(LIBDIR)/$(LIBNAME).so.$(MAJOR) ln -sf $(LIBNAME).so.$(MAJOR) $(LIBDIR)/$(LIBNAME).so install -m 644 -s -p lrmi.h $(INCDIR)/lrmi.h ldconfig .PHONY: clean clean: rm -f $(objects) $(pic_objects) $(all) core rm -f liblrmi.so liblrmi.so.$(MAJOR) liblrmi.so.$(VERSION) .PHONY: distclean distclean: clean rm -f .depend .PHONY: depend depend: $(sources) -$(CC) -M $(CPPFLAGS) $^ >.depend v86d-0.1.10/libs/lrmi-0.10/Makefile.bsd000066400000000000000000000013231153201731300170320ustar00rootroot00000000000000CFLAGS = -g -Wall RANLIB = ranlib OS != uname -s sources = lrmi.c lrmi.h objects = lrmi.o pic_objects = lrmi.lo all = liblrmi.a liblrmi.so vbetest .if ${OS}=="NetBSD" || ${OS}=="OpenBSD" libs= -li386 .endif all: $(all) .c.o: $(CC) -c $(CPPFLAGS) $(CFLAGS) -o ${.TARGET} ${.IMPSRC} .SUFFIXES: .lo .c.lo: $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o ${.TARGET} ${.IMPSRC} liblrmi.a: $(objects) $(AR) -r ${.TARGET} ${.ALLSRC} $(RANLIB) ${.TARGET} liblrmi.so: $(pic_objects) $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -shared -o ${.TARGET} ${.ALLSRC} ${libs} vbetest: vbetest.o liblrmi.a $(CC) $(CPPFLAGS) $(CFLAGS) -o ${.TARGET} ${.ALLSRC} ${libs} .PHONY: clean clean: rm -f $(objects) $(pic_objects) vbetest.o $(all) *.core v86d-0.1.10/libs/lrmi-0.10/README000066400000000000000000000012071153201731300155040ustar00rootroot00000000000000Linux Real Mode Interface ========================= 1, Goal This library provides a DPMI like interface under Linux and *BSD systems using vm86. There is also some VBE (VESA Bios Extension) interface utility called vbetest. 2, Supported systems Only under x86: * Linux 2.2 and above * FreeBSD * NetBSD * OpenBSD 3, License Look into the individual source files. 4, Authors Josh Vanderhoof * original author Dmitry Frolov * FreeBSD/NetBSD support Alex Beregszaszi * merged MPlayer, MPlayerXP, svgalib and LRMI versions * OpenBSD support Oleg I. Vdovikin * pthread fixes Peter Kosinar * pthread fixes v86d-0.1.10/libs/lrmi-0.10/lrmi.c000066400000000000000000000551061153201731300157420ustar00rootroot00000000000000/* Linux Real Mode Interface - A library of DPMI-like functions for Linux. Copyright (C) 1998 by Josh Vanderhoof Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \ || defined(__FreeBSD__) || defined(__OpenBSD__)) #include #include #if defined(__linux__) #include #include #ifdef USE_LIBC_VM86 #include #endif #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include #include #include #include #include #include #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ #if defined(__FreeBSD__) #include #endif #include #include #include #include #include #include "lrmi.h" /* 2.6.26+ kernels don't define the legacy masks. */ #if defined(__linux__) && !defined(TF_MASK) #define TF_MASK X86_EFLAGS_TF #define IF_MASK X86_EFLAGS_IF #define VIF_MASK X86_EFLAGS_VIF #define IOPL_MASK X86_EFLAGS_IOPL #endif #define REAL_MEM_BASE ((void *)0x10000) #define REAL_MEM_SIZE 0x40000 #define REAL_MEM_BLOCKS 0x100 struct mem_block { unsigned int size : 20; unsigned int free : 1; }; static struct { int ready; int count; struct mem_block blocks[REAL_MEM_BLOCKS]; } mem_info = { 0 }; static int read_file(char *name, void *p, size_t n) { int fd; fd = open(name, O_RDONLY); if (fd == -1) { perror("open"); return 0; } if (read(fd, p, n) != n) { perror("read"); close(fd); return 0; } close(fd); return 1; } static int map_file(void *start, size_t length, int prot, int flags, char *name, long offset) { void *m; int fd; fd = open(name, (flags & MAP_SHARED) ? O_RDWR : O_RDONLY); if (fd == -1) { perror("open"); return 0; } m = mmap(start, length, prot, flags, fd, offset); if (m == (void *)-1) { perror("mmap"); close(fd); return 0; } close(fd); return 1; } static int real_mem_init(void) { if (mem_info.ready) return 1; if (!map_file((void *)REAL_MEM_BASE, REAL_MEM_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, "/dev/zero", 0)) return 0; mem_info.ready = 1; mem_info.count = 1; mem_info.blocks[0].size = REAL_MEM_SIZE; mem_info.blocks[0].free = 1; return 1; } static void real_mem_deinit(void) { if (mem_info.ready) { munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE); mem_info.ready = 0; } } static void insert_block(int i) { memmove( mem_info.blocks + i + 1, mem_info.blocks + i, (mem_info.count - i) * sizeof(struct mem_block)); mem_info.count++; } static void delete_block(int i) { mem_info.count--; memmove( mem_info.blocks + i, mem_info.blocks + i + 1, (mem_info.count - i) * sizeof(struct mem_block)); } void * LRMI_alloc_real(int size) { int i; char *r = (char *)REAL_MEM_BASE; if (!mem_info.ready) return NULL; if (mem_info.count == REAL_MEM_BLOCKS) return NULL; size = (size + 15) & ~15; for (i = 0; i < mem_info.count; i++) { if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) { insert_block(i); mem_info.blocks[i].size = size; mem_info.blocks[i].free = 0; mem_info.blocks[i + 1].size -= size; return (void *)r; } r += mem_info.blocks[i].size; } return NULL; } void LRMI_free_real(void *m) { int i; char *r = (char *)REAL_MEM_BASE; if (!mem_info.ready) return; i = 0; while (m != (void *)r) { r += mem_info.blocks[i].size; i++; if (i == mem_info.count) return; } mem_info.blocks[i].free = 1; if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) { mem_info.blocks[i].size += mem_info.blocks[i + 1].size; delete_block(i + 1); } if (i - 1 >= 0 && mem_info.blocks[i - 1].free) { mem_info.blocks[i - 1].size += mem_info.blocks[i].size; delete_block(i); } } #if defined(__linux__) #define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) #define DEFAULT_VM86_FLAGS (PSL_I | PSL_IOPL) #define TF_MASK PSL_T #define VIF_MASK PSL_VIF #endif #define DEFAULT_STACK_SIZE 0x1000 #define RETURN_TO_32_INT 255 #if defined(__linux__) #define CONTEXT_REGS context.vm.regs #define REG(x) x #elif defined(__NetBSD__) || defined(__OpenBSD__) #define CONTEXT_REGS context.vm.substr.regs #define REG(x) vmsc.sc_ ## x #elif defined(__FreeBSD__) #define CONTEXT_REGS context.vm.uc #define REG(x) uc_mcontext.mc_ ## x #endif static struct { int ready; unsigned short ret_seg, ret_off; unsigned short stack_seg, stack_off; #if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) struct vm86_struct vm; #elif defined(__FreeBSD__) struct { struct vm86_init_args init; ucontext_t uc; } vm; #endif #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) int success; jmp_buf env; void *old_sighandler; int vret; #endif } context = { 0 }; static inline void set_bit(unsigned int bit, void *array) { unsigned char *a = array; a[bit / 8] |= (1 << (bit % 8)); } static inline unsigned int get_int_seg(int i) { return *(unsigned short *)(i * 4 + 2); } static inline unsigned int get_int_off(int i) { return *(unsigned short *)(i * 4); } static inline void pushw(unsigned short i) { CONTEXT_REGS.REG(esp) -= 2; *(unsigned short *)(((unsigned int)CONTEXT_REGS.REG(ss) << 4) + CONTEXT_REGS.REG(esp)) = i; } int LRMI_init(void) { void *m; if (context.ready) return 1; if (!real_mem_init()) return 0; /* Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) and the ROM (0xa0000 - 0x100000) */ /* * v86d: map the IVTBDA area as shared, see note in v86_mem.c for * an explanation */ if (!map_file((void *)0, 0x502, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, "/dev/mem", 0)) { real_mem_deinit(); return 0; } if (!map_file((void *)0xa0000, 0x20000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, "/dev/mem", 0xa0000)) { munmap((void *)0, 0x502); real_mem_deinit(); return 0; } if (!map_file((void *)0xc0000, 0x40000, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED, "/dev/mem", 0xc0000)) { munmap((void *)0, 0x502); munmap((void *)0xa0000, 0x20000); real_mem_deinit(); return 0; } /* Allocate a stack */ m = LRMI_alloc_real(DEFAULT_STACK_SIZE); context.stack_seg = (unsigned int)m >> 4; context.stack_off = DEFAULT_STACK_SIZE; #if defined(__linux__) /* The return to 32-bit code (vm86_ret section) is linked into the absolute address 0x9000. */ context.ret_seg = 0x0900; context.ret_off = 0x0000; asm (".pushsection vm86_ret, \"ax\"\nint %0\n.popsection" : /* no return value */ : "i" (RETURN_TO_32_INT)); #else /* Allocate the return to 32 bit routine */ m = LRMI_alloc_real(2); context.ret_seg = (unsigned int)m >> 4; context.ret_off = (unsigned int)m & 0xf; ((unsigned char *)m)[0] = 0xcd; /* int opcode */ ((unsigned char *)m)[1] = RETURN_TO_32_INT; #endif /* __linux__ */ memset(&context.vm, 0, sizeof(context.vm)); /* Enable kernel emulation of all ints except RETURN_TO_32_INT */ #if defined(__linux__) memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); #elif defined(__NetBSD__) || defined(__OpenBSD__) set_bit(RETURN_TO_32_INT, &context.vm.int_byuser); #elif defined(__FreeBSD__) set_bit(RETURN_TO_32_INT, &context.vm.init.int_map); #endif context.ready = 1; return 1; } static void set_regs(struct LRMI_regs *r) { CONTEXT_REGS.REG(edi) = r->edi; CONTEXT_REGS.REG(esi) = r->esi; CONTEXT_REGS.REG(ebp) = r->ebp; CONTEXT_REGS.REG(ebx) = r->ebx; CONTEXT_REGS.REG(edx) = r->edx; CONTEXT_REGS.REG(ecx) = r->ecx; CONTEXT_REGS.REG(eax) = r->eax; CONTEXT_REGS.REG(eflags) = DEFAULT_VM86_FLAGS; CONTEXT_REGS.REG(es) = r->es; CONTEXT_REGS.REG(ds) = r->ds; CONTEXT_REGS.REG(fs) = r->fs; CONTEXT_REGS.REG(gs) = r->gs; } static void get_regs(struct LRMI_regs *r) { r->edi = CONTEXT_REGS.REG(edi); r->esi = CONTEXT_REGS.REG(esi); r->ebp = CONTEXT_REGS.REG(ebp); r->ebx = CONTEXT_REGS.REG(ebx); r->edx = CONTEXT_REGS.REG(edx); r->ecx = CONTEXT_REGS.REG(ecx); r->eax = CONTEXT_REGS.REG(eax); r->flags = CONTEXT_REGS.REG(eflags); r->es = CONTEXT_REGS.REG(es); r->ds = CONTEXT_REGS.REG(ds); r->fs = CONTEXT_REGS.REG(fs); r->gs = CONTEXT_REGS.REG(gs); } #define DIRECTION_FLAG (1 << 10) enum { CSEG = 0x2e, SSEG = 0x36, DSEG = 0x3e, ESEG = 0x26, FSEG = 0x64, GSEG = 0x65, }; static void em_ins(int size) { unsigned int edx, edi; edx = CONTEXT_REGS.REG(edx) & 0xffff; edi = CONTEXT_REGS.REG(edi) & 0xffff; edi += (unsigned int)CONTEXT_REGS.REG(es) << 4; if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) { if (size == 4) asm volatile ("std; insl; cld" : "=D" (edi) : "d" (edx), "0" (edi)); else if (size == 2) asm volatile ("std; insw; cld" : "=D" (edi) : "d" (edx), "0" (edi)); else asm volatile ("std; insb; cld" : "=D" (edi) : "d" (edx), "0" (edi)); } else { if (size == 4) asm volatile ("cld; insl" : "=D" (edi) : "d" (edx), "0" (edi)); else if (size == 2) asm volatile ("cld; insw" : "=D" (edi) : "d" (edx), "0" (edi)); else asm volatile ("cld; insb" : "=D" (edi) : "d" (edx), "0" (edi)); } edi -= (unsigned int)CONTEXT_REGS.REG(es) << 4; CONTEXT_REGS.REG(edi) &= 0xffff0000; CONTEXT_REGS.REG(edi) |= edi & 0xffff; } static void em_rep_ins(int size) { unsigned int cx; cx = CONTEXT_REGS.REG(ecx) & 0xffff; while (cx--) em_ins(size); CONTEXT_REGS.REG(ecx) &= 0xffff0000; } static void em_outs(int size, int seg) { unsigned int edx, esi, base; edx = CONTEXT_REGS.REG(edx) & 0xffff; esi = CONTEXT_REGS.REG(esi) & 0xffff; switch (seg) { case CSEG: base = CONTEXT_REGS.REG(cs); break; case SSEG: base = CONTEXT_REGS.REG(ss); break; case ESEG: base = CONTEXT_REGS.REG(es); break; case FSEG: base = CONTEXT_REGS.REG(fs); break; case GSEG: base = CONTEXT_REGS.REG(gs); break; default: case DSEG: base = CONTEXT_REGS.REG(ds); break; } esi += base << 4; if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) { if (size == 4) asm volatile ("std; outsl; cld" : "=S" (esi) : "d" (edx), "0" (esi)); else if (size == 2) asm volatile ("std; outsw; cld" : "=S" (esi) : "d" (edx), "0" (esi)); else asm volatile ("std; outsb; cld" : "=S" (esi) : "d" (edx), "0" (esi)); } else { if (size == 4) asm volatile ("cld; outsl" : "=S" (esi) : "d" (edx), "0" (esi)); else if (size == 2) asm volatile ("cld; outsw" : "=S" (esi) : "d" (edx), "0" (esi)); else asm volatile ("cld; outsb" : "=S" (esi) : "d" (edx), "0" (esi)); } esi -= base << 4; CONTEXT_REGS.REG(esi) &= 0xffff0000; CONTEXT_REGS.REG(esi) |= esi & 0xffff; } static void em_rep_outs(int size, int seg) { unsigned int cx; cx = CONTEXT_REGS.REG(ecx) & 0xffff; while (cx--) em_outs(size, seg); CONTEXT_REGS.REG(ecx) &= 0xffff0000; } static void em_inbl(unsigned char literal) { asm volatile ("inb %w1, %b0" : "=a" (CONTEXT_REGS.REG(eax)) : "d" (literal), "0" (CONTEXT_REGS.REG(eax))); } static void em_inb(void) { asm volatile ("inb %w1, %b0" : "=a" (CONTEXT_REGS.REG(eax)) : "d" (CONTEXT_REGS.REG(edx)), "0" (CONTEXT_REGS.REG(eax))); } static void em_inw(void) { asm volatile ("inw %w1, %w0" : "=a" (CONTEXT_REGS.REG(eax)) : "d" (CONTEXT_REGS.REG(edx)), "0" (CONTEXT_REGS.REG(eax))); } static void em_inl(void) { asm volatile ("inl %w1, %0" : "=a" (CONTEXT_REGS.REG(eax)) : "d" (CONTEXT_REGS.REG(edx))); } static void em_outbl(unsigned char literal) { asm volatile ("outb %b0, %w1" : : "a" (CONTEXT_REGS.REG(eax)), "d" (literal)); } static void em_outb(void) { asm volatile ("outb %b0, %w1" : : "a" (CONTEXT_REGS.REG(eax)), "d" (CONTEXT_REGS.REG(edx))); } static void em_outw(void) { asm volatile ("outw %w0, %w1" : : "a" (CONTEXT_REGS.REG(eax)), "d" (CONTEXT_REGS.REG(edx))); } static void em_outl(void) { asm volatile ("outl %0, %w1" : : "a" (CONTEXT_REGS.REG(eax)), "d" (CONTEXT_REGS.REG(edx))); } static int emulate(void) { unsigned char *insn; struct { unsigned char seg; unsigned int size : 1; unsigned int rep : 1; } prefix = { DSEG, 0, 0 }; int i = 0; insn = (unsigned char *)((unsigned int)CONTEXT_REGS.REG(cs) << 4); insn += CONTEXT_REGS.REG(eip); while (1) { if (insn[i] == 0x66) { prefix.size = 1 - prefix.size; i++; } else if (insn[i] == 0xf3) { prefix.rep = 1; i++; } else if (insn[i] == CSEG || insn[i] == SSEG || insn[i] == DSEG || insn[i] == ESEG || insn[i] == FSEG || insn[i] == GSEG) { prefix.seg = insn[i]; i++; } else if (insn[i] == 0xf0 || insn[i] == 0xf2 || insn[i] == 0x67) { /* these prefixes are just ignored */ i++; } else if (insn[i] == 0x6c) { if (prefix.rep) em_rep_ins(1); else em_ins(1); i++; break; } else if (insn[i] == 0x6d) { if (prefix.rep) { if (prefix.size) em_rep_ins(4); else em_rep_ins(2); } else { if (prefix.size) em_ins(4); else em_ins(2); } i++; break; } else if (insn[i] == 0x6e) { if (prefix.rep) em_rep_outs(1, prefix.seg); else em_outs(1, prefix.seg); i++; break; } else if (insn[i] == 0x6f) { if (prefix.rep) { if (prefix.size) em_rep_outs(4, prefix.seg); else em_rep_outs(2, prefix.seg); } else { if (prefix.size) em_outs(4, prefix.seg); else em_outs(2, prefix.seg); } i++; break; } else if (insn[i] == 0xe4) { em_inbl(insn[i + 1]); i += 2; break; } else if (insn[i] == 0xec) { em_inb(); i++; break; } else if (insn[i] == 0xed) { if (prefix.size) em_inl(); else em_inw(); i++; break; } else if (insn[i] == 0xe6) { em_outbl(insn[i + 1]); i += 2; break; } else if (insn[i] == 0xee) { em_outb(); i++; break; } else if (insn[i] == 0xef) { if (prefix.size) em_outl(); else em_outw(); i++; break; } else return 0; } CONTEXT_REGS.REG(eip) += i; return 1; } #if defined(__linux__) /* I don't know how to make sure I get the right vm86() from libc. The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) which should be declared as "int vm86(struct vm86_struct *);" in . This just does syscall 113 with inline asm, which should work for both libc's (I hope). */ #if !defined(USE_LIBC_VM86) static int lrmi_vm86(struct vm86_struct *vm) { int r; #ifdef __PIC__ asm volatile ( "pushl %%ebx\n\t" "movl %2, %%ebx\n\t" "int $0x80\n\t" "popl %%ebx" : "=a" (r) : "0" (113), "r" (vm)); #else asm volatile ( "int $0x80" : "=a" (r) : "0" (113), "b" (vm)); #endif return r; } #else #define lrmi_vm86 vm86 #endif #endif /* __linux__ */ static void debug_info(int vret) { #ifdef LRMI_DEBUG int i; unsigned char *p; fputs("vm86() failed\n", stderr); fprintf(stderr, "return = 0x%x\n", vret); fprintf(stderr, "eax = 0x%08x\n", CONTEXT_REGS.REG(eax)); fprintf(stderr, "ebx = 0x%08x\n", CONTEXT_REGS.REG(ebx)); fprintf(stderr, "ecx = 0x%08x\n", CONTEXT_REGS.REG(ecx)); fprintf(stderr, "edx = 0x%08x\n", CONTEXT_REGS.REG(edx)); fprintf(stderr, "esi = 0x%08x\n", CONTEXT_REGS.REG(esi)); fprintf(stderr, "edi = 0x%08x\n", CONTEXT_REGS.REG(edi)); fprintf(stderr, "ebp = 0x%08x\n", CONTEXT_REGS.REG(ebp)); fprintf(stderr, "eip = 0x%08x\n", CONTEXT_REGS.REG(eip)); fprintf(stderr, "cs = 0x%04x\n", CONTEXT_REGS.REG(cs)); fprintf(stderr, "esp = 0x%08x\n", CONTEXT_REGS.REG(esp)); fprintf(stderr, "ss = 0x%04x\n", CONTEXT_REGS.REG(ss)); fprintf(stderr, "ds = 0x%04x\n", CONTEXT_REGS.REG(ds)); fprintf(stderr, "es = 0x%04x\n", CONTEXT_REGS.REG(es)); fprintf(stderr, "fs = 0x%04x\n", CONTEXT_REGS.REG(fs)); fprintf(stderr, "gs = 0x%04x\n", CONTEXT_REGS.REG(gs)); fprintf(stderr, "eflags = 0x%08x\n", CONTEXT_REGS.REG(eflags)); fputs("cs:ip = [ ", stderr); p = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + (CONTEXT_REGS.REG(eip) & 0xffff)); for (i = 0; i < 16; ++i) fprintf(stderr, "%02x ", (unsigned int)p[i]); fputs("]\n", stderr); #endif } #if defined(__linux__) static int run_vm86(void) { unsigned int vret; sigset_t all_sigs, old_sigs; unsigned long old_gs, old_fs; while (1) { // FIXME: may apply this to BSD equivalents? sigfillset(&all_sigs); sigprocmask(SIG_SETMASK, &all_sigs, &old_sigs); asm volatile ("mov %%gs, %0" : "=rm" (old_gs)); asm volatile ("mov %%fs, %0" : "=rm" (old_fs)); vret = lrmi_vm86(&context.vm); asm volatile ("mov %0, %%gs" :: "rm" (old_gs)); asm volatile ("mov %0, %%fs" :: "rm" (old_fs)); sigprocmask(SIG_SETMASK, &old_sigs, NULL); if (VM86_TYPE(vret) == VM86_INTx) { unsigned int v = VM86_ARG(vret); if (v == RETURN_TO_32_INT) return 1; pushw(CONTEXT_REGS.REG(eflags)); pushw(CONTEXT_REGS.REG(cs)); pushw(CONTEXT_REGS.REG(eip)); CONTEXT_REGS.REG(cs) = get_int_seg(v); CONTEXT_REGS.REG(eip) = get_int_off(v); CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); continue; } if (VM86_TYPE(vret) != VM86_UNKNOWN) break; if (!emulate()) break; } debug_info(vret); return 0; } #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) #if defined(__NetBSD__) || defined(__OpenBSD__) static void vm86_callback(int sig, int code, struct sigcontext *sc) { /* Sync our context with what the kernel develivered to us. */ memcpy(&CONTEXT_REGS, sc, sizeof(*sc)); switch (VM86_TYPE(code)) { case VM86_INTx: { unsigned int v = VM86_ARG(code); if (v == RETURN_TO_32_INT) { context.success = 1; longjmp(context.env, 1); } pushw(CONTEXT_REGS.REG(eflags)); pushw(CONTEXT_REGS.REG(cs)); pushw(CONTEXT_REGS.REG(eip)); CONTEXT_REGS.REG(cs) = get_int_seg(v); CONTEXT_REGS.REG(eip) = get_int_off(v); CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); break; } case VM86_UNKNOWN: if (emulate() == 0) { context.success = 0; context.vret = code; longjmp(context.env, 1); } break; default: context.success = 0; context.vret = code; longjmp(context.env, 1); return; } /* ...and sync our context back to the kernel. */ memcpy(sc, &CONTEXT_REGS, sizeof(*sc)); } #elif defined(__FreeBSD__) static void vm86_callback(int sig, int code, struct sigcontext *sc) { unsigned char *addr; /* Sync our context with what the kernel develivered to us. */ memcpy(&CONTEXT_REGS, sc, sizeof(*sc)); if (code) { /* XXX probably need to call original signal handler here */ context.success = 0; context.vret = code; longjmp(context.env, 1); } addr = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + CONTEXT_REGS.REG(eip)); if (addr[0] == 0xcd) { /* int opcode */ if (addr[1] == RETURN_TO_32_INT) { context.success = 1; longjmp(context.env, 1); } pushw(CONTEXT_REGS.REG(eflags)); pushw(CONTEXT_REGS.REG(cs)); pushw(CONTEXT_REGS.REG(eip)); CONTEXT_REGS.REG(cs) = get_int_seg(addr[1]); CONTEXT_REGS.REG(eip) = get_int_off(addr[1]); CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); } else { if (emulate() == 0) { context.success = 0; longjmp(context.env, 1); } } /* ...and sync our context back to the kernel. */ memcpy(sc, &CONTEXT_REGS, sizeof(*sc)); } #endif /* __FreeBSD__ */ static int run_vm86(void) { if (context.old_sighandler) { #ifdef LRMI_DEBUG fprintf(stderr, "run_vm86: callback already installed\n"); #endif return (0); } #if defined(__NetBSD__) || defined(__OpenBSD__) context.old_sighandler = signal(SIGURG, (void (*)(int))vm86_callback); #elif defined(__FreeBSD__) context.old_sighandler = signal(SIGBUS, (void (*)(int))vm86_callback); #endif if (context.old_sighandler == (void *)-1) { context.old_sighandler = NULL; #ifdef LRMI_DEBUG fprintf(stderr, "run_vm86: cannot install callback\n"); #endif return (0); } if (setjmp(context.env)) { #if defined(__NetBSD__) || defined(__OpenBSD__) (void) signal(SIGURG, context.old_sighandler); #elif defined(__FreeBSD__) (void) signal(SIGBUS, context.old_sighandler); #endif context.old_sighandler = NULL; if (context.success) return (1); debug_info(context.vret); return (0); } #if defined(__NetBSD__) || defined(__OpenBSD__) if (i386_vm86(&context.vm) == -1) return (0); #elif defined(__FreeBSD__) if (i386_vm86(VM86_INIT, &context.vm.init)) return 0; CONTEXT_REGS.REG(eflags) |= PSL_VM | PSL_VIF; sigreturn(&context.vm.uc); #endif /* __FreeBSD__ */ /* NOTREACHED */ return (0); } #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ int LRMI_call(struct LRMI_regs *r) { unsigned int vret; memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS)); set_regs(r); CONTEXT_REGS.REG(cs) = r->cs; CONTEXT_REGS.REG(eip) = r->ip; if (r->ss == 0 && r->sp == 0) { CONTEXT_REGS.REG(ss) = context.stack_seg; CONTEXT_REGS.REG(esp) = context.stack_off; } else { CONTEXT_REGS.REG(ss) = r->ss; CONTEXT_REGS.REG(esp) = r->sp; } pushw(context.ret_seg); pushw(context.ret_off); vret = run_vm86(); get_regs(r); return vret; } int LRMI_int(int i, struct LRMI_regs *r) { unsigned int vret; unsigned int seg, off; seg = get_int_seg(i); off = get_int_off(i); /* If the interrupt is in regular memory, it's probably still pointing at a dos TSR (which is now gone). */ if (seg < 0xa000 || (seg << 4) + off >= 0x100000) { #ifdef LRMI_DEBUG fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); #endif return 0; } memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS)); set_regs(r); CONTEXT_REGS.REG(cs) = seg; CONTEXT_REGS.REG(eip) = off; if (r->ss == 0 && r->sp == 0) { CONTEXT_REGS.REG(ss) = context.stack_seg; CONTEXT_REGS.REG(esp) = context.stack_off; } else { CONTEXT_REGS.REG(ss) = r->ss; CONTEXT_REGS.REG(esp) = r->sp; } pushw(DEFAULT_VM86_FLAGS); pushw(context.ret_seg); pushw(context.ret_off); vret = run_vm86(); get_regs(r); return vret; } #else /* (__linux__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__) && __i386__ */ #warning "LRMI is not supported on your system!" #endif v86d-0.1.10/libs/lrmi-0.10/lrmi.h000066400000000000000000000053561153201731300157510ustar00rootroot00000000000000/* Linux Real Mode Interface - A library of DPMI-like functions for Linux. Copyright (C) 1998 by Josh Vanderhoof Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LRMI_H #define LRMI_H #if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \ || defined(__FreeBSD__) || defined(__OpenBSD__)) struct LRMI_regs { unsigned int edi; unsigned int esi; unsigned int ebp; unsigned int reserved; unsigned int ebx; unsigned int edx; unsigned int ecx; unsigned int eax; unsigned short int flags; unsigned short int es; unsigned short int ds; unsigned short int fs; unsigned short int gs; unsigned short int ip; unsigned short int cs; unsigned short int sp; unsigned short int ss; }; #ifndef LRMI_PREFIX #define LRMI_PREFIX LRMI_ #endif #define LRMI_CONCAT2(a, b) a ## b #define LRMI_CONCAT(a, b) LRMI_CONCAT2(a, b) #define LRMI_MAKENAME(a) LRMI_CONCAT(LRMI_PREFIX, a) /* Package version (high 16bit = major, low 16bit minor) */ #define LRMI_version 0x0009 /* 0.9 */ /* Initialize returns 1 if sucessful, 0 for failure */ #define LRMI_init LRMI_MAKENAME(init) int LRMI_init(void); /* Simulate a 16 bit far call returns 1 if sucessful, 0 for failure */ #define LRMI_call LRMI_MAKENAME(call) int LRMI_call(struct LRMI_regs *r); /* Simulate a 16 bit interrupt returns 1 if sucessful, 0 for failure */ #define LRMI_int LRMI_MAKENAME(int) int LRMI_int(int interrupt, struct LRMI_regs *r); /* Allocate real mode memory The returned block is paragraph (16 byte) aligned */ #define LRMI_alloc_real LRMI_MAKENAME(alloc_real) void * LRMI_alloc_real(int size); /* Free real mode memory */ #define LRMI_free_real LRMI_MAKENAME(free_real) void LRMI_free_real(void *m); #else /* (__linux__ || __NetBSD__ || __FreeBSD__) && __i386__ */ #warning "LRMI is not supported on your system!" #endif #endif v86d-0.1.10/libs/lrmi-0.10/vbe.h000066400000000000000000000047461153201731300155640ustar00rootroot00000000000000/* This file is in the public domain. */ #ifndef _VBE_H #define _VBE_H /* structures for vbe 2.0 */ struct vbe_info_block { char vbe_signature[4]; short vbe_version; unsigned short oem_string_off; unsigned short oem_string_seg; int capabilities; unsigned short video_mode_list_off; unsigned short video_mode_list_seg; short total_memory; short oem_software_rev; unsigned short oem_vendor_name_off; unsigned short oem_vendor_name_seg; unsigned short oem_product_name_off; unsigned short oem_product_name_seg; unsigned short oem_product_rev_off; unsigned short oem_product_rev_seg; char reserved[222]; char oem_data[256]; } __attribute__ ((packed)); #define VBE_ATTR_MODE_SUPPORTED (1 << 0) #define VBE_ATTR_TTY (1 << 2) #define VBE_ATTR_COLOR (1 << 3) #define VBE_ATTR_GRAPHICS (1 << 4) #define VBE_ATTR_NOT_VGA (1 << 5) #define VBE_ATTR_NOT_WINDOWED (1 << 6) #define VBE_ATTR_LINEAR (1 << 7) #define VBE_WIN_RELOCATABLE (1 << 0) #define VBE_WIN_READABLE (1 << 1) #define VBE_WIN_WRITEABLE (1 << 2) #define VBE_MODEL_TEXT 0 #define VBE_MODEL_CGA 1 #define VBE_MODEL_HERCULES 2 #define VBE_MODEL_PLANAR 3 #define VBE_MODEL_PACKED 4 #define VBE_MODEL_256 5 #define VBE_MODEL_RGB 6 #define VBE_MODEL_YUV 7 struct vbe_mode_info_block { unsigned short mode_attributes; unsigned char win_a_attributes; unsigned char win_b_attributes; unsigned short win_granularity; unsigned short win_size; unsigned short win_a_segment; unsigned short win_b_segment; unsigned short win_func_ptr_off; unsigned short win_func_ptr_seg; unsigned short bytes_per_scanline; unsigned short x_resolution; unsigned short y_resolution; unsigned char x_char_size; unsigned char y_char_size; unsigned char number_of_planes; unsigned char bits_per_pixel; unsigned char number_of_banks; unsigned char memory_model; unsigned char bank_size; unsigned char number_of_image_pages; unsigned char res1; unsigned char red_mask_size; unsigned char red_field_position; unsigned char green_mask_size; unsigned char green_field_position; unsigned char blue_mask_size; unsigned char blue_field_position; unsigned char rsvd_mask_size; unsigned char rsvd_field_position; unsigned char direct_color_mode_info; unsigned int phys_base_ptr; unsigned int offscreen_mem_offset; unsigned short offscreen_mem_size; unsigned char res2[206]; } __attribute__ ((packed)); struct vbe_palette_entry { unsigned char blue; unsigned char green; unsigned char red; unsigned char align; } __attribute__ ((packed)); #endif v86d-0.1.10/libs/lrmi-0.10/vbetest.c000066400000000000000000000217121153201731300164470ustar00rootroot00000000000000/* List the available VESA graphics modes. This program is in the public domain. */ #include #include #include #include #include #if defined(__linux__) #include #include #include #elif defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #elif defined(__FreeBSD__) #include #include #endif #include "lrmi.h" #include "vbe.h" struct { struct vbe_info_block *info; struct vbe_mode_info_block *mode; char *win; /* this doesn't point directly at the window, see update_window() */ int win_low, win_high; } vbe; static char *run_command = NULL; void * save_state(void) { struct LRMI_regs r; void *buffer; memset(&r, 0, sizeof(r)); r.eax = 0x4f04; r.ecx = 0xf; /* all states */ r.edx = 0; /* get buffer size */ if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't get video state buffer size (vm86 failure)\n"); return NULL; } if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Get video state buffer size failed\n"); return NULL; } buffer = LRMI_alloc_real((r.ebx & 0xffff) * 64); if (buffer == NULL) { fprintf(stderr, "Can't allocate video state buffer\n"); return NULL; } memset(&r, 0, sizeof(r)); r.eax = 0x4f04; r.ecx = 0xf; /* all states */ r.edx = 1; /* save state */ r.es = (unsigned int)buffer >> 4; r.ebx = (unsigned int)buffer & 0xf; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't save video state (vm86 failure)\n"); return NULL; } if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Save video state failed\n"); return NULL; } return buffer; } void restore_state(void *buffer) { struct LRMI_regs r; memset(&r, 0, sizeof(r)); r.eax = 0x4f04; r.ecx = 0xf; /* all states */ r.edx = 2; /* restore state */ r.es = (unsigned int)buffer >> 4; r.ebx = (unsigned int)buffer & 0xf; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't restore video state (vm86 failure)\n"); } else if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Restore video state failed\n"); } LRMI_free_real(buffer); } void text_mode(void) { struct LRMI_regs r; memset(&r, 0, sizeof(r)); r.eax = 3; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't set text mode (vm86 failure)\n"); } } int update_window(int address) { struct LRMI_regs r; int w, g; if (address >= vbe.win_low && address < vbe.win_high) return 0; g = vbe.mode->win_granularity * 1024; w = address / g; memset(&r, 0, sizeof(r)); r.eax = 0x4f05; r.ebx = 0; r.edx = w; LRMI_int(0x10, &r); vbe.win_low = w * g; vbe.win_high = vbe.win_low + vbe.mode->win_size * 1024; vbe.win = (char *)(vbe.mode->win_a_segment << 4); vbe.win -= vbe.win_low; return 1; } void set_pixel(int x, int y, int r, int g, int b) { int x_res = vbe.mode->x_resolution; int y_res = vbe.mode->y_resolution; int shift_r = vbe.mode->red_field_position; int shift_g = vbe.mode->green_field_position; int shift_b = vbe.mode->blue_field_position; int pixel_size = (vbe.mode->bits_per_pixel + 7) / 8; int bpl = vbe.mode->bytes_per_scanline; int c, addr; if (x < 0 || x >= x_res || y < 0 || y >= y_res) return; r >>= 8 - vbe.mode->red_mask_size; g >>= 8 - vbe.mode->green_mask_size; b >>= 8 - vbe.mode->blue_mask_size; c = (r << shift_r) | (g << shift_g) | (b << shift_b); addr = y * bpl + (x * pixel_size); update_window(addr); memcpy(vbe.win + addr, &c, pixel_size); } void set_mode(int n) { struct LRMI_regs r; memset(&r, 0, sizeof(r)); r.eax = 0x4f02; r.ebx = n; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't set video mode (vm86 failure)\n"); } else if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Set video mode failed\n"); } memset(&r, 0, sizeof(r)); r.eax = 0x4f01; r.ecx = n; r.es = (unsigned int)vbe.mode >> 4; r.edi = (unsigned int)vbe.mode & 0xf; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't get mode info (vm86 failure)\n"); return; } if ((r.eax & 0xffff) != 0x4f) { fprintf(stderr, "Get mode info failed\n"); return; } vbe.win_low = vbe.win_high = -1; /* Draw a colorful checkerboard */ if (vbe.mode->memory_model == VBE_MODEL_RGB) { int x_res = vbe.mode->x_resolution; int y_res = vbe.mode->y_resolution; int x, y; for (y = 0; y < y_res; ++y) { for (x = 0; x < x_res; ++x) { int r, g, b; if ((x & 16) ^ (y & 16)) { r = x * 255 / x_res; g = y * 255 / y_res; b = 255 - x * 255 / x_res; } else { r = 255 - x * 255 / x_res; g = y * 255 / y_res; b = 255 - y * 255 / y_res; } set_pixel(x, y, r, g, b); } } } } void interactive_set_mode(int n) { void *state; #if defined(__linux__) struct stat stat; #elif defined(__NetBSD__) || defined(__OpenBSD__) struct wsdisplay_fbinfo wsi; #elif defined(__FreeBSD__) struct vid_info vi; #endif if (n == -1) { printf("Type a mode number, or 'q' to quit - "); if (scanf("%d", &n) != 1) return; } #if defined(__linux__) if (fstat(0, &stat) != 0) { fprintf(stderr, "Can't stat() stdin\n"); return; } if ((stat.st_rdev & 0xff00) != 0x400 || (stat.st_rdev & 0xff) > 63) #elif defined(__NetBSD__) || defined(__OpenBSD__) if (ioctl(0, WSDISPLAYIO_GINFO, &wsi) == -1) #elif defined(__FreeBSD__) memset(&vi, 0, sizeof(vi)); vi.size = sizeof(vi); if (ioctl(0, CONS_GETINFO, &vi) == -1) #endif { fprintf(stderr, "To switch video modes, " "this program must be run from the console\n"); return; } printf("setting mode %d\n", n); #if defined(__linux__) || defined(__FreeBSD__) ioctl(0, KDSETMODE, KD_GRAPHICS); #elif defined(__NetBSD__) || defined(__OpenBSD__) ioctl(0, WSDISPLAYIO_SMODE, WSDISPLAYIO_MODE_MAPPED); #endif state = save_state(); if (state == NULL) return; set_mode(n); system(run_command); sleep(5); text_mode(); restore_state(state); #if defined(__linux__) || defined(__FreeBSD__) ioctl(0, KDSETMODE, KD_TEXT); #elif defined(__NetBSD__) || defined(__OpenBSD__) ioctl(0, WSDISPLAYIO_SMODE, WSDISPLAYIO_MODE_EMUL); #endif } void usage_and_quit(int error) { fputs("Usage: vbetest [-m mode] [-c command]\n", error ? stderr : stdout); exit(error); } int main(int argc, char *argv[]) { struct LRMI_regs r; short int *mode_list; int i, mode = -1; #if defined(__NetBSD__) || defined(__OpenBSD__) unsigned long iomap[32]; #endif for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-c") == 0) { i++; if (i == argc) usage_and_quit(1); run_command = argv[i]; } else if (strcmp(argv[i], "-m") == 0) { char *e; i++; if (i == argc) usage_and_quit(1); mode = strtol(argv[i], &e, 10); if (e == argv[i]) usage_and_quit(1); } else usage_and_quit(1); } if (!LRMI_init()) return 1; vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block) + sizeof(struct vbe_mode_info_block)); if (vbe.info == NULL) { fprintf(stderr, "Can't alloc real mode memory\n"); return 1; } vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1); #if 0 /* Allow read/write to video IO ports */ ioperm(0x2b0, 0x2df - 0x2b0, 1); ioperm(0x3b0, 0x3df - 0x3b0, 1); #else /* Allow read/write to ALL io ports */ #if defined(__linux__) ioperm(0, 1024, 1); iopl(3); #elif defined(__NetBSD__) || defined(__OpenBSD__) memset(&iomap[0], 0xff, sizeof(iomap)); i386_set_ioperm(iomap); i386_iopl(3); #elif defined(__FreeBSD__) i386_set_ioperm(0, 0x10000, 1); #endif #endif memset(&r, 0, sizeof(r)); r.eax = 0x4f00; r.es = (unsigned int)vbe.info >> 4; r.edi = 0; memcpy(vbe.info->vbe_signature, "VBE2", 4); if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't get VESA info (vm86 failure)\n"); return 1; } if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0) { fprintf(stderr, "No VESA bios\n"); return 1; } printf("VBE Version %x.%x\n", (int)(vbe.info->vbe_version >> 8) & 0xff, (int)vbe.info->vbe_version & 0xff); printf("%s\n", (char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off)); mode_list = (short int *)(vbe.info->video_mode_list_seg * 16 + vbe.info->video_mode_list_off); while (*mode_list != -1) { memset(&r, 0, sizeof(r)); r.eax = 0x4f01; r.ecx = *mode_list; r.es = (unsigned int)vbe.mode >> 4; r.edi = (unsigned int)vbe.mode & 0xf; if (!LRMI_int(0x10, &r)) { fprintf(stderr, "Can't get mode info (vm86 failure)\n"); return 1; } if (vbe.mode->memory_model == VBE_MODEL_RGB) printf("[%3d] %dx%d (%d:%d:%d)\n", *mode_list, vbe.mode->x_resolution, vbe.mode->y_resolution, vbe.mode->red_mask_size, vbe.mode->green_mask_size, vbe.mode->blue_mask_size); else if (vbe.mode->memory_model == VBE_MODEL_256) printf("[%3d] %dx%d (256 color palette)\n", *mode_list, vbe.mode->x_resolution, vbe.mode->y_resolution); else if (vbe.mode->memory_model == VBE_MODEL_PACKED) printf("[%3d] %dx%d (%d color palette)\n", *mode_list, vbe.mode->x_resolution, vbe.mode->y_resolution, 1 << vbe.mode->bits_per_pixel); mode_list++; } LRMI_free_real(vbe.info); interactive_set_mode(mode); return 0; } v86d-0.1.10/libs/x86emu/000077500000000000000000000000001153201731300144415ustar00rootroot00000000000000v86d-0.1.10/libs/x86emu/LICENSE000066400000000000000000000013421153201731300154460ustar00rootroot00000000000000 License information ------------------- The x86emu library is under a BSD style license, comaptible with the XFree86 and X licenses used by XFree86. The original x86emu libraries were under the GNU General Public License. Due to license incompatibilities between the GPL and the XFree86 license, the original authors of the code decided to allow a license change. If you have submitted code to the original x86emu project, and you don't agree with the license change, please contact us and let you know. Your code will be removed to comply with your wishes. If you have any questions about this, please send email to x86emu@linuxlabs.com or KendallB@scitechsoft.com for clarification. v86d-0.1.10/libs/x86emu/Makefile000066400000000000000000000003141153201731300160770ustar00rootroot00000000000000OBJS = decode.o fpu.o ops.o ops2.o prim_ops.o sys.o libx86emu.a: $(OBJS) ar rv $@ $+ %.o: %.c $(CC) -c $(CFLAGS) -o $@ $< CFLAGS += -I. -I../../include -I../../include/x86emu clean: rm -f *.a *.o v86d-0.1.10/libs/x86emu/debug.c000066400000000000000000000267471153201731300157130ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file contains the code to handle debugging of the * emulator. * ****************************************************************************/ #include "x86emu/x86emui.h" #ifndef NO_SYS_HEADERS #include #include #endif /*----------------------------- Implementation ----------------------------*/ #ifdef DEBUG static void print_encoded_bytes (u16 s, u16 o); static void print_decoded_instruction (void); static int parse_line (char *s, int *ps, int *n); /* should look something like debug's output. */ void X86EMU_trace_regs (void) { if (DEBUG_TRACE()) { x86emu_dump_regs(); } if (DEBUG_DECODE() && ! DEBUG_DECODE_NOPRINT()) { printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip); print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip); print_decoded_instruction(); } } void X86EMU_trace_xregs (void) { if (DEBUG_TRACE()) { x86emu_dump_xregs(); } } void x86emu_just_disassemble (void) { /* * This routine called if the flag DEBUG_DISASSEMBLE is set kind * of a hack! */ printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip); print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip); print_decoded_instruction(); } static void disassemble_forward (u16 seg, u16 off, int n) { X86EMU_sysEnv tregs; int i; u8 op1; /* * hack, hack, hack. What we do is use the exact machinery set up * for execution, except that now there is an additional state * flag associated with the "execution", and we are using a copy * of the register struct. All the major opcodes, once fully * decoded, have the following two steps: TRACE_REGS(r,m); * SINGLE_STEP(r,m); which disappear if DEBUG is not defined to * the preprocessor. The TRACE_REGS macro expands to: * * if (debug&DEBUG_DISASSEMBLE) * {just_disassemble(); goto EndOfInstruction;} * if (debug&DEBUG_TRACE) trace_regs(r,m); * * ...... and at the last line of the routine. * * EndOfInstruction: end_instr(); * * Up to the point where TRACE_REG is expanded, NO modifications * are done to any register EXCEPT the IP register, for fetch and * decoding purposes. * * This was done for an entirely different reason, but makes a * nice way to get the system to help debug codes. */ tregs = M; tregs.x86.R_IP = off; tregs.x86.R_CS = seg; /* reset the decoding buffers */ tregs.x86.enc_str_pos = 0; tregs.x86.enc_pos = 0; /* turn on the "disassemble only, no execute" flag */ tregs.x86.debug |= DEBUG_DISASSEMBLE_F; /* DUMP NEXT n instructions to screen in straight_line fashion */ /* * This looks like the regular instruction fetch stream, except * that when this occurs, each fetched opcode, upon seeing the * DEBUG_DISASSEMBLE flag set, exits immediately after decoding * the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!! * Note the use of a copy of the register structure... */ for (i=0; i 256) return; seg = fetch_data_word_abs(0,iv*4); off = fetch_data_word_abs(0,iv*4+2); printk("%04x:%04x ", seg, off); } void X86EMU_dump_memory (u16 seg, u16 off, u32 amt) { u32 start = off & 0xfffffff0; u32 end = (off+16) & 0xfffffff0; u32 i; u32 current; current = start; while (end <= off + amt) { printk("%04x:%04x ", seg, start); for (i=start; i< off; i++) printk(" "); for ( ; i< end; i++) printk("%02x ", fetch_data_byte_abs(seg,i)); printk("\n"); start = end; end = start + 16; } } void x86emu_single_step (void) { char s[1024]; int ps[10]; int ntok; int cmd; int done; int segment; int offset; static int breakpoint; static int noDecode = 1; char *p; if (DEBUG_BREAK()) { if (M.x86.saved_ip != breakpoint) { return; } else { M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; M.x86.debug |= DEBUG_TRACE_F; M.x86.debug &= ~DEBUG_BREAK_F; print_decoded_instruction (); X86EMU_trace_regs(); } } done=0; offset = M.x86.saved_ip; while (!done) { printk("-"); p = fgets(s, 1023, stdin); cmd = parse_line(s, ps, &ntok); switch(cmd) { case 'u': disassemble_forward(M.x86.saved_cs,(u16)offset,10); break; case 'd': if (ntok == 2) { segment = M.x86.saved_cs; offset = ps[1]; X86EMU_dump_memory(segment,(u16)offset,16); offset += 16; } else if (ntok == 3) { segment = ps[1]; offset = ps[2]; X86EMU_dump_memory(segment,(u16)offset,16); offset += 16; } else { segment = M.x86.saved_cs; X86EMU_dump_memory(segment,(u16)offset,16); offset += 16; } break; case 'c': M.x86.debug ^= DEBUG_TRACECALL_F; break; case 's': M.x86.debug ^= DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F; break; case 'r': X86EMU_trace_regs(); break; case 'x': X86EMU_trace_xregs(); break; case 'g': if (ntok == 2) { breakpoint = ps[1]; if (noDecode) { M.x86.debug |= DEBUG_DECODE_NOPRINT_F; } else { M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; } M.x86.debug &= ~DEBUG_TRACE_F; M.x86.debug |= DEBUG_BREAK_F; done = 1; } break; case 'q': M.x86.debug |= DEBUG_EXIT; return; case 'P': noDecode = (noDecode)?0:1; printk("Toggled decoding to %s\n",(noDecode)?"FALSE":"TRUE"); break; case 't': case 0: done = 1; break; } } } int X86EMU_trace_on(void) { return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F; } int X86EMU_trace_off(void) { return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F); } static int parse_line (char *s, int *ps, int *n) { int cmd; *n = 0; while(*s == ' ' || *s == '\t') s++; ps[*n] = *s; switch (*s) { case '\n': *n += 1; return 0; default: cmd = *s; *n += 1; } while (1) { while (*s != ' ' && *s != '\t' && *s != '\n') s++; if (*s == '\n') return cmd; while(*s == ' ' || *s == '\t') s++; sscanf(s,"%x",&ps[*n]); *n += 1; } } #endif /* DEBUG */ void x86emu_dump_regs (void) { printk("\tAX=%04x ", M.x86.R_AX ); printk("BX=%04x ", M.x86.R_BX ); printk("CX=%04x ", M.x86.R_CX ); printk("DX=%04x ", M.x86.R_DX ); printk("SP=%04x ", M.x86.R_SP ); printk("BP=%04x ", M.x86.R_BP ); printk("SI=%04x ", M.x86.R_SI ); printk("DI=%04x\n", M.x86.R_DI ); printk("\tDS=%04x ", M.x86.R_DS ); printk("ES=%04x ", M.x86.R_ES ); printk("SS=%04x ", M.x86.R_SS ); printk("CS=%04x ", M.x86.R_CS ); printk("IP=%04x ", M.x86.R_IP ); if (ACCESS_FLAG(F_OF)) printk("OV "); /* CHECKED... */ else printk("NV "); if (ACCESS_FLAG(F_DF)) printk("DN "); else printk("UP "); if (ACCESS_FLAG(F_IF)) printk("EI "); else printk("DI "); if (ACCESS_FLAG(F_SF)) printk("NG "); else printk("PL "); if (ACCESS_FLAG(F_ZF)) printk("ZR "); else printk("NZ "); if (ACCESS_FLAG(F_AF)) printk("AC "); else printk("NA "); if (ACCESS_FLAG(F_PF)) printk("PE "); else printk("PO "); if (ACCESS_FLAG(F_CF)) printk("CY "); else printk("NC "); printk("\n"); } void x86emu_dump_xregs (void) { printk("\tEAX=%08x ", M.x86.R_EAX ); printk("EBX=%08x ", M.x86.R_EBX ); printk("ECX=%08x ", M.x86.R_ECX ); printk("EDX=%08x \n", M.x86.R_EDX ); printk("\tESP=%08x ", M.x86.R_ESP ); printk("EBP=%08x ", M.x86.R_EBP ); printk("ESI=%08x ", M.x86.R_ESI ); printk("EDI=%08x\n", M.x86.R_EDI ); printk("\tDS=%04x ", M.x86.R_DS ); printk("ES=%04x ", M.x86.R_ES ); printk("SS=%04x ", M.x86.R_SS ); printk("CS=%04x ", M.x86.R_CS ); printk("EIP=%08x\n\t", M.x86.R_EIP ); if (ACCESS_FLAG(F_OF)) printk("OV "); /* CHECKED... */ else printk("NV "); if (ACCESS_FLAG(F_DF)) printk("DN "); else printk("UP "); if (ACCESS_FLAG(F_IF)) printk("EI "); else printk("DI "); if (ACCESS_FLAG(F_SF)) printk("NG "); else printk("PL "); if (ACCESS_FLAG(F_ZF)) printk("ZR "); else printk("NZ "); if (ACCESS_FLAG(F_AF)) printk("AC "); else printk("NA "); if (ACCESS_FLAG(F_PF)) printk("PE "); else printk("PO "); if (ACCESS_FLAG(F_CF)) printk("CY "); else printk("NC "); printk("\n"); } v86d-0.1.10/libs/x86emu/decode.c000066400000000000000000000717751153201731300160510ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file includes subroutines which are related to * instruction decoding and accessess of immediate data via IP. etc. * ****************************************************************************/ #include #include "x86emu/x86emui.h" /*----------------------------- Implementation ----------------------------*/ /**************************************************************************** REMARKS: Handles any pending asychronous interrupts. ****************************************************************************/ static void x86emu_intr_handle(void) { u8 intno; if (M.x86.intr & INTR_SYNCH) { intno = M.x86.intno; if (_X86EMU_intrTab[intno]) { (*_X86EMU_intrTab[intno])(intno); } else { push_word((u16)M.x86.R_FLG); CLEAR_FLAG(F_IF); CLEAR_FLAG(F_TF); push_word(M.x86.R_CS); M.x86.R_CS = mem_access_word(intno * 4 + 2); push_word(M.x86.R_IP); M.x86.R_IP = mem_access_word(intno * 4); M.x86.intr = 0; } } } /**************************************************************************** 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( u8 intrnum) { M.x86.intno = intrnum; M.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(void) { u8 op1; M.x86.intr = 0; DB(x86emu_end_instr();) for (;;) { DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) /* If debugging, save the IP and CS values. */ SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP); INC_DECODED_INST_LEN(1); if (M.x86.intr) { if (M.x86.intr & INTR_HALTED) { DB( if (M.x86.R_SP != 0) { printk("halted\n"); X86EMU_trace_regs(); } else { if (M.x86.debug) printk("Service completed successfully\n"); }) return; } if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) || !ACCESS_FLAG(F_IF)) { x86emu_intr_handle(); } } op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); (*x86emu_optab[op1])(op1); if (M.x86.debug & DEBUG_EXIT) { M.x86.debug &= ~DEBUG_EXIT; return; } } } /**************************************************************************** REMARKS: Halts the system by setting the halted system flag. ****************************************************************************/ void X86EMU_halt_sys(void) { M.x86.intr |= INTR_HALTED; } /**************************************************************************** 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 (*sys_rdb) is already inline! ****************************************************************************/ void fetch_decode_modrm( int *mod, int *regh, int *regl) { int fetched; DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); INC_DECODED_INST_LEN(1); *mod = (fetched >> 6) & 0x03; *regh = (fetched >> 3) & 0x07; *regl = (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 (*sys_rdb) is already inline! ****************************************************************************/ u8 fetch_byte_imm(void) { u8 fetched; DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); INC_DECODED_INST_LEN(1); 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 (*sys_rdw) is already inline! ****************************************************************************/ u16 fetch_word_imm(void) { u16 fetched; DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); M.x86.R_IP += 2; INC_DECODED_INST_LEN(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 (*sys_rdw) is already inline! ****************************************************************************/ u32 fetch_long_imm(void) { u32 fetched; DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); M.x86.R_IP += 4; INC_DECODED_INST_LEN(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 M.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. ****************************************************************************/ _INLINE u32 get_data_segment(void) { #define GET_SEGMENT(segment) switch (M.x86.mode & SYSMODE_SEGMASK) { case 0: /* default case: use ds register */ case SYSMODE_SEGOVR_DS: case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: return M.x86.R_DS; case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */ return M.x86.R_SS; case SYSMODE_SEGOVR_CS: case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: return M.x86.R_CS; case SYSMODE_SEGOVR_ES: case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: return M.x86.R_ES; case SYSMODE_SEGOVR_FS: case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: return M.x86.R_FS; case SYSMODE_SEGOVR_GS: case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: return M.x86.R_GS; case SYSMODE_SEGOVR_SS: case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: return M.x86.R_SS; default: #ifdef DEBUG printk("error: should not happen: multiple overrides.\n"); #endif HALT_SYS(); return 0; } } /**************************************************************************** PARAMETERS: offset - Offset to load data from RETURNS: Byte value read from the absolute memory location. NOTE: Do not inline this function as (*sys_rdX) is already inline! ****************************************************************************/ u8 fetch_data_byte( uint offset) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif return (*sys_rdb)((get_data_segment() << 4) + offset); } /**************************************************************************** PARAMETERS: offset - Offset to load data from RETURNS: Word value read from the absolute memory location. NOTE: Do not inline this function as (*sys_rdX) is already inline! ****************************************************************************/ u16 fetch_data_word( uint offset) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif return (*sys_rdw)((get_data_segment() << 4) + offset); } /**************************************************************************** PARAMETERS: offset - Offset to load data from RETURNS: Long value read from the absolute memory location. NOTE: Do not inline this function as (*sys_rdX) is already inline! ****************************************************************************/ u32 fetch_data_long( uint offset) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif return (*sys_rdl)((get_data_segment() << 4) + 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 (*sys_rdX) is already inline! ****************************************************************************/ u8 fetch_data_byte_abs( uint segment, uint offset) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif return (*sys_rdb)(((u32)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 (*sys_rdX) is already inline! ****************************************************************************/ u16 fetch_data_word_abs( uint segment, uint offset) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif return (*sys_rdw)(((u32)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 (*sys_rdX) is already inline! ****************************************************************************/ u32 fetch_data_long_abs( uint segment, uint offset) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif return (*sys_rdl)(((u32)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 (*sys_wrX) is already inline! ****************************************************************************/ void store_data_byte( uint offset, u8 val) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif (*sys_wrb)((get_data_segment() << 4) + 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 (*sys_wrX) is already inline! ****************************************************************************/ void store_data_word( uint offset, u16 val) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif (*sys_wrw)((get_data_segment() << 4) + 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 (*sys_wrX) is already inline! ****************************************************************************/ void store_data_long( uint offset, u32 val) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif (*sys_wrl)((get_data_segment() << 4) + 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 (*sys_wrX) is already inline! ****************************************************************************/ void store_data_byte_abs( uint segment, uint offset, u8 val) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif (*sys_wrb)(((u32)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 (*sys_wrX) is already inline! ****************************************************************************/ void store_data_word_abs( uint segment, uint offset, u16 val) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif (*sys_wrw)(((u32)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 (*sys_wrX) is already inline! ****************************************************************************/ void store_data_long_abs( uint segment, uint offset, u32 val) { #ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif (*sys_wrl)(((u32)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. ****************************************************************************/ u8* decode_rm_byte_register( int reg) { switch (reg) { case 0: DECODE_PRINTF("AL"); return &M.x86.R_AL; case 1: DECODE_PRINTF("CL"); return &M.x86.R_CL; case 2: DECODE_PRINTF("DL"); return &M.x86.R_DL; case 3: DECODE_PRINTF("BL"); return &M.x86.R_BL; case 4: DECODE_PRINTF("AH"); return &M.x86.R_AH; case 5: DECODE_PRINTF("CH"); return &M.x86.R_CH; case 6: DECODE_PRINTF("DH"); return &M.x86.R_DH; case 7: DECODE_PRINTF("BH"); return &M.x86.R_BH; } HALT_SYS(); return NULL; /* NOT REACHED OR REACHED ON ERROR */ } /**************************************************************************** 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. ****************************************************************************/ u16* decode_rm_word_register( int reg) { switch (reg) { case 0: DECODE_PRINTF("AX"); return &M.x86.R_AX; case 1: DECODE_PRINTF("CX"); return &M.x86.R_CX; case 2: DECODE_PRINTF("DX"); return &M.x86.R_DX; case 3: DECODE_PRINTF("BX"); return &M.x86.R_BX; case 4: DECODE_PRINTF("SP"); return &M.x86.R_SP; case 5: DECODE_PRINTF("BP"); return &M.x86.R_BP; case 6: DECODE_PRINTF("SI"); return &M.x86.R_SI; case 7: DECODE_PRINTF("DI"); return &M.x86.R_DI; } HALT_SYS(); return NULL; /* NOTREACHED OR REACHED ON ERROR */ } /**************************************************************************** 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. ****************************************************************************/ u32* decode_rm_long_register( int reg) { switch (reg) { case 0: DECODE_PRINTF("EAX"); return &M.x86.R_EAX; case 1: DECODE_PRINTF("ECX"); return &M.x86.R_ECX; case 2: DECODE_PRINTF("EDX"); return &M.x86.R_EDX; case 3: DECODE_PRINTF("EBX"); return &M.x86.R_EBX; case 4: DECODE_PRINTF("ESP"); return &M.x86.R_ESP; case 5: DECODE_PRINTF("EBP"); return &M.x86.R_EBP; case 6: DECODE_PRINTF("ESI"); return &M.x86.R_ESI; case 7: DECODE_PRINTF("EDI"); return &M.x86.R_EDI; } HALT_SYS(); return NULL; /* NOTREACHED OR REACHED ON ERROR */ } /**************************************************************************** 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. ****************************************************************************/ u16* decode_rm_seg_register( int reg) { switch (reg) { case 0: DECODE_PRINTF("ES"); return &M.x86.R_ES; case 1: DECODE_PRINTF("CS"); return &M.x86.R_CS; case 2: DECODE_PRINTF("SS"); return &M.x86.R_SS; case 3: DECODE_PRINTF("DS"); return &M.x86.R_DS; case 4: DECODE_PRINTF("FS"); return &M.x86.R_FS; case 5: DECODE_PRINTF("GS"); return &M.x86.R_GS; case 6: case 7: DECODE_PRINTF("ILLEGAL SEGREG"); break; } HALT_SYS(); return NULL; /* NOT REACHED OR REACHED ON ERROR */ } /* * * return offset from the SIB Byte */ u32 decode_sib_address(int sib, int mod) { u32 base = 0, i = 0, scale = 1; switch(sib & 0x07) { case 0: DECODE_PRINTF("[EAX]"); base = M.x86.R_EAX; break; case 1: DECODE_PRINTF("[ECX]"); base = M.x86.R_ECX; break; case 2: DECODE_PRINTF("[EDX]"); base = M.x86.R_EDX; break; case 3: DECODE_PRINTF("[EBX]"); base = M.x86.R_EBX; break; case 4: DECODE_PRINTF("[ESP]"); base = M.x86.R_ESP; M.x86.mode |= SYSMODE_SEG_DS_SS; break; case 5: if (mod == 0) { base = fetch_long_imm(); DECODE_PRINTF2("%08x", base); } else { DECODE_PRINTF("[EBP]"); base = M.x86.R_ESP; M.x86.mode |= SYSMODE_SEG_DS_SS; } break; case 6: DECODE_PRINTF("[ESI]"); base = M.x86.R_ESI; break; case 7: DECODE_PRINTF("[EDI]"); base = M.x86.R_EDI; break; } switch ((sib >> 3) & 0x07) { case 0: DECODE_PRINTF("[EAX"); i = M.x86.R_EAX; break; case 1: DECODE_PRINTF("[ECX"); i = M.x86.R_ECX; break; case 2: DECODE_PRINTF("[EDX"); i = M.x86.R_EDX; break; case 3: DECODE_PRINTF("[EBX"); i = M.x86.R_EBX; break; case 4: i = 0; break; case 5: DECODE_PRINTF("[EBP"); i = M.x86.R_EBP; break; case 6: DECODE_PRINTF("[ESI"); i = M.x86.R_ESI; break; case 7: DECODE_PRINTF("[EDI"); i = M.x86.R_EDI; break; } scale = 1 << ((sib >> 6) & 0x03); if (((sib >> 3) & 0x07) != 4) { if (scale == 1) { DECODE_PRINTF("]"); } else { DECODE_PRINTF2("*%d]", scale); } } 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 addressing. Also enables the decoding of instructions. NOTE: The code which specifies the corresponding segment (ds vs ss) below in the case of [BP+..]. The assumption here is that at the point that this subroutine is called, the bit corresponding to SYSMODE_SEG_DS_SS will be zero. After every instruction except the segment override instructions, this bit (as well as any bits indicating segment overrides) will be clear. So if a SS access is needed, set this bit. Otherwise, DS access occurs (unless any of the segment override bits are set). ****************************************************************************/ u32 decode_rm00_address( int rm) { u32 offset; int sib; if (M.x86.mode & SYSMODE_PREFIX_ADDR) { /* 32-bit addressing */ switch (rm) { case 0: DECODE_PRINTF("[EAX]"); return M.x86.R_EAX; case 1: DECODE_PRINTF("[ECX]"); return M.x86.R_ECX; case 2: DECODE_PRINTF("[EDX]"); return M.x86.R_EDX; case 3: DECODE_PRINTF("[EBX]"); return M.x86.R_EBX; case 4: sib = fetch_byte_imm(); return decode_sib_address(sib, 0); case 5: offset = fetch_long_imm(); DECODE_PRINTF2("[%08x]", offset); return offset; case 6: DECODE_PRINTF("[ESI]"); return M.x86.R_ESI; case 7: DECODE_PRINTF("[EDI]"); return M.x86.R_EDI; } HALT_SYS(); } else { /* 16-bit addressing */ switch (rm) { case 0: DECODE_PRINTF("[BX+SI]"); return (M.x86.R_BX + M.x86.R_SI) & 0xffff; case 1: DECODE_PRINTF("[BX+DI]"); return (M.x86.R_BX + M.x86.R_DI) & 0xffff; case 2: DECODE_PRINTF("[BP+SI]"); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + M.x86.R_SI) & 0xffff; case 3: DECODE_PRINTF("[BP+DI]"); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + M.x86.R_DI) & 0xffff; case 4: DECODE_PRINTF("[SI]"); return M.x86.R_SI; case 5: DECODE_PRINTF("[DI]"); return M.x86.R_DI; case 6: offset = fetch_word_imm(); DECODE_PRINTF2("[%04x]", offset); return offset; case 7: DECODE_PRINTF("[BX]"); return M.x86.R_BX; } HALT_SYS(); } return 0; } /**************************************************************************** PARAMETERS: rm - RM value to decode RETURNS: Offset in memory for the address decoding REMARKS: Return the offset given by mod=01 addressing. Also enables the decoding of instructions. ****************************************************************************/ u32 decode_rm01_address( int rm) { int displacement = 0; int sib; /* Fetch disp8 if no SIB byte */ if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4))) displacement = (s8)fetch_byte_imm(); if (M.x86.mode & SYSMODE_PREFIX_ADDR) { /* 32-bit addressing */ switch (rm) { case 0: DECODE_PRINTF2("%d[EAX]", displacement); return M.x86.R_EAX + displacement; case 1: DECODE_PRINTF2("%d[ECX]", displacement); return M.x86.R_ECX + displacement; case 2: DECODE_PRINTF2("%d[EDX]", displacement); return M.x86.R_EDX + displacement; case 3: DECODE_PRINTF2("%d[EBX]", displacement); return M.x86.R_EBX + displacement; case 4: sib = fetch_byte_imm(); displacement = (s8)fetch_byte_imm(); DECODE_PRINTF2("%d", displacement); return decode_sib_address(sib, 1) + displacement; case 5: DECODE_PRINTF2("%d[EBP]", displacement); return M.x86.R_EBP + displacement; case 6: DECODE_PRINTF2("%d[ESI]", displacement); return M.x86.R_ESI + displacement; case 7: DECODE_PRINTF2("%d[EDI]", displacement); return M.x86.R_EDI + displacement; } HALT_SYS(); } else { /* 16-bit addressing */ switch (rm) { case 0: DECODE_PRINTF2("%d[BX+SI]", displacement); return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; case 1: DECODE_PRINTF2("%d[BX+DI]", displacement); return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; case 2: DECODE_PRINTF2("%d[BP+SI]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; case 3: DECODE_PRINTF2("%d[BP+DI]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; case 4: DECODE_PRINTF2("%d[SI]", displacement); return (M.x86.R_SI + displacement) & 0xffff; case 5: DECODE_PRINTF2("%d[DI]", displacement); return (M.x86.R_DI + displacement) & 0xffff; case 6: DECODE_PRINTF2("%d[BP]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + displacement) & 0xffff; case 7: DECODE_PRINTF2("%d[BX]", displacement); return (M.x86.R_BX + displacement) & 0xffff; } HALT_SYS(); } return 0; /* SHOULD NOT HAPPEN */ } /**************************************************************************** PARAMETERS: rm - RM value to decode RETURNS: Offset in memory for the address decoding REMARKS: Return the offset given by mod=10 addressing. Also enables the decoding of instructions. ****************************************************************************/ u32 decode_rm10_address( int rm) { u32 displacement = 0; int sib; /* Fetch disp16 if 16-bit addr mode */ if (!(M.x86.mode & SYSMODE_PREFIX_ADDR)) displacement = (u16)fetch_word_imm(); else { /* Fetch disp32 if no SIB byte */ if (rm != 4) displacement = (u32)fetch_long_imm(); } if (M.x86.mode & SYSMODE_PREFIX_ADDR) { /* 32-bit addressing */ switch (rm) { case 0: DECODE_PRINTF2("%08x[EAX]", displacement); return M.x86.R_EAX + displacement; case 1: DECODE_PRINTF2("%08x[ECX]", displacement); return M.x86.R_ECX + displacement; case 2: DECODE_PRINTF2("%08x[EDX]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return M.x86.R_EDX + displacement; case 3: DECODE_PRINTF2("%08x[EBX]", displacement); return M.x86.R_EBX + displacement; case 4: sib = fetch_byte_imm(); displacement = (u32)fetch_long_imm(); DECODE_PRINTF2("%08x", displacement); return decode_sib_address(sib, 2) + displacement; break; case 5: DECODE_PRINTF2("%08x[EBP]", displacement); return M.x86.R_EBP + displacement; case 6: DECODE_PRINTF2("%08x[ESI]", displacement); return M.x86.R_ESI + displacement; case 7: DECODE_PRINTF2("%08x[EDI]", displacement); return M.x86.R_EDI + displacement; } HALT_SYS(); } else { /* 16-bit addressing */ switch (rm) { case 0: DECODE_PRINTF2("%04x[BX+SI]", displacement); return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; case 1: DECODE_PRINTF2("%04x[BX+DI]", displacement); return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; case 2: DECODE_PRINTF2("%04x[BP+SI]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; case 3: DECODE_PRINTF2("%04x[BP+DI]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; case 4: DECODE_PRINTF2("%04x[SI]", displacement); return (M.x86.R_SI + displacement) & 0xffff; case 5: DECODE_PRINTF2("%04x[DI]", displacement); return (M.x86.R_DI + displacement) & 0xffff; case 6: DECODE_PRINTF2("%04x[BP]", displacement); M.x86.mode |= SYSMODE_SEG_DS_SS; return (M.x86.R_BP + displacement) & 0xffff; case 7: DECODE_PRINTF2("%04x[BX]", displacement); return (M.x86.R_BX + displacement) & 0xffff; } HALT_SYS(); } return 0; /*NOTREACHED */ } v86d-0.1.10/libs/x86emu/fpu.c000066400000000000000000000646551153201731300154170ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file contains the code to implement the decoding and * emulation of the FPU instructions. * ****************************************************************************/ #include "x86emu/x86emui.h" /*----------------------------- Implementation ----------------------------*/ /* opcode=0xd8 */ void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("ESC D8\n"); DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG static char *x86emu_fpu_op_d9_tab[] = { "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ", "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t", "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ", "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t", "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ", "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t", }; static char *x86emu_fpu_op_d9_tab1[] = { "FLD\t", "FLD\t", "FLD\t", "FLD\t", "FLD\t", "FLD\t", "FLD\t", "FLD\t", "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", "FNOP", "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9", "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", "FCHS", "FABS", "ESC_D9", "ESC_D9", "FTST", "FXAM", "ESC_D9", "ESC_D9", "FLD1", "FLDL2T", "FLDL2E", "FLDPI", "FLDLG2", "FLDLN2", "FLDZ", "ESC_D9", "F2XM1", "FYL2X", "FPTAN", "FPATAN", "FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP", "FPREM", "FYL2XP1", "FSQRT", "ESC_D9", "FRNDINT", "FSCALE", "ESC_D9", "ESC_D9", }; #endif /* DEBUG */ /* opcode=0xd9 */ void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; u8 stkelem = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (mod != 3) { DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl); } else { DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]); } #endif switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); break; case 3: /* register to register */ stkelem = (u8)rl; if (rh < 4) { DECODE_PRINTF2("ST(%d)\n", stkelem); } else { DECODE_PRINTF("\n"); } break; } #ifdef X86EMU_FPU_PRESENT /* execute */ switch (mod) { case 3: switch (rh) { case 0: x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem); break; case 1: x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem); break; case 2: switch (rl) { case 0: x86emu_fpu_R_nop(); break; default: x86emu_fpu_illegal(); break; } case 3: x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem); break; case 4: switch (rl) { case 0: x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP); break; case 1: x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP); break; case 4: x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP); break; case 5: x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP); break; default: /* 2,3,6,7 */ x86emu_fpu_illegal(); break; } break; case 5: switch (rl) { case 0: x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP); break; case 1: x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP); break; case 2: x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP); break; case 3: x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP); break; case 4: x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP); break; case 5: x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP); break; case 6: x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP); break; default: /* 7 */ x86emu_fpu_illegal(); break; } break; case 6: switch (rl) { case 0: x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP); break; case 1: x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP); break; case 2: x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP); break; case 3: x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP); break; case 4: x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP); break; case 5: x86emu_fpu_illegal(); break; case 6: x86emu_fpu_R_decstp(); break; case 7: x86emu_fpu_R_incstp(); break; } break; case 7: switch (rl) { case 0: x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP); break; case 1: x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP); break; case 2: x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP); break; case 3: x86emu_fpu_illegal(); break; case 4: x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP); break; case 5: x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP); break; case 6: case 7: default: x86emu_fpu_illegal(); break; } break; default: switch (rh) { case 0: x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset); break; case 1: x86emu_fpu_illegal(); break; case 2: x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset); break; case 3: x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset); break; case 4: x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset); break; case 5: x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset); break; case 6: x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset); break; case 7: x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset); break; } } } #else (void)destoffset; (void)stkelem; #endif /* X86EMU_FPU_PRESENT */ DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG char *x86emu_fpu_op_da_tab[] = { "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ", "FICOMP\tDWORD PTR ", "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ", "FIDIVR\tDWORD PTR ", "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ", "FICOMP\tDWORD PTR ", "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ", "FIDIVR\tDWORD PTR ", "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ", "FICOMP\tDWORD PTR ", "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ", "FIDIVR\tDWORD PTR ", "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", }; #endif /* DEBUG */ /* opcode=0xda */ void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; u8 stkelem = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); break; case 3: /* register to register */ stkelem = (u8)rl; DECODE_PRINTF2("\tST(%d),ST\n", stkelem); break; } #ifdef X86EMU_FPU_PRESENT switch (mod) { case 3: x86emu_fpu_illegal(); break; default: switch (rh) { case 0: x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset); break; case 1: x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset); break; case 2: x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset); break; case 3: x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset); break; case 4: x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset); break; case 5: x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset); break; case 6: x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset); break; case 7: x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset); break; } } #else (void)destoffset; (void)stkelem; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG char *x86emu_fpu_op_db_tab[] = { "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ", "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ", "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ", "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ", "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ", "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ", }; #endif /* DEBUG */ /* opcode=0xdb */ void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (mod != 3) { DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl); } else if (rh == 4) { /* === 11 10 0 nnn */ switch (rl) { case 0: DECODE_PRINTF("FENI\n"); break; case 1: DECODE_PRINTF("FDISI\n"); break; case 2: DECODE_PRINTF("FCLEX\n"); break; case 3: DECODE_PRINTF("FINIT\n"); break; } } else { DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl)); } #endif /* DEBUG */ switch (mod) { case 0: destoffset = decode_rm00_address(rl); break; case 1: destoffset = decode_rm01_address(rl); break; case 2: destoffset = decode_rm10_address(rl); break; case 3: /* register to register */ break; } #ifdef X86EMU_FPU_PRESENT /* execute */ switch (mod) { case 3: switch (rh) { case 4: switch (rl) { case 0: x86emu_fpu_R_feni(); break; case 1: x86emu_fpu_R_fdisi(); break; case 2: x86emu_fpu_R_fclex(); break; case 3: x86emu_fpu_R_finit(); break; default: x86emu_fpu_illegal(); break; } break; default: x86emu_fpu_illegal(); break; } break; default: switch (rh) { case 0: x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset); break; case 1: x86emu_fpu_illegal(); break; case 2: x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset); break; case 3: x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset); break; case 4: x86emu_fpu_illegal(); break; case 5: x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset); break; case 6: x86emu_fpu_illegal(); break; case 7: x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset); break; } } #else (void)destoffset; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG char *x86emu_fpu_op_dc_tab[] = { "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ", "FCOMP\tQWORD PTR ", "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ", "FDIVR\tQWORD PTR ", "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ", "FCOMP\tQWORD PTR ", "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ", "FDIVR\tQWORD PTR ", "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ", "FCOMP\tQWORD PTR ", "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ", "FDIVR\tQWORD PTR ", "FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t", "FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t", }; #endif /* DEBUG */ /* opcode=0xdc */ void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; u8 stkelem = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); break; case 3: /* register to register */ stkelem = (u8)rl; DECODE_PRINTF2("\tST(%d),ST\n", stkelem); break; } #ifdef X86EMU_FPU_PRESENT /* execute */ switch (mod) { case 3: switch (rh) { case 0: x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP); break; case 1: x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP); break; case 2: x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP); break; case 3: x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP); break; case 4: x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP); break; case 5: x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP); break; case 6: x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP); break; case 7: x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP); break; } break; default: switch (rh) { case 0: x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset); break; case 1: x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset); break; case 2: x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset); break; case 3: x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset); break; case 4: x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset); break; case 5: x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset); break; case 6: x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset); break; case 7: x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset); break; } } #else (void)destoffset; (void)stkelem; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG static char *x86emu_fpu_op_dd_tab[] = { "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ", "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t", "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ", "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t", "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ", "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t", "FFREE\t", "FXCH\t", "FST\t", "FSTP\t", "ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,", }; #endif /* DEBUG */ /* opcode=0xdd */ void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; u8 stkelem = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); break; case 3: /* register to register */ stkelem = (u8)rl; DECODE_PRINTF2("\tST(%d),ST\n", stkelem); break; } #ifdef X86EMU_FPU_PRESENT switch (mod) { case 3: switch (rh) { case 0: x86emu_fpu_R_ffree(stkelem); break; case 1: x86emu_fpu_R_fxch(stkelem); break; case 2: x86emu_fpu_R_fst(stkelem); /* register version */ break; case 3: x86emu_fpu_R_fstp(stkelem); /* register version */ break; default: x86emu_fpu_illegal(); break; } break; default: switch (rh) { case 0: x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset); break; case 1: x86emu_fpu_illegal(); break; case 2: x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset); break; case 3: x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset); break; case 4: x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset); break; case 5: x86emu_fpu_illegal(); break; case 6: x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset); break; case 7: x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset); break; } } #else (void)destoffset; (void)stkelem; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG static char *x86emu_fpu_op_de_tab[] = { "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ", "FICOMP\tWORD PTR ", "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ", "FIDIVR\tWORD PTR ", "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ", "FICOMP\tWORD PTR ", "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ", "FIDIVR\tWORD PTR ", "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ", "FICOMP\tWORD PTR ", "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ", "FIDIVR\tWORD PTR ", "FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t", "FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t", }; #endif /* DEBUG */ /* opcode=0xde */ void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; u8 stkelem = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); break; case 3: /* register to register */ stkelem = (u8)rl; DECODE_PRINTF2("\tST(%d),ST\n", stkelem); break; } #ifdef X86EMU_FPU_PRESENT switch (mod) { case 3: switch (rh) { case 0: x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP); break; case 1: x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP); break; case 2: x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP); break; case 3: if (stkelem == 1) x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP); else x86emu_fpu_illegal(); break; case 4: x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP); break; case 5: x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP); break; case 6: x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP); break; case 7: x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP); break; } break; default: switch (rh) { case 0: x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset); break; case 1: x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset); break; case 2: x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset); break; case 3: x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset); break; case 4: x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset); break; case 5: x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset); break; case 6: x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset); break; case 7: x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset); break; } } #else (void)destoffset; (void)stkelem; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } #ifdef DEBUG static char *x86emu_fpu_op_df_tab[] = { /* mod == 00 */ "FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ", "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ", "FISTP\tQWORD PTR ", /* mod == 01 */ "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ", "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ", "FISTP\tQWORD PTR ", /* mod == 10 */ "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ", "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ", "FISTP\tQWORD PTR ", /* mod == 11 */ "FFREE\t", "FXCH\t", "FST\t", "FSTP\t", "ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F," }; #endif /* DEBUG */ /* opcode=0xdf */ void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset = 0; u8 stkelem = 0; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); break; case 3: /* register to register */ stkelem = (u8)rl; DECODE_PRINTF2("\tST(%d)\n", stkelem); break; } #ifdef X86EMU_FPU_PRESENT switch (mod) { case 3: switch (rh) { case 0: x86emu_fpu_R_ffree(stkelem); break; case 1: x86emu_fpu_R_fxch(stkelem); break; case 2: x86emu_fpu_R_fst(stkelem); /* register version */ break; case 3: x86emu_fpu_R_fstp(stkelem); /* register version */ break; default: x86emu_fpu_illegal(); break; } break; default: switch (rh) { case 0: x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset); break; case 1: x86emu_fpu_illegal(); break; case 2: x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset); break; case 3: x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset); break; case 4: x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset); break; case 5: x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset); break; case 6: x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset); break; case 7: x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset); break; } } #else (void)destoffset; (void)stkelem; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR_NO_TRACE(); } v86d-0.1.10/libs/x86emu/ops.c000066400000000000000000012625731153201731300154260ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file includes subroutines to implement the decoding * and emulation of all the x86 processor instructions. * * There are approximately 250 subroutines in here, which correspond * to the 256 byte-"opcodes" found on the 8086. The table which * dispatches this is found in the files optab.[ch]. * * Each opcode proc has a comment preceeding it which gives it's table * address. Several opcodes are missing (undefined) in the table. * * Each proc includes information for decoding (DECODE_PRINTF and * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc * functions (START_OF_INSTR, END_OF_INSTR). * * Many of the procedures are *VERY* similar in coding. This has * allowed for a very large amount of code to be generated in a fairly * short amount of time (i.e. cut, paste, and modify). The result is * that much of the code below could have been folded into subroutines * for a large reduction in size of this file. The downside would be * that there would be a penalty in execution speed. The file could * also have been *MUCH* larger by inlining certain functions which * were called. This could have resulted even faster execution. The * prime directive I used to decide whether to inline the code or to * modularize it, was basically: 1) no unnecessary subroutine calls, * 2) no routines more than about 200 lines in size, and 3) modularize * any code that I might not get right the first time. The fetch_* * subroutines fall into the latter category. The The decode_* fall * into the second category. The coding of the "switch(mod){ .... }" * in many of the subroutines below falls into the first category. * Especially, the coding of {add,and,or,sub,...}_{byte,word} * subroutines are an especially glaring case of the third guideline. * Since so much of the code is cloned from other modules (compare * opcode #00 to opcode #01), making the basic operations subroutine * calls is especially important; otherwise mistakes in coding an * "add" would represent a nightmare in maintenance. * ****************************************************************************/ #include "x86emu/x86emui.h" /*----------------------------- Implementation ----------------------------*/ /**************************************************************************** PARAMETERS: op1 - Instruction op code REMARKS: Handles illegal opcodes. ****************************************************************************/ static void x86emuOp_illegal_op( u8 op1) { START_OF_INSTR(); if (M.x86.R_SP != 0) { DECODE_PRINTF("ILLEGAL X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n", M.x86.R_CS, M.x86.R_IP-1,op1); HALT_SYS(); } else { /* If we get here, it means the stack pointer is back to zero * so we are just returning from an emulator service call * so therte is no need to display an error message. We trap * the emulator with an 0xF1 opcode to finish the service * call. */ X86EMU_halt_sys(); } END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x00 ****************************************************************************/ static void x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; u8 *destreg, *srcreg; u8 destval; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x01 ****************************************************************************/ static void x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x02 ****************************************************************************/ static void x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x03 ****************************************************************************/ static void x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x04 ****************************************************************************/ static void x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("ADD\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = add_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x05 ****************************************************************************/ static void x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("ADD\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("ADD\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = add_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = add_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x06 ****************************************************************************/ static void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("PUSH\tES\n"); TRACE_AND_STEP(); push_word(M.x86.R_ES); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x07 ****************************************************************************/ static void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("POP\tES\n"); TRACE_AND_STEP(); M.x86.R_ES = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x08 ****************************************************************************/ static void x86emuOp_or_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("OR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x09 ****************************************************************************/ static void x86emuOp_or_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("OR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = or_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0a ****************************************************************************/ static void x86emuOp_or_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("OR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0b ****************************************************************************/ static void x86emuOp_or_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("OR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = or_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0c ****************************************************************************/ static void x86emuOp_or_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("OR\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = or_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0d ****************************************************************************/ static void x86emuOp_or_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("OR\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("OR\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = or_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = or_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0e ****************************************************************************/ static void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("PUSH\tCS\n"); TRACE_AND_STEP(); push_word(M.x86.R_CS); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f. Escape for two-byte opcode (286 or better) ****************************************************************************/ static void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1)) { u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); INC_DECODED_INST_LEN(1); (*x86emu_optab2[op2])(op2); } /**************************************************************************** REMARKS: Handles opcode 0x10 ****************************************************************************/ static void x86emuOp_adc_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("ADC\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x11 ****************************************************************************/ static void x86emuOp_adc_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("ADC\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = adc_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x12 ****************************************************************************/ static void x86emuOp_adc_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("ADC\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x13 ****************************************************************************/ static void x86emuOp_adc_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("ADC\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = adc_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x14 ****************************************************************************/ static void x86emuOp_adc_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("ADC\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = adc_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x15 ****************************************************************************/ static void x86emuOp_adc_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("ADC\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("ADC\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = adc_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = adc_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x16 ****************************************************************************/ static void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("PUSH\tSS\n"); TRACE_AND_STEP(); push_word(M.x86.R_SS); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x17 ****************************************************************************/ static void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("POP\tSS\n"); TRACE_AND_STEP(); M.x86.R_SS = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x18 ****************************************************************************/ static void x86emuOp_sbb_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("SBB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x19 ****************************************************************************/ static void x86emuOp_sbb_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("SBB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sbb_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x1a ****************************************************************************/ static void x86emuOp_sbb_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("SBB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x1b ****************************************************************************/ static void x86emuOp_sbb_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("SBB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sbb_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x1c ****************************************************************************/ static void x86emuOp_sbb_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("SBB\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = sbb_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x1d ****************************************************************************/ static void x86emuOp_sbb_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("SBB\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("SBB\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = sbb_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = sbb_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x1e ****************************************************************************/ static void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("PUSH\tDS\n"); TRACE_AND_STEP(); push_word(M.x86.R_DS); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x1f ****************************************************************************/ static void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("POP\tDS\n"); TRACE_AND_STEP(); M.x86.R_DS = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x20 ****************************************************************************/ static void x86emuOp_and_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("AND\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x21 ****************************************************************************/ static void x86emuOp_and_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("AND\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = and_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x22 ****************************************************************************/ static void x86emuOp_and_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("AND\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x23 ****************************************************************************/ static void x86emuOp_and_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("AND\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_long(*destreg, srcval); break; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_word(*destreg, srcval); break; } case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = and_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x24 ****************************************************************************/ static void x86emuOp_and_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("AND\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = and_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x25 ****************************************************************************/ static void x86emuOp_and_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("AND\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("AND\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = and_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = and_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x26 ****************************************************************************/ static void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("ES:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_SEGOVR_ES; /* * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 * opcode subroutines we do not want to do this. */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x27 ****************************************************************************/ static void x86emuOp_daa(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("DAA\n"); TRACE_AND_STEP(); M.x86.R_AL = daa_byte(M.x86.R_AL); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x28 ****************************************************************************/ static void x86emuOp_sub_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("SUB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x29 ****************************************************************************/ static void x86emuOp_sub_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("SUB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = sub_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x2a ****************************************************************************/ static void x86emuOp_sub_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("SUB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x2b ****************************************************************************/ static void x86emuOp_sub_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("SUB\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = sub_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x2c ****************************************************************************/ static void x86emuOp_sub_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("SUB\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = sub_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x2d ****************************************************************************/ static void x86emuOp_sub_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("SUB\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("SUB\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = sub_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = sub_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x2e ****************************************************************************/ static void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("CS:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_SEGOVR_CS; /* note no DECODE_CLEAR_SEGOVR here. */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x2f ****************************************************************************/ static void x86emuOp_das(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("DAS\n"); TRACE_AND_STEP(); M.x86.R_AL = das_byte(M.x86.R_AL); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x30 ****************************************************************************/ static void x86emuOp_xor_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("XOR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x31 ****************************************************************************/ static void x86emuOp_xor_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("XOR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = xor_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x32 ****************************************************************************/ static void x86emuOp_xor_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("XOR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x33 ****************************************************************************/ static void x86emuOp_xor_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("XOR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = xor_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x34 ****************************************************************************/ static void x86emuOp_xor_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("XOR\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = xor_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x35 ****************************************************************************/ static void x86emuOp_xor_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XOR\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("XOR\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = xor_long(M.x86.R_EAX, srcval); } else { M.x86.R_AX = xor_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x36 ****************************************************************************/ static void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("SS:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_SEGOVR_SS; /* no DECODE_CLEAR_SEGOVR ! */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x37 ****************************************************************************/ static void x86emuOp_aaa(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("AAA\n"); TRACE_AND_STEP(); M.x86.R_AX = aaa_word(M.x86.R_AX); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x38 ****************************************************************************/ static void x86emuOp_cmp_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; u8 *destreg, *srcreg; u8 destval; START_OF_INSTR(); DECODE_PRINTF("CMP\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(destval, *srcreg); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(destval, *srcreg); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(destval, *srcreg); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x39 ****************************************************************************/ static void x86emuOp_cmp_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("CMP\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(destval, *srcreg); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(destval, *srcreg); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(destval, *srcreg); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(destval, *srcreg); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(destval, *srcreg); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(destval, *srcreg); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x3a ****************************************************************************/ static void x86emuOp_cmp_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("CMP\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x3b ****************************************************************************/ static void x86emuOp_cmp_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("CMP\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); cmp_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x3c ****************************************************************************/ static void x86emuOp_cmp_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 srcval; START_OF_INSTR(); DECODE_PRINTF("CMP\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); cmp_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x3d ****************************************************************************/ static void x86emuOp_cmp_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("CMP\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("CMP\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { cmp_long(M.x86.R_EAX, srcval); } else { cmp_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x3e ****************************************************************************/ static void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("DS:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_SEGOVR_DS; /* NO DECODE_CLEAR_SEGOVR! */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x3f ****************************************************************************/ static void x86emuOp_aas(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("AAS\n"); TRACE_AND_STEP(); M.x86.R_AX = aas_word(M.x86.R_AX); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x40 ****************************************************************************/ static void x86emuOp_inc_AX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tEAX\n"); } else { DECODE_PRINTF("INC\tAX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = inc_long(M.x86.R_EAX); } else { M.x86.R_AX = inc_word(M.x86.R_AX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x41 ****************************************************************************/ static void x86emuOp_inc_CX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tECX\n"); } else { DECODE_PRINTF("INC\tCX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = inc_long(M.x86.R_ECX); } else { M.x86.R_CX = inc_word(M.x86.R_CX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x42 ****************************************************************************/ static void x86emuOp_inc_DX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tEDX\n"); } else { DECODE_PRINTF("INC\tDX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDX = inc_long(M.x86.R_EDX); } else { M.x86.R_DX = inc_word(M.x86.R_DX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x43 ****************************************************************************/ static void x86emuOp_inc_BX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tEBX\n"); } else { DECODE_PRINTF("INC\tBX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBX = inc_long(M.x86.R_EBX); } else { M.x86.R_BX = inc_word(M.x86.R_BX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x44 ****************************************************************************/ static void x86emuOp_inc_SP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tESP\n"); } else { DECODE_PRINTF("INC\tSP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESP = inc_long(M.x86.R_ESP); } else { M.x86.R_SP = inc_word(M.x86.R_SP); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x45 ****************************************************************************/ static void x86emuOp_inc_BP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tEBP\n"); } else { DECODE_PRINTF("INC\tBP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBP = inc_long(M.x86.R_EBP); } else { M.x86.R_BP = inc_word(M.x86.R_BP); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x46 ****************************************************************************/ static void x86emuOp_inc_SI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tESI\n"); } else { DECODE_PRINTF("INC\tSI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESI = inc_long(M.x86.R_ESI); } else { M.x86.R_SI = inc_word(M.x86.R_SI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x47 ****************************************************************************/ static void x86emuOp_inc_DI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tEDI\n"); } else { DECODE_PRINTF("INC\tDI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDI = inc_long(M.x86.R_EDI); } else { M.x86.R_DI = inc_word(M.x86.R_DI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x48 ****************************************************************************/ static void x86emuOp_dec_AX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tEAX\n"); } else { DECODE_PRINTF("DEC\tAX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = dec_long(M.x86.R_EAX); } else { M.x86.R_AX = dec_word(M.x86.R_AX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x49 ****************************************************************************/ static void x86emuOp_dec_CX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tECX\n"); } else { DECODE_PRINTF("DEC\tCX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = dec_long(M.x86.R_ECX); } else { M.x86.R_CX = dec_word(M.x86.R_CX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x4a ****************************************************************************/ static void x86emuOp_dec_DX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tEDX\n"); } else { DECODE_PRINTF("DEC\tDX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDX = dec_long(M.x86.R_EDX); } else { M.x86.R_DX = dec_word(M.x86.R_DX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x4b ****************************************************************************/ static void x86emuOp_dec_BX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tEBX\n"); } else { DECODE_PRINTF("DEC\tBX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBX = dec_long(M.x86.R_EBX); } else { M.x86.R_BX = dec_word(M.x86.R_BX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x4c ****************************************************************************/ static void x86emuOp_dec_SP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tESP\n"); } else { DECODE_PRINTF("DEC\tSP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESP = dec_long(M.x86.R_ESP); } else { M.x86.R_SP = dec_word(M.x86.R_SP); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x4d ****************************************************************************/ static void x86emuOp_dec_BP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tEBP\n"); } else { DECODE_PRINTF("DEC\tBP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBP = dec_long(M.x86.R_EBP); } else { M.x86.R_BP = dec_word(M.x86.R_BP); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x4e ****************************************************************************/ static void x86emuOp_dec_SI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tESI\n"); } else { DECODE_PRINTF("DEC\tSI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESI = dec_long(M.x86.R_ESI); } else { M.x86.R_SI = dec_word(M.x86.R_SI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x4f ****************************************************************************/ static void x86emuOp_dec_DI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tEDI\n"); } else { DECODE_PRINTF("DEC\tDI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDI = dec_long(M.x86.R_EDI); } else { M.x86.R_DI = dec_word(M.x86.R_DI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x50 ****************************************************************************/ static void x86emuOp_push_AX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tEAX\n"); } else { DECODE_PRINTF("PUSH\tAX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_EAX); } else { push_word(M.x86.R_AX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x51 ****************************************************************************/ static void x86emuOp_push_CX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tECX\n"); } else { DECODE_PRINTF("PUSH\tCX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_ECX); } else { push_word(M.x86.R_CX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x52 ****************************************************************************/ static void x86emuOp_push_DX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tEDX\n"); } else { DECODE_PRINTF("PUSH\tDX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_EDX); } else { push_word(M.x86.R_DX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x53 ****************************************************************************/ static void x86emuOp_push_BX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tEBX\n"); } else { DECODE_PRINTF("PUSH\tBX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_EBX); } else { push_word(M.x86.R_BX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x54 ****************************************************************************/ static void x86emuOp_push_SP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tESP\n"); } else { DECODE_PRINTF("PUSH\tSP\n"); } TRACE_AND_STEP(); /* Always push (E)SP, since we are emulating an i386 and above * processor. This is necessary as some BIOS'es use this to check * what type of processor is in the system. */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_ESP); } else { push_word((u16)(M.x86.R_SP)); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x55 ****************************************************************************/ static void x86emuOp_push_BP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tEBP\n"); } else { DECODE_PRINTF("PUSH\tBP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_EBP); } else { push_word(M.x86.R_BP); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x56 ****************************************************************************/ static void x86emuOp_push_SI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tESI\n"); } else { DECODE_PRINTF("PUSH\tSI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_ESI); } else { push_word(M.x86.R_SI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x57 ****************************************************************************/ static void x86emuOp_push_DI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSH\tEDI\n"); } else { DECODE_PRINTF("PUSH\tDI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(M.x86.R_EDI); } else { push_word(M.x86.R_DI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x58 ****************************************************************************/ static void x86emuOp_pop_AX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tEAX\n"); } else { DECODE_PRINTF("POP\tAX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = pop_long(); } else { M.x86.R_AX = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x59 ****************************************************************************/ static void x86emuOp_pop_CX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tECX\n"); } else { DECODE_PRINTF("POP\tCX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = pop_long(); } else { M.x86.R_CX = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x5a ****************************************************************************/ static void x86emuOp_pop_DX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tEDX\n"); } else { DECODE_PRINTF("POP\tDX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDX = pop_long(); } else { M.x86.R_DX = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x5b ****************************************************************************/ static void x86emuOp_pop_BX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tEBX\n"); } else { DECODE_PRINTF("POP\tBX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBX = pop_long(); } else { M.x86.R_BX = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x5c ****************************************************************************/ static void x86emuOp_pop_SP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tESP\n"); } else { DECODE_PRINTF("POP\tSP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESP = pop_long(); } else { M.x86.R_SP = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x5d ****************************************************************************/ static void x86emuOp_pop_BP(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tEBP\n"); } else { DECODE_PRINTF("POP\tBP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBP = pop_long(); } else { M.x86.R_BP = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x5e ****************************************************************************/ static void x86emuOp_pop_SI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tESI\n"); } else { DECODE_PRINTF("POP\tSI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESI = pop_long(); } else { M.x86.R_SI = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x5f ****************************************************************************/ static void x86emuOp_pop_DI(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POP\tEDI\n"); } else { DECODE_PRINTF("POP\tDI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDI = pop_long(); } else { M.x86.R_DI = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x60 ****************************************************************************/ static void x86emuOp_push_all(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSHAD\n"); } else { DECODE_PRINTF("PUSHA\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 old_sp = M.x86.R_ESP; push_long(M.x86.R_EAX); push_long(M.x86.R_ECX); push_long(M.x86.R_EDX); push_long(M.x86.R_EBX); push_long(old_sp); push_long(M.x86.R_EBP); push_long(M.x86.R_ESI); push_long(M.x86.R_EDI); } else { u16 old_sp = M.x86.R_SP; push_word(M.x86.R_AX); push_word(M.x86.R_CX); push_word(M.x86.R_DX); push_word(M.x86.R_BX); push_word(old_sp); push_word(M.x86.R_BP); push_word(M.x86.R_SI); push_word(M.x86.R_DI); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x61 ****************************************************************************/ static void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POPAD\n"); } else { DECODE_PRINTF("POPA\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDI = pop_long(); M.x86.R_ESI = pop_long(); M.x86.R_EBP = pop_long(); M.x86.R_ESP += 4; /* skip ESP */ M.x86.R_EBX = pop_long(); M.x86.R_EDX = pop_long(); M.x86.R_ECX = pop_long(); M.x86.R_EAX = pop_long(); } else { M.x86.R_DI = pop_word(); M.x86.R_SI = pop_word(); M.x86.R_BP = pop_word(); M.x86.R_SP += 2; /* skip SP */ M.x86.R_BX = pop_word(); M.x86.R_DX = pop_word(); M.x86.R_CX = pop_word(); M.x86.R_AX = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ /**************************************************************************** REMARKS: Handles opcode 0x64 ****************************************************************************/ static void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("FS:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_SEGOVR_FS; /* * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 * opcode subroutines we do not want to do this. */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x65 ****************************************************************************/ static void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("GS:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_SEGOVR_GS; /* * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 * opcode subroutines we do not want to do this. */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x66 - prefix for 32-bit register ****************************************************************************/ static void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("DATA:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_PREFIX_DATA; /* note no DECODE_CLEAR_SEGOVR here. */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x67 - prefix for 32-bit address ****************************************************************************/ static void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("ADDR:\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_PREFIX_ADDR; /* note no DECODE_CLEAR_SEGOVR here. */ END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x68 ****************************************************************************/ static void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1)) { u32 imm; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { imm = fetch_long_imm(); } else { imm = fetch_word_imm(); } DECODE_PRINTF2("PUSH\t%x\n", imm); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(imm); } else { push_word((u16)imm); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x69 ****************************************************************************/ static void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("IMUL\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; s32 imm; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); imm = fetch_long_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; s16 imm; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); imm = fetch_word_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); res = (s16)srcval * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; s32 imm; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); imm = fetch_long_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; s16 imm; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); imm = fetch_word_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); res = (s16)srcval * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; s32 imm; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); imm = fetch_long_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; s16 imm; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); imm = fetch_word_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); res = (s16)srcval * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; u32 res_lo,res_hi; s32 imm; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); imm = fetch_long_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg,*srcreg; u32 res; s16 imm; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); imm = fetch_word_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); res = (s16)*srcreg * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x6a ****************************************************************************/ static void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1)) { s16 imm; START_OF_INSTR(); imm = (s8)fetch_byte_imm(); DECODE_PRINTF2("PUSH\t%d\n", imm); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long((s32)imm); } else { push_word(imm); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x6b ****************************************************************************/ static void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; s8 imm; START_OF_INSTR(); DECODE_PRINTF("IMUL\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); res = (s16)srcval * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); res = (s16)srcval * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); res = (s16)srcval * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg,*srcreg; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%d\n", (s32)imm); res = (s16)*srcreg * (s16)imm; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x6c ****************************************************************************/ static void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("INSB\n"); ins(1); TRACE_AND_STEP(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x6d ****************************************************************************/ static void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INSD\n"); ins(4); } else { DECODE_PRINTF("INSW\n"); ins(2); } TRACE_AND_STEP(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x6e ****************************************************************************/ static void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("OUTSB\n"); outs(1); TRACE_AND_STEP(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x6f ****************************************************************************/ static void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("OUTSD\n"); outs(4); } else { DECODE_PRINTF("OUTSW\n"); outs(2); } TRACE_AND_STEP(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x70 ****************************************************************************/ static void x86emuOp_jump_near_O(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if overflow flag is set */ START_OF_INSTR(); DECODE_PRINTF("JO\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (ACCESS_FLAG(F_OF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x71 ****************************************************************************/ static void x86emuOp_jump_near_NO(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if overflow is not set */ START_OF_INSTR(); DECODE_PRINTF("JNO\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (!ACCESS_FLAG(F_OF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x72 ****************************************************************************/ static void x86emuOp_jump_near_B(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if carry flag is set. */ START_OF_INSTR(); DECODE_PRINTF("JB\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (ACCESS_FLAG(F_CF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x73 ****************************************************************************/ static void x86emuOp_jump_near_NB(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if carry flag is clear. */ START_OF_INSTR(); DECODE_PRINTF("JNB\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (!ACCESS_FLAG(F_CF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x74 ****************************************************************************/ static void x86emuOp_jump_near_Z(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if zero flag is set. */ START_OF_INSTR(); DECODE_PRINTF("JZ\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (ACCESS_FLAG(F_ZF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x75 ****************************************************************************/ static void x86emuOp_jump_near_NZ(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if zero flag is clear. */ START_OF_INSTR(); DECODE_PRINTF("JNZ\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (!ACCESS_FLAG(F_ZF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x76 ****************************************************************************/ static void x86emuOp_jump_near_BE(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if carry flag is set or if the zero flag is set. */ START_OF_INSTR(); DECODE_PRINTF("JBE\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x77 ****************************************************************************/ static void x86emuOp_jump_near_NBE(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if carry flag is clear and if the zero flag is clear */ START_OF_INSTR(); DECODE_PRINTF("JNBE\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x78 ****************************************************************************/ static void x86emuOp_jump_near_S(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if sign flag is set */ START_OF_INSTR(); DECODE_PRINTF("JS\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (ACCESS_FLAG(F_SF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x79 ****************************************************************************/ static void x86emuOp_jump_near_NS(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if sign flag is clear */ START_OF_INSTR(); DECODE_PRINTF("JNS\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (!ACCESS_FLAG(F_SF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x7a ****************************************************************************/ static void x86emuOp_jump_near_P(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if parity flag is set (even parity) */ START_OF_INSTR(); DECODE_PRINTF("JP\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (ACCESS_FLAG(F_PF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x7b ****************************************************************************/ static void x86emuOp_jump_near_NP(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; /* jump to byte offset if parity flag is clear (odd parity) */ START_OF_INSTR(); DECODE_PRINTF("JNP\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (!ACCESS_FLAG(F_PF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x7c ****************************************************************************/ static void x86emuOp_jump_near_L(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; int sf, of; /* jump to byte offset if sign flag not equal to overflow flag. */ START_OF_INSTR(); DECODE_PRINTF("JL\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); sf = ACCESS_FLAG(F_SF) != 0; of = ACCESS_FLAG(F_OF) != 0; if (sf ^ of) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x7d ****************************************************************************/ static void x86emuOp_jump_near_NL(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; int sf, of; /* jump to byte offset if sign flag not equal to overflow flag. */ START_OF_INSTR(); DECODE_PRINTF("JNL\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); sf = ACCESS_FLAG(F_SF) != 0; of = ACCESS_FLAG(F_OF) != 0; /* note: inverse of above, but using == instead of xor. */ if (sf == of) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x7e ****************************************************************************/ static void x86emuOp_jump_near_LE(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; int sf, of; /* jump to byte offset if sign flag not equal to overflow flag or the zero flag is set */ START_OF_INSTR(); DECODE_PRINTF("JLE\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); sf = ACCESS_FLAG(F_SF) != 0; of = ACCESS_FLAG(F_OF) != 0; if ((sf ^ of) || ACCESS_FLAG(F_ZF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x7f ****************************************************************************/ static void x86emuOp_jump_near_NLE(u8 X86EMU_UNUSED(op1)) { s8 offset; u16 target; int sf, of; /* jump to byte offset if sign flag equal to overflow flag. and the zero flag is clear */ START_OF_INSTR(); DECODE_PRINTF("JNLE\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + (s16)offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); sf = ACCESS_FLAG(F_SF) != 0; of = ACCESS_FLAG(F_OF) != 0; if ((sf == of) && !ACCESS_FLAG(F_ZF)) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } static u8 (*opc80_byte_operation[])(u8 d, u8 s) = { add_byte, /* 00 */ or_byte, /* 01 */ adc_byte, /* 02 */ sbb_byte, /* 03 */ and_byte, /* 04 */ sub_byte, /* 05 */ xor_byte, /* 06 */ cmp_byte, /* 07 */ }; /**************************************************************************** REMARKS: Handles opcode 0x80 ****************************************************************************/ static void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 imm; u8 destval; /* * Weirdo special case instruction format. Part of the opcode * held below in "RH". Doubly nested case would result, except * that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ADD\t"); break; case 1: DECODE_PRINTF("OR\t"); break; case 2: DECODE_PRINTF("ADC\t"); break; case 3: DECODE_PRINTF("SBB\t"); break; case 4: DECODE_PRINTF("AND\t"); break; case 5: DECODE_PRINTF("SUB\t"); break; case 6: DECODE_PRINTF("XOR\t"); break; case 7: DECODE_PRINTF("CMP\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc80_byte_operation[rh]) (destval, imm); if (rh != 7) store_data_byte(destoffset, destval); break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc80_byte_operation[rh]) (destval, imm); if (rh != 7) store_data_byte(destoffset, destval); break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc80_byte_operation[rh]) (destval, imm); if (rh != 7) store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc80_byte_operation[rh]) (*destreg, imm); if (rh != 7) *destreg = destval; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } static u16 (*opc81_word_operation[])(u16 d, u16 s) = { add_word, /*00 */ or_word, /*01 */ adc_word, /*02 */ sbb_word, /*03 */ and_word, /*04 */ sub_word, /*05 */ xor_word, /*06 */ cmp_word, /*07 */ }; static u32 (*opc81_long_operation[])(u32 d, u32 s) = { add_long, /*00 */ or_long, /*01 */ adc_long, /*02 */ sbb_long, /*03 */ and_long, /*04 */ sub_long, /*05 */ xor_long, /*06 */ cmp_long, /*07 */ }; /**************************************************************************** REMARKS: Handles opcode 0x81 ****************************************************************************/ static void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; /* * Weirdo special case instruction format. Part of the opcode * held below in "RH". Doubly nested case would result, except * that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ADD\t"); break; case 1: DECODE_PRINTF("OR\t"); break; case 2: DECODE_PRINTF("ADC\t"); break; case 3: DECODE_PRINTF("SBB\t"); break; case 4: DECODE_PRINTF("AND\t"); break; case 5: DECODE_PRINTF("SUB\t"); break; case 6: DECODE_PRINTF("XOR\t"); break; case 7: DECODE_PRINTF("CMP\t"); break; } } #endif /* * Know operation, decode the mod byte to find the addressing * mode. */ switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); imm = fetch_long_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_long_operation[rh]) (destval, imm); if (rh != 7) store_data_long(destoffset, destval); } else { u16 destval,imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); imm = fetch_word_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_word_operation[rh]) (destval, imm); if (rh != 7) store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); imm = fetch_long_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_long_operation[rh]) (destval, imm); if (rh != 7) store_data_long(destoffset, destval); } else { u16 destval,imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); imm = fetch_word_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_word_operation[rh]) (destval, imm); if (rh != 7) store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); imm = fetch_long_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_long_operation[rh]) (destval, imm); if (rh != 7) store_data_long(destoffset, destval); } else { u16 destval,imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); imm = fetch_word_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_word_operation[rh]) (destval, imm); if (rh != 7) store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 destval,imm; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); imm = fetch_long_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_long_operation[rh]) (*destreg, imm); if (rh != 7) *destreg = destval; } else { u16 *destreg; u16 destval,imm; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); imm = fetch_word_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); destval = (*opc81_word_operation[rh]) (*destreg, imm); if (rh != 7) *destreg = destval; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } static u8 (*opc82_byte_operation[])(u8 s, u8 d) = { add_byte, /*00 */ or_byte, /*01 *//*YYY UNUSED ???? */ adc_byte, /*02 */ sbb_byte, /*03 */ and_byte, /*04 *//*YYY UNUSED ???? */ sub_byte, /*05 */ xor_byte, /*06 *//*YYY UNUSED ???? */ cmp_byte, /*07 */ }; /**************************************************************************** REMARKS: Handles opcode 0x82 ****************************************************************************/ static void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 imm; u8 destval; /* * Weirdo special case instruction format. Part of the opcode * held below in "RH". Doubly nested case would result, except * that the decoded instruction Similar to opcode 81, except that * the immediate byte is sign extended to a word length. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ADD\t"); break; case 1: DECODE_PRINTF("OR\t"); break; case 2: DECODE_PRINTF("ADC\t"); break; case 3: DECODE_PRINTF("SBB\t"); break; case 4: DECODE_PRINTF("AND\t"); break; case 5: DECODE_PRINTF("SUB\t"); break; case 6: DECODE_PRINTF("XOR\t"); break; case 7: DECODE_PRINTF("CMP\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); destval = fetch_data_byte(destoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc82_byte_operation[rh]) (destval, imm); if (rh != 7) store_data_byte(destoffset, destval); break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); destval = fetch_data_byte(destoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc82_byte_operation[rh]) (destval, imm); if (rh != 7) store_data_byte(destoffset, destval); break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); destval = fetch_data_byte(destoffset); imm = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc82_byte_operation[rh]) (destval, imm); if (rh != 7) store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc82_byte_operation[rh]) (*destreg, imm); if (rh != 7) *destreg = destval; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } static u16 (*opc83_word_operation[])(u16 s, u16 d) = { add_word, /*00 */ or_word, /*01 *//*YYY UNUSED ???? */ adc_word, /*02 */ sbb_word, /*03 */ and_word, /*04 *//*YYY UNUSED ???? */ sub_word, /*05 */ xor_word, /*06 *//*YYY UNUSED ???? */ cmp_word, /*07 */ }; static u32 (*opc83_long_operation[])(u32 s, u32 d) = { add_long, /*00 */ or_long, /*01 *//*YYY UNUSED ???? */ adc_long, /*02 */ sbb_long, /*03 */ and_long, /*04 *//*YYY UNUSED ???? */ sub_long, /*05 */ xor_long, /*06 *//*YYY UNUSED ???? */ cmp_long, /*07 */ }; /**************************************************************************** REMARKS: Handles opcode 0x83 ****************************************************************************/ static void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; /* * Weirdo special case instruction format. Part of the opcode * held below in "RH". Doubly nested case would result, except * that the decoded instruction Similar to opcode 81, except that * the immediate byte is sign extended to a word length. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ADD\t"); break; case 1: DECODE_PRINTF("OR\t"); break; case 2: DECODE_PRINTF("ADC\t"); break; case 3: DECODE_PRINTF("SBB\t"); break; case 4: DECODE_PRINTF("AND\t"); break; case 5: DECODE_PRINTF("SUB\t"); break; case 6: DECODE_PRINTF("XOR\t"); break; case 7: DECODE_PRINTF("CMP\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm00_address(rl); destval = fetch_data_long(destoffset); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_long_operation[rh]) (destval, imm); if (rh != 7) store_data_long(destoffset, destval); } else { u16 destval,imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm00_address(rl); destval = fetch_data_word(destoffset); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_word_operation[rh]) (destval, imm); if (rh != 7) store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm01_address(rl); destval = fetch_data_long(destoffset); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_long_operation[rh]) (destval, imm); if (rh != 7) store_data_long(destoffset, destval); } else { u16 destval,imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm01_address(rl); destval = fetch_data_word(destoffset); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_word_operation[rh]) (destval, imm); if (rh != 7) store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm10_address(rl); destval = fetch_data_long(destoffset); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_long_operation[rh]) (destval, imm); if (rh != 7) store_data_long(destoffset, destval); } else { u16 destval,imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm10_address(rl); destval = fetch_data_word(destoffset); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_word_operation[rh]) (destval, imm); if (rh != 7) store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 destval,imm; destreg = DECODE_RM_LONG_REGISTER(rl); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_long_operation[rh]) (*destreg, imm); if (rh != 7) *destreg = destval; } else { u16 *destreg; u16 destval,imm; destreg = DECODE_RM_WORD_REGISTER(rl); imm = (s8) fetch_byte_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); destval = (*opc83_word_operation[rh]) (*destreg, imm); if (rh != 7) *destreg = destval; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x84 ****************************************************************************/ static void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; START_OF_INSTR(); DECODE_PRINTF("TEST\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_byte(destval, *srcreg); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_byte(destval, *srcreg); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_byte(destval, *srcreg); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x85 ****************************************************************************/ static void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("TEST\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_long(destval, *srcreg); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_word(destval, *srcreg); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_long(destval, *srcreg); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_word(destval, *srcreg); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_long(destval, *srcreg); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_word(destval, *srcreg); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); test_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x86 ****************************************************************************/ static void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; u8 destval; u8 tmp; START_OF_INSTR(); DECODE_PRINTF("XCHG\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = *destreg; *destreg = tmp; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x87 ****************************************************************************/ static void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("XCHG\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; u32 destval,tmp; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_long(destoffset, destval); } else { u16 *srcreg; u16 destval,tmp; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; u32 destval,tmp; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_long(destoffset, destval); } else { u16 *srcreg; u16 destval,tmp; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; u32 destval,tmp; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_long(destoffset, destval); } else { u16 *srcreg; u16 destval,tmp; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = destval; destval = tmp; store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; u32 tmp; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = *destreg; *destreg = tmp; } else { u16 *destreg,*srcreg; u16 tmp; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); tmp = *srcreg; *srcreg = *destreg; *destreg = tmp; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x88 ****************************************************************************/ static void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_byte(destoffset, *srcreg); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_byte(destoffset, *srcreg); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_byte(destoffset, *srcreg); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x89 ****************************************************************************/ static void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u32 destoffset; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_long(destoffset, *srcreg); } else { u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_word(destoffset, *srcreg); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_long(destoffset, *srcreg); } else { u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_word(destoffset, *srcreg); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_long(destoffset, *srcreg); } else { u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); store_data_word(destoffset, *srcreg); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x8a ****************************************************************************/ static void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x8b ****************************************************************************/ static void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg, *srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; } else { u16 *destreg, *srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x8c ****************************************************************************/ static void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u16 *destreg, *srcreg; uint destoffset; u16 destval; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcreg = decode_rm_seg_register(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = *srcreg; store_data_word(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcreg = decode_rm_seg_register(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = *srcreg; store_data_word(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcreg = decode_rm_seg_register(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = *srcreg; store_data_word(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = decode_rm_seg_register(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x8d ****************************************************************************/ static void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u16 *srcreg; uint destoffset; /* * TODO: Need to handle address size prefix! * * lea eax,[eax+ebx*2] ?? */ START_OF_INSTR(); DECODE_PRINTF("LEA\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *srcreg = (u16)destoffset; break; case 1: srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *srcreg = (u16)destoffset; break; case 2: srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *srcreg = (u16)destoffset; break; case 3: /* register to register */ /* undefined. Do nothing. */ break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x8e ****************************************************************************/ static void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u16 *destreg, *srcreg; uint srcoffset; u16 srcval; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = decode_rm_seg_register(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 1: destreg = decode_rm_seg_register(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 2: destreg = decode_rm_seg_register(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 3: /* register to register */ destreg = decode_rm_seg_register(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; break; } /* * Clean up, and reset all the R_xSP pointers to the correct * locations. This is about 3x too much overhead (doing all the * segreg ptrs when only one is needed, but this instruction * *cannot* be that common, and this isn't too much work anyway. */ DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x8f ****************************************************************************/ static void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("POP\t"); FETCH_DECODE_MODRM(mod, rh, rl); if (rh != 0) { DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); HALT_SYS(); } switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = pop_long(); store_data_long(destoffset, destval); } else { u16 destval; destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = pop_word(); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = pop_long(); store_data_long(destoffset, destval); } else { u16 destval; destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = pop_word(); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = pop_long(); store_data_long(destoffset, destval); } else { u16 destval; destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = pop_word(); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = pop_long(); } else { u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = pop_word(); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x90 ****************************************************************************/ static void x86emuOp_nop(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("NOP\n"); TRACE_AND_STEP(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x91 ****************************************************************************/ static void x86emuOp_xchg_word_AX_CX(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,ECX\n"); } else { DECODE_PRINTF("XCHG\tAX,CX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_ECX; M.x86.R_ECX = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_CX; M.x86.R_CX = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x92 ****************************************************************************/ static void x86emuOp_xchg_word_AX_DX(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,EDX\n"); } else { DECODE_PRINTF("XCHG\tAX,DX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_EDX; M.x86.R_EDX = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_DX; M.x86.R_DX = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x93 ****************************************************************************/ static void x86emuOp_xchg_word_AX_BX(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,EBX\n"); } else { DECODE_PRINTF("XCHG\tAX,BX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_EBX; M.x86.R_EBX = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_BX; M.x86.R_BX = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x94 ****************************************************************************/ static void x86emuOp_xchg_word_AX_SP(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,ESP\n"); } else { DECODE_PRINTF("XCHG\tAX,SP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_ESP; M.x86.R_ESP = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_SP; M.x86.R_SP = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x95 ****************************************************************************/ static void x86emuOp_xchg_word_AX_BP(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,EBP\n"); } else { DECODE_PRINTF("XCHG\tAX,BP\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_EBP; M.x86.R_EBP = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_BP; M.x86.R_BP = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x96 ****************************************************************************/ static void x86emuOp_xchg_word_AX_SI(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,ESI\n"); } else { DECODE_PRINTF("XCHG\tAX,SI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_ESI; M.x86.R_ESI = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_SI; M.x86.R_SI = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x97 ****************************************************************************/ static void x86emuOp_xchg_word_AX_DI(u8 X86EMU_UNUSED(op1)) { u32 tmp; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("XCHG\tEAX,EDI\n"); } else { DECODE_PRINTF("XCHG\tAX,DI\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { tmp = M.x86.R_EAX; M.x86.R_EAX = M.x86.R_EDI; M.x86.R_EDI = tmp; } else { tmp = M.x86.R_AX; M.x86.R_AX = M.x86.R_DI; M.x86.R_DI = (u16)tmp; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x98 ****************************************************************************/ static void x86emuOp_cbw(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("CWDE\n"); } else { DECODE_PRINTF("CBW\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { if (M.x86.R_AX & 0x8000) { M.x86.R_EAX |= 0xffff0000; } else { M.x86.R_EAX &= 0x0000ffff; } } else { if (M.x86.R_AL & 0x80) { M.x86.R_AH = 0xff; } else { M.x86.R_AH = 0x0; } } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x99 ****************************************************************************/ static void x86emuOp_cwd(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("CDQ\n"); } else { DECODE_PRINTF("CWD\n"); } DECODE_PRINTF("CWD\n"); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { if (M.x86.R_EAX & 0x80000000) { M.x86.R_EDX = 0xffffffff; } else { M.x86.R_EDX = 0x0; } } else { if (M.x86.R_AX & 0x8000) { M.x86.R_DX = 0xffff; } else { M.x86.R_DX = 0x0; } } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x9a ****************************************************************************/ static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1)) { u16 farseg, faroff; START_OF_INSTR(); DECODE_PRINTF("CALL\t"); faroff = fetch_word_imm(); farseg = fetch_word_imm(); DECODE_PRINTF2("%04x:", farseg); DECODE_PRINTF2("%04x\n", faroff); CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR "); /* XXX * * Hooked interrupt vectors calling into our "BIOS" will cause * problems unless all intersegment stuff is checked for BIOS * access. Check needed here. For moment, let it alone. */ TRACE_AND_STEP(); push_word(M.x86.R_CS); M.x86.R_CS = farseg; push_word(M.x86.R_IP); M.x86.R_IP = faroff; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x9b ****************************************************************************/ static void x86emuOp_wait(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("WAIT"); TRACE_AND_STEP(); /* NADA. */ DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x9c ****************************************************************************/ static void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1)) { u32 flags; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("PUSHFD\n"); } else { DECODE_PRINTF("PUSHF\n"); } TRACE_AND_STEP(); /* clear out *all* bits not representing flags, and turn on real bits */ flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON; if (M.x86.mode & SYSMODE_PREFIX_DATA) { push_long(flags); } else { push_word((u16)flags); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x9d ****************************************************************************/ static void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("POPFD\n"); } else { DECODE_PRINTF("POPF\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EFLG = pop_long(); } else { M.x86.R_FLG = pop_word(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x9e ****************************************************************************/ static void x86emuOp_sahf(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("SAHF\n"); TRACE_AND_STEP(); /* clear the lower bits of the flag register */ M.x86.R_FLG &= 0xffffff00; /* or in the AH register into the flags register */ M.x86.R_FLG |= M.x86.R_AH; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x9f ****************************************************************************/ static void x86emuOp_lahf(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("LAHF\n"); TRACE_AND_STEP(); M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff); /*undocumented TC++ behavior??? Nope. It's documented, but you have too look real hard to notice it. */ M.x86.R_AH |= 0x2; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa0 ****************************************************************************/ static void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1)) { u16 offset; START_OF_INSTR(); DECODE_PRINTF("MOV\tAL,"); offset = fetch_word_imm(); DECODE_PRINTF2("[%04x]\n", offset); TRACE_AND_STEP(); M.x86.R_AL = fetch_data_byte(offset); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa1 ****************************************************************************/ static void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1)) { u16 offset; START_OF_INSTR(); offset = fetch_word_imm(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset); } else { DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = fetch_data_long(offset); } else { M.x86.R_AX = fetch_data_word(offset); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa2 ****************************************************************************/ static void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1)) { u16 offset; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); offset = fetch_word_imm(); DECODE_PRINTF2("[%04x],AL\n", offset); TRACE_AND_STEP(); store_data_byte(offset, M.x86.R_AL); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa3 ****************************************************************************/ static void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1)) { u16 offset; START_OF_INSTR(); offset = fetch_word_imm(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset); } else { DECODE_PRINTF2("MOV\t[%04x],AX\n", offset); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { store_data_long(offset, M.x86.R_EAX); } else { store_data_word(offset, M.x86.R_AX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa4 ****************************************************************************/ static void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1)) { u8 val; u32 count; int inc; START_OF_INSTR(); DECODE_PRINTF("MOVS\tBYTE\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -1; else inc = 1; TRACE_AND_STEP(); count = 1; if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* move them until CX is ZERO. */ count = M.x86.R_CX; M.x86.R_CX = 0; M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } while (count--) { val = fetch_data_byte(M.x86.R_SI); store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val); M.x86.R_SI += inc; M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa5 ****************************************************************************/ static void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1)) { u32 val; int inc; u32 count; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOVS\tDWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -4; else inc = 4; } else { DECODE_PRINTF("MOVS\tWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -2; else inc = 2; } TRACE_AND_STEP(); count = 1; if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* move them until CX is ZERO. */ count = M.x86.R_CX; M.x86.R_CX = 0; M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } while (count--) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val = fetch_data_long(M.x86.R_SI); store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val); } else { val = fetch_data_word(M.x86.R_SI); store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val); } M.x86.R_SI += inc; M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa6 ****************************************************************************/ static void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1)) { s8 val1, val2; int inc; START_OF_INSTR(); DECODE_PRINTF("CMPS\tBYTE\n"); TRACE_AND_STEP(); if (ACCESS_FLAG(F_DF)) /* down */ inc = -1; else inc = 1; if (M.x86.mode & SYSMODE_PREFIX_REPE) { /* REPE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { val1 = fetch_data_byte(M.x86.R_SI); val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); cmp_byte(val1, val2); M.x86.R_CX -= 1; M.x86.R_SI += inc; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF) == 0) break; } M.x86.mode &= ~SYSMODE_PREFIX_REPE; } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { /* REPNE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { val1 = fetch_data_byte(M.x86.R_SI); val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); cmp_byte(val1, val2); M.x86.R_CX -= 1; M.x86.R_SI += inc; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF)) break; /* zero flag set means equal */ } M.x86.mode &= ~SYSMODE_PREFIX_REPNE; } else { val1 = fetch_data_byte(M.x86.R_SI); val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); cmp_byte(val1, val2); M.x86.R_SI += inc; M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa7 ****************************************************************************/ static void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1)) { u32 val1,val2; int inc; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("CMPS\tDWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -4; else inc = 4; } else { DECODE_PRINTF("CMPS\tWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -2; else inc = 2; } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_REPE) { /* REPE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val1 = fetch_data_long(M.x86.R_SI); val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); cmp_long(val1, val2); } else { val1 = fetch_data_word(M.x86.R_SI); val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); cmp_word((u16)val1, (u16)val2); } M.x86.R_CX -= 1; M.x86.R_SI += inc; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF) == 0) break; } M.x86.mode &= ~SYSMODE_PREFIX_REPE; } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { /* REPNE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val1 = fetch_data_long(M.x86.R_SI); val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); cmp_long(val1, val2); } else { val1 = fetch_data_word(M.x86.R_SI); val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); cmp_word((u16)val1, (u16)val2); } M.x86.R_CX -= 1; M.x86.R_SI += inc; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF)) break; /* zero flag set means equal */ } M.x86.mode &= ~SYSMODE_PREFIX_REPNE; } else { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val1 = fetch_data_long(M.x86.R_SI); val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); cmp_long(val1, val2); } else { val1 = fetch_data_word(M.x86.R_SI); val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); cmp_word((u16)val1, (u16)val2); } M.x86.R_SI += inc; M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa8 ****************************************************************************/ static void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1)) { int imm; START_OF_INSTR(); DECODE_PRINTF("TEST\tAL,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%04x\n", imm); TRACE_AND_STEP(); test_byte(M.x86.R_AL, (u8)imm); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xa9 ****************************************************************************/ static void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("TEST\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("TEST\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { test_long(M.x86.R_EAX, srcval); } else { test_word(M.x86.R_AX, (u16)srcval); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xaa ****************************************************************************/ static void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1)) { int inc; START_OF_INSTR(); DECODE_PRINTF("STOS\tBYTE\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -1; else inc = 1; TRACE_AND_STEP(); if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); M.x86.R_CX -= 1; M.x86.R_DI += inc; } M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } else { store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xab ****************************************************************************/ static void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1)) { int inc; u32 count; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("STOS\tDWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -4; else inc = 4; } else { DECODE_PRINTF("STOS\tWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -2; else inc = 2; } TRACE_AND_STEP(); count = 1; if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* move them until CX is ZERO. */ count = M.x86.R_CX; M.x86.R_CX = 0; M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } while (count--) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX); } else { store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX); } M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xac ****************************************************************************/ static void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1)) { int inc; START_OF_INSTR(); DECODE_PRINTF("LODS\tBYTE\n"); TRACE_AND_STEP(); if (ACCESS_FLAG(F_DF)) /* down */ inc = -1; else inc = 1; if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { M.x86.R_AL = fetch_data_byte(M.x86.R_SI); M.x86.R_CX -= 1; M.x86.R_SI += inc; } M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } else { M.x86.R_AL = fetch_data_byte(M.x86.R_SI); M.x86.R_SI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xad ****************************************************************************/ static void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1)) { int inc; u32 count; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("LODS\tDWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -4; else inc = 4; } else { DECODE_PRINTF("LODS\tWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -2; else inc = 2; } TRACE_AND_STEP(); count = 1; if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* move them until CX is ZERO. */ count = M.x86.R_CX; M.x86.R_CX = 0; M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } while (count--) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = fetch_data_long(M.x86.R_SI); } else { M.x86.R_AX = fetch_data_word(M.x86.R_SI); } M.x86.R_SI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xae ****************************************************************************/ static void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1)) { s8 val2; int inc; START_OF_INSTR(); DECODE_PRINTF("SCAS\tBYTE\n"); TRACE_AND_STEP(); if (ACCESS_FLAG(F_DF)) /* down */ inc = -1; else inc = 1; if (M.x86.mode & SYSMODE_PREFIX_REPE) { /* REPE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); cmp_byte(M.x86.R_AL, val2); M.x86.R_CX -= 1; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF) == 0) break; } M.x86.mode &= ~SYSMODE_PREFIX_REPE; } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { /* REPNE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); cmp_byte(M.x86.R_AL, val2); M.x86.R_CX -= 1; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF)) break; /* zero flag set means equal */ } M.x86.mode &= ~SYSMODE_PREFIX_REPNE; } else { val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); cmp_byte(M.x86.R_AL, val2); M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xaf ****************************************************************************/ static void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1)) { int inc; u32 val; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("SCAS\tDWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -4; else inc = 4; } else { DECODE_PRINTF("SCAS\tWORD\n"); if (ACCESS_FLAG(F_DF)) /* down */ inc = -2; else inc = 2; } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_REPE) { /* REPE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); cmp_long(M.x86.R_EAX, val); } else { val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); cmp_word(M.x86.R_AX, (u16)val); } M.x86.R_CX -= 1; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF) == 0) break; } M.x86.mode &= ~SYSMODE_PREFIX_REPE; } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { /* REPNE */ /* move them until CX is ZERO. */ while (M.x86.R_CX != 0) { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); cmp_long(M.x86.R_EAX, val); } else { val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); cmp_word(M.x86.R_AX, (u16)val); } M.x86.R_CX -= 1; M.x86.R_DI += inc; if (ACCESS_FLAG(F_ZF)) break; /* zero flag set means equal */ } M.x86.mode &= ~SYSMODE_PREFIX_REPNE; } else { if (M.x86.mode & SYSMODE_PREFIX_DATA) { val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); cmp_long(M.x86.R_EAX, val); } else { val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); cmp_word(M.x86.R_AX, (u16)val); } M.x86.R_DI += inc; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb0 ****************************************************************************/ static void x86emuOp_mov_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tAL,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_AL = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb1 ****************************************************************************/ static void x86emuOp_mov_byte_CL_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tCL,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_CL = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb2 ****************************************************************************/ static void x86emuOp_mov_byte_DL_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tDL,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_DL = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb3 ****************************************************************************/ static void x86emuOp_mov_byte_BL_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tBL,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_BL = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb4 ****************************************************************************/ static void x86emuOp_mov_byte_AH_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tAH,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_AH = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb5 ****************************************************************************/ static void x86emuOp_mov_byte_CH_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tCH,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_CH = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb6 ****************************************************************************/ static void x86emuOp_mov_byte_DH_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tDH,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_DH = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb7 ****************************************************************************/ static void x86emuOp_mov_byte_BH_IMM(u8 X86EMU_UNUSED(op1)) { u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\tBH,"); imm = fetch_byte_imm(); DECODE_PRINTF2("%x\n", imm); TRACE_AND_STEP(); M.x86.R_BH = imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb8 ****************************************************************************/ static void x86emuOp_mov_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = srcval; } else { M.x86.R_AX = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xb9 ****************************************************************************/ static void x86emuOp_mov_word_CX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tECX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tCX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = srcval; } else { M.x86.R_CX = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xba ****************************************************************************/ static void x86emuOp_mov_word_DX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tEDX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tDX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDX = srcval; } else { M.x86.R_DX = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xbb ****************************************************************************/ static void x86emuOp_mov_word_BX_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tEBX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tBX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBX = srcval; } else { M.x86.R_BX = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xbc ****************************************************************************/ static void x86emuOp_mov_word_SP_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tESP,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tSP,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESP = srcval; } else { M.x86.R_SP = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xbd ****************************************************************************/ static void x86emuOp_mov_word_BP_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tEBP,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tBP,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EBP = srcval; } else { M.x86.R_BP = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xbe ****************************************************************************/ static void x86emuOp_mov_word_SI_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tESI,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tSI,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ESI = srcval; } else { M.x86.R_SI = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xbf ****************************************************************************/ static void x86emuOp_mov_word_DI_IMM(u8 X86EMU_UNUSED(op1)) { u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("MOV\tEDI,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("MOV\tDI,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EDI = srcval; } else { M.x86.R_DI = (u16)srcval; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /* used by opcodes c0, d0, and d2. */ static u8(*opcD0_byte_operation[])(u8 d, u8 s) = { rol_byte, ror_byte, rcl_byte, rcr_byte, shl_byte, shr_byte, shl_byte, /* sal_byte === shl_byte by definition */ sar_byte, }; /**************************************************************************** REMARKS: Handles opcode 0xc0 ****************************************************************************/ static void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 destval; u8 amt; /* * Yet another weirdo special case instruction format. Part of * the opcode held below in "RH". Doubly nested case would * result, except that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ROL\t"); break; case 1: DECODE_PRINTF("ROR\t"); break; case 2: DECODE_PRINTF("RCL\t"); break; case 3: DECODE_PRINTF("RCR\t"); break; case 4: DECODE_PRINTF("SHL\t"); break; case 5: DECODE_PRINTF("SHR\t"); break; case 6: DECODE_PRINTF("SAL\t"); break; case 7: DECODE_PRINTF("SAR\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, amt); store_data_byte(destoffset, destval); break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, amt); store_data_byte(destoffset, destval); break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, amt); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (*destreg, amt); *destreg = destval; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /* used by opcodes c1, d1, and d3. */ static u16(*opcD1_word_operation[])(u16 s, u8 d) = { rol_word, ror_word, rcl_word, rcr_word, shl_word, shr_word, shl_word, /* sal_byte === shl_byte by definition */ sar_word, }; /* used by opcodes c1, d1, and d3. */ static u32 (*opcD1_long_operation[])(u32 s, u8 d) = { rol_long, ror_long, rcl_long, rcr_long, shl_long, shr_long, shl_long, /* sal_byte === shl_byte by definition */ sar_long, }; /**************************************************************************** REMARKS: Handles opcode 0xc1 ****************************************************************************/ static void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; u8 amt; /* * Yet another weirdo special case instruction format. Part of * the opcode held below in "RH". Doubly nested case would * result, except that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ROL\t"); break; case 1: DECODE_PRINTF("ROR\t"); break; case 2: DECODE_PRINTF("RCL\t"); break; case 3: DECODE_PRINTF("RCR\t"); break; case 4: DECODE_PRINTF("SHL\t"); break; case 5: DECODE_PRINTF("SHR\t"); break; case 6: DECODE_PRINTF("SAL\t"); break; case 7: DECODE_PRINTF("SAR\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm00_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, amt); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm00_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, amt); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm01_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, amt); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm01_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, amt); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm10_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, amt); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm10_address(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, amt); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); TRACE_AND_STEP(); *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); } else { u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); amt = fetch_byte_imm(); DECODE_PRINTF2(",%x\n", amt); TRACE_AND_STEP(); *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc2 ****************************************************************************/ static void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1)) { u16 imm; START_OF_INSTR(); DECODE_PRINTF("RET\t"); imm = fetch_word_imm(); DECODE_PRINTF2("%x\n", imm); RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip); TRACE_AND_STEP(); M.x86.R_IP = pop_word(); M.x86.R_SP += imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc3 ****************************************************************************/ static void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("RET\n"); RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip); TRACE_AND_STEP(); M.x86.R_IP = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc4 ****************************************************************************/ static void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rh, rl; u16 *dstreg; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("LES\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_ES = fetch_data_word(srcoffset + 2); break; case 1: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_ES = fetch_data_word(srcoffset + 2); break; case 2: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_ES = fetch_data_word(srcoffset + 2); break; case 3: /* register to register */ /* UNDEFINED! */ TRACE_AND_STEP(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc5 ****************************************************************************/ static void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rh, rl; u16 *dstreg; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("LDS\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_DS = fetch_data_word(srcoffset + 2); break; case 1: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_DS = fetch_data_word(srcoffset + 2); break; case 2: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_DS = fetch_data_word(srcoffset + 2); break; case 3: /* register to register */ /* UNDEFINED! */ TRACE_AND_STEP(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc6 ****************************************************************************/ static void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 imm; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); if (rh != 0) { DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n"); HALT_SYS(); } switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%2x\n", imm); TRACE_AND_STEP(); store_data_byte(destoffset, imm); break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%2x\n", imm); TRACE_AND_STEP(); store_data_byte(destoffset, imm); break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%2x\n", imm); TRACE_AND_STEP(); store_data_byte(destoffset, imm); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); imm = fetch_byte_imm(); DECODE_PRINTF2(",%2x\n", imm); TRACE_AND_STEP(); *destreg = imm; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc7 ****************************************************************************/ static void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); if (rh != 0) { DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); HALT_SYS(); } switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm00_address(rl); imm = fetch_long_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); store_data_long(destoffset, imm); } else { u16 imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm00_address(rl); imm = fetch_word_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); store_data_word(destoffset, imm); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm01_address(rl); imm = fetch_long_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); store_data_long(destoffset, imm); } else { u16 imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm01_address(rl); imm = fetch_word_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); store_data_word(destoffset, imm); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 imm; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm10_address(rl); imm = fetch_long_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); store_data_long(destoffset, imm); } else { u16 imm; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm10_address(rl); imm = fetch_word_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); store_data_word(destoffset, imm); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 imm; destreg = DECODE_RM_LONG_REGISTER(rl); imm = fetch_long_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); *destreg = imm; } else { u16 *destreg; u16 imm; destreg = DECODE_RM_WORD_REGISTER(rl); imm = fetch_word_imm(); DECODE_PRINTF2(",%x\n", imm); TRACE_AND_STEP(); *destreg = imm; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc8 ****************************************************************************/ static void x86emuOp_enter(u8 X86EMU_UNUSED(op1)) { u16 local,frame_pointer; u8 nesting; int i; START_OF_INSTR(); local = fetch_word_imm(); nesting = fetch_byte_imm(); DECODE_PRINTF2("ENTER %x\n", local); DECODE_PRINTF2(",%x\n", nesting); TRACE_AND_STEP(); push_word(M.x86.R_BP); frame_pointer = M.x86.R_SP; if (nesting > 0) { for (i = 1; i < nesting; i++) { M.x86.R_BP -= 2; push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP)); } push_word(frame_pointer); } M.x86.R_BP = frame_pointer; M.x86.R_SP = (u16)(M.x86.R_SP - local); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xc9 ****************************************************************************/ static void x86emuOp_leave(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("LEAVE\n"); TRACE_AND_STEP(); M.x86.R_SP = M.x86.R_BP; M.x86.R_BP = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xca ****************************************************************************/ static void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1)) { u16 imm; START_OF_INSTR(); DECODE_PRINTF("RETF\t"); imm = fetch_word_imm(); DECODE_PRINTF2("%x\n", imm); RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip); TRACE_AND_STEP(); M.x86.R_IP = pop_word(); M.x86.R_CS = pop_word(); M.x86.R_SP += imm; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xcb ****************************************************************************/ static void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("RETF\n"); RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip); TRACE_AND_STEP(); M.x86.R_IP = pop_word(); M.x86.R_CS = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xcc ****************************************************************************/ static void x86emuOp_int3(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("INT 3\n"); TRACE_AND_STEP(); if (_X86EMU_intrTab[3]) { (*_X86EMU_intrTab[3])(3); } else { push_word((u16)M.x86.R_FLG); CLEAR_FLAG(F_IF); CLEAR_FLAG(F_TF); push_word(M.x86.R_CS); M.x86.R_CS = mem_access_word(3 * 4 + 2); push_word(M.x86.R_IP); M.x86.R_IP = mem_access_word(3 * 4); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xcd ****************************************************************************/ static void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1)) { u8 intnum; START_OF_INSTR(); DECODE_PRINTF("INT\t"); intnum = fetch_byte_imm(); DECODE_PRINTF2("%x\n", intnum); TRACE_AND_STEP(); if (_X86EMU_intrTab[intnum]) { (*_X86EMU_intrTab[intnum])(intnum); } else { push_word((u16)M.x86.R_FLG); CLEAR_FLAG(F_IF); CLEAR_FLAG(F_TF); push_word(M.x86.R_CS); M.x86.R_CS = mem_access_word(intnum * 4 + 2); push_word(M.x86.R_IP); M.x86.R_IP = mem_access_word(intnum * 4); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xce ****************************************************************************/ static void x86emuOp_into(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("INTO\n"); TRACE_AND_STEP(); if (ACCESS_FLAG(F_OF)) { if (_X86EMU_intrTab[4]) { (*_X86EMU_intrTab[4])(4); } else { push_word((u16)M.x86.R_FLG); CLEAR_FLAG(F_IF); CLEAR_FLAG(F_TF); push_word(M.x86.R_CS); M.x86.R_CS = mem_access_word(4 * 4 + 2); push_word(M.x86.R_IP); M.x86.R_IP = mem_access_word(4 * 4); } } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xcf ****************************************************************************/ static void x86emuOp_iret(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("IRET\n"); TRACE_AND_STEP(); M.x86.R_IP = pop_word(); M.x86.R_CS = pop_word(); M.x86.R_FLG = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xd0 ****************************************************************************/ static void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 destval; /* * Yet another weirdo special case instruction format. Part of * the opcode held below in "RH". Doubly nested case would * result, except that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ROL\t"); break; case 1: DECODE_PRINTF("ROR\t"); break; case 2: DECODE_PRINTF("RCL\t"); break; case 3: DECODE_PRINTF("RCR\t"); break; case 4: DECODE_PRINTF("SHL\t"); break; case 5: DECODE_PRINTF("SHR\t"); break; case 6: DECODE_PRINTF("SAL\t"); break; case 7: DECODE_PRINTF("SAR\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, 1); store_data_byte(destoffset, destval); break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, 1); store_data_byte(destoffset, destval); break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, 1); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(",1\n"); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (*destreg, 1); *destreg = destval; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xd1 ****************************************************************************/ static void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; /* * Yet another weirdo special case instruction format. Part of * the opcode held below in "RH". Doubly nested case would * result, except that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ROL\t"); break; case 1: DECODE_PRINTF("ROR\t"); break; case 2: DECODE_PRINTF("RCL\t"); break; case 3: DECODE_PRINTF("RCR\t"); break; case 4: DECODE_PRINTF("SHL\t"); break; case 5: DECODE_PRINTF("SHR\t"); break; case 6: DECODE_PRINTF("SAL\t"); break; case 7: DECODE_PRINTF("SAR\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, 1); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, 1); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, 1); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, 1); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, 1); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(",1\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, 1); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(",1\n"); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (*destreg, 1); *destreg = destval; } else { u16 destval; u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(",1\n"); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (*destreg, 1); *destreg = destval; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xd2 ****************************************************************************/ static void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 destval; u8 amt; /* * Yet another weirdo special case instruction format. Part of * the opcode held below in "RH". Doubly nested case would * result, except that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ROL\t"); break; case 1: DECODE_PRINTF("ROR\t"); break; case 2: DECODE_PRINTF("RCL\t"); break; case 3: DECODE_PRINTF("RCR\t"); break; case 4: DECODE_PRINTF("SHL\t"); break; case 5: DECODE_PRINTF("SHR\t"); break; case 6: DECODE_PRINTF("SAL\t"); break; case 7: DECODE_PRINTF("SAR\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ amt = M.x86.R_CL; switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, amt); store_data_byte(destoffset, destval); break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, amt); store_data_byte(destoffset, destval); break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (destval, amt); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = (*opcD0_byte_operation[rh]) (*destreg, amt); *destreg = destval; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xd3 ****************************************************************************/ static void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; u8 amt; /* * Yet another weirdo special case instruction format. Part of * the opcode held below in "RH". Doubly nested case would * result, except that the decoded instruction */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("ROL\t"); break; case 1: DECODE_PRINTF("ROR\t"); break; case 2: DECODE_PRINTF("RCL\t"); break; case 3: DECODE_PRINTF("RCR\t"); break; case 4: DECODE_PRINTF("SHL\t"); break; case 5: DECODE_PRINTF("SHR\t"); break; case 6: DECODE_PRINTF("SAL\t"); break; case 7: DECODE_PRINTF("SAR\t"); break; } } #endif /* know operation, decode the mod byte to find the addressing mode. */ amt = M.x86.R_CL; switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, amt); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, amt); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, amt); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, amt); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = (*opcD1_long_operation[rh]) (destval, amt); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("WORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(",CL\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = (*opcD1_word_operation[rh]) (destval, amt); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); } else { u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xd4 ****************************************************************************/ static void x86emuOp_aam(u8 X86EMU_UNUSED(op1)) { u8 a; START_OF_INSTR(); DECODE_PRINTF("AAM\n"); a = fetch_byte_imm(); /* this is a stupid encoding. */ if (a != 10) { /* fix: add base decoding aam_word(u8 val, int base a) */ DECODE_PRINTF("ERROR DECODING AAM\n"); TRACE_REGS(); HALT_SYS(); } TRACE_AND_STEP(); /* note the type change here --- returning AL and AH in AX. */ M.x86.R_AX = aam_word(M.x86.R_AL); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xd5 ****************************************************************************/ static void x86emuOp_aad(u8 X86EMU_UNUSED(op1)) { u8 a; START_OF_INSTR(); DECODE_PRINTF("AAD\n"); a = fetch_byte_imm(); if (a != 10) { /* fix: add base decoding aad_word(u16 val, int base a) */ DECODE_PRINTF("ERROR DECODING AAM\n"); TRACE_REGS(); HALT_SYS(); } TRACE_AND_STEP(); M.x86.R_AX = aad_word(M.x86.R_AX); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /* opcode 0xd6 ILLEGAL OPCODE */ /**************************************************************************** REMARKS: Handles opcode 0xd7 ****************************************************************************/ static void x86emuOp_xlat(u8 X86EMU_UNUSED(op1)) { u16 addr; START_OF_INSTR(); DECODE_PRINTF("XLAT\n"); TRACE_AND_STEP(); addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL); M.x86.R_AL = fetch_data_byte(addr); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /* instuctions D8 .. DF are in i87_ops.c */ /**************************************************************************** REMARKS: Handles opcode 0xe0 ****************************************************************************/ static void x86emuOp_loopne(u8 X86EMU_UNUSED(op1)) { s16 ip; START_OF_INSTR(); DECODE_PRINTF("LOOPNE\t"); ip = (s8) fetch_byte_imm(); ip += (s16) M.x86.R_IP; DECODE_PRINTF2("%04x\n", ip); TRACE_AND_STEP(); M.x86.R_CX -= 1; if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ M.x86.R_IP = ip; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe1 ****************************************************************************/ static void x86emuOp_loope(u8 X86EMU_UNUSED(op1)) { s16 ip; START_OF_INSTR(); DECODE_PRINTF("LOOPE\t"); ip = (s8) fetch_byte_imm(); ip += (s16) M.x86.R_IP; DECODE_PRINTF2("%04x\n", ip); TRACE_AND_STEP(); M.x86.R_CX -= 1; if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ M.x86.R_IP = ip; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe2 ****************************************************************************/ static void x86emuOp_loop(u8 X86EMU_UNUSED(op1)) { s16 ip; START_OF_INSTR(); DECODE_PRINTF("LOOP\t"); ip = (s8) fetch_byte_imm(); ip += (s16) M.x86.R_IP; DECODE_PRINTF2("%04x\n", ip); TRACE_AND_STEP(); M.x86.R_CX -= 1; if (M.x86.R_CX != 0) M.x86.R_IP = ip; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe3 ****************************************************************************/ static void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1)) { u16 target; s8 offset; /* jump to byte offset if overflow flag is set */ START_OF_INSTR(); DECODE_PRINTF("JCXZ\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); if (M.x86.R_CX == 0) M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe4 ****************************************************************************/ static void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) { u8 port; START_OF_INSTR(); DECODE_PRINTF("IN\t"); port = (u8) fetch_byte_imm(); DECODE_PRINTF2("%x,AL\n", port); TRACE_AND_STEP(); M.x86.R_AL = (*sys_inb)(port); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe5 ****************************************************************************/ static void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1)) { u8 port; START_OF_INSTR(); DECODE_PRINTF("IN\t"); port = (u8) fetch_byte_imm(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF2("EAX,%x\n", port); } else { DECODE_PRINTF2("AX,%x\n", port); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = (*sys_inl)(port); } else { M.x86.R_AX = (*sys_inw)(port); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe6 ****************************************************************************/ static void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1)) { u8 port; START_OF_INSTR(); DECODE_PRINTF("OUT\t"); port = (u8) fetch_byte_imm(); DECODE_PRINTF2("%x,AL\n", port); TRACE_AND_STEP(); (*sys_outb)(port, M.x86.R_AL); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe7 ****************************************************************************/ static void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1)) { u8 port; START_OF_INSTR(); DECODE_PRINTF("OUT\t"); port = (u8) fetch_byte_imm(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF2("%x,EAX\n", port); } else { DECODE_PRINTF2("%x,AX\n", port); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { (*sys_outl)(port, M.x86.R_EAX); } else { (*sys_outw)(port, M.x86.R_AX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe8 ****************************************************************************/ static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) { s16 ip; START_OF_INSTR(); DECODE_PRINTF("CALL\t"); ip = (s16) fetch_word_imm(); ip += (s16) M.x86.R_IP; /* CHECK SIGN */ DECODE_PRINTF2("%04x\n", (u16)ip); CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, ""); TRACE_AND_STEP(); push_word(M.x86.R_IP); M.x86.R_IP = ip; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xe9 ****************************************************************************/ static void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1)) { int ip; START_OF_INSTR(); DECODE_PRINTF("JMP\t"); ip = (s16)fetch_word_imm(); ip += (s16)M.x86.R_IP; DECODE_PRINTF2("%04x\n", (u16)ip); TRACE_AND_STEP(); M.x86.R_IP = (u16)ip; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xea ****************************************************************************/ static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1)) { u16 cs, ip; START_OF_INSTR(); DECODE_PRINTF("JMP\tFAR "); ip = fetch_word_imm(); cs = fetch_word_imm(); DECODE_PRINTF2("%04x:", cs); DECODE_PRINTF2("%04x\n", ip); TRACE_AND_STEP(); M.x86.R_IP = ip; M.x86.R_CS = cs; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xeb ****************************************************************************/ static void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1)) { u16 target; s8 offset; START_OF_INSTR(); DECODE_PRINTF("JMP\t"); offset = (s8)fetch_byte_imm(); target = (u16)(M.x86.R_IP + offset); DECODE_PRINTF2("%x\n", target); TRACE_AND_STEP(); M.x86.R_IP = target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xec ****************************************************************************/ static void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("IN\tAL,DX\n"); TRACE_AND_STEP(); M.x86.R_AL = (*sys_inb)(M.x86.R_DX); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xed ****************************************************************************/ static void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("IN\tEAX,DX\n"); } else { DECODE_PRINTF("IN\tAX,DX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_EAX = (*sys_inl)(M.x86.R_DX); } else { M.x86.R_AX = (*sys_inw)(M.x86.R_DX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xee ****************************************************************************/ static void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("OUT\tDX,AL\n"); TRACE_AND_STEP(); (*sys_outb)(M.x86.R_DX, M.x86.R_AL); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xef ****************************************************************************/ static void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("OUT\tDX,EAX\n"); } else { DECODE_PRINTF("OUT\tDX,AX\n"); } TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { (*sys_outl)(M.x86.R_DX, M.x86.R_EAX); } else { (*sys_outw)(M.x86.R_DX, M.x86.R_AX); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf0 ****************************************************************************/ static void x86emuOp_lock(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("LOCK:\n"); TRACE_AND_STEP(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /*opcode 0xf1 ILLEGAL OPERATION */ /**************************************************************************** REMARKS: Handles opcode 0xf2 ****************************************************************************/ static void x86emuOp_repne(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("REPNE\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_PREFIX_REPNE; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf3 ****************************************************************************/ static void x86emuOp_repe(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("REPE\n"); TRACE_AND_STEP(); M.x86.mode |= SYSMODE_PREFIX_REPE; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf4 ****************************************************************************/ static void x86emuOp_halt(u8 X86EMU_UNUSED(op1)) { START_OF_INSTR(); DECODE_PRINTF("HALT\n"); TRACE_AND_STEP(); HALT_SYS(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf5 ****************************************************************************/ static void x86emuOp_cmc(u8 X86EMU_UNUSED(op1)) { /* complement the carry flag. */ START_OF_INSTR(); DECODE_PRINTF("CMC\n"); TRACE_AND_STEP(); TOGGLE_FLAG(F_CF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf6 ****************************************************************************/ static void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; u8 *destreg; uint destoffset; u8 destval, srcval; /* long, drawn out code follows. Double switch for a total of 32 cases. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: /* mod=00 */ switch (rh) { case 0: /* test byte imm */ DECODE_PRINTF("TEST\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcval = fetch_byte_imm(); DECODE_PRINTF2("%02x\n", srcval); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); test_byte(destval, srcval); break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: DECODE_PRINTF("NOT\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = not_byte(destval); store_data_byte(destoffset, destval); break; case 3: DECODE_PRINTF("NEG\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = neg_byte(destval); store_data_byte(destoffset, destval); break; case 4: DECODE_PRINTF("MUL\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); mul_byte(destval); break; case 5: DECODE_PRINTF("IMUL\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); imul_byte(destval); break; case 6: DECODE_PRINTF("DIV\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); div_byte(destval); break; case 7: DECODE_PRINTF("IDIV\tBYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); idiv_byte(destval); break; } break; /* end mod==00 */ case 1: /* mod=01 */ switch (rh) { case 0: /* test byte imm */ DECODE_PRINTF("TEST\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcval = fetch_byte_imm(); DECODE_PRINTF2("%02x\n", srcval); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); test_byte(destval, srcval); break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: DECODE_PRINTF("NOT\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = not_byte(destval); store_data_byte(destoffset, destval); break; case 3: DECODE_PRINTF("NEG\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = neg_byte(destval); store_data_byte(destoffset, destval); break; case 4: DECODE_PRINTF("MUL\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); mul_byte(destval); break; case 5: DECODE_PRINTF("IMUL\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); imul_byte(destval); break; case 6: DECODE_PRINTF("DIV\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); div_byte(destval); break; case 7: DECODE_PRINTF("IDIV\tBYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); idiv_byte(destval); break; } break; /* end mod==01 */ case 2: /* mod=10 */ switch (rh) { case 0: /* test byte imm */ DECODE_PRINTF("TEST\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcval = fetch_byte_imm(); DECODE_PRINTF2("%02x\n", srcval); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); test_byte(destval, srcval); break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: DECODE_PRINTF("NOT\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = not_byte(destval); store_data_byte(destoffset, destval); break; case 3: DECODE_PRINTF("NEG\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = neg_byte(destval); store_data_byte(destoffset, destval); break; case 4: DECODE_PRINTF("MUL\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); mul_byte(destval); break; case 5: DECODE_PRINTF("IMUL\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); imul_byte(destval); break; case 6: DECODE_PRINTF("DIV\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); div_byte(destval); break; case 7: DECODE_PRINTF("IDIV\tBYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); idiv_byte(destval); break; } break; /* end mod==10 */ case 3: /* mod=11 */ switch (rh) { case 0: /* test byte imm */ DECODE_PRINTF("TEST\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcval = fetch_byte_imm(); DECODE_PRINTF2("%02x\n", srcval); TRACE_AND_STEP(); test_byte(*destreg, srcval); break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: DECODE_PRINTF("NOT\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = not_byte(*destreg); break; case 3: DECODE_PRINTF("NEG\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = neg_byte(*destreg); break; case 4: DECODE_PRINTF("MUL\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); mul_byte(*destreg); /*!!! */ break; case 5: DECODE_PRINTF("IMUL\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); imul_byte(*destreg); break; case 6: DECODE_PRINTF("DIV\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); div_byte(*destreg); break; case 7: DECODE_PRINTF("IDIV\t"); destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); idiv_byte(*destreg); break; } break; /* end mod==11 */ } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf7 ****************************************************************************/ static void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) { int mod, rl, rh; uint destoffset; /* long, drawn out code follows. Double switch for a total of 32 cases. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: /* mod=00 */ switch (rh) { case 0: /* test word imm */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,srcval; DECODE_PRINTF("TEST\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcval = fetch_long_imm(); DECODE_PRINTF2("%x\n", srcval); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); test_long(destval, srcval); } else { u16 destval,srcval; DECODE_PRINTF("TEST\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); srcval = fetch_word_imm(); DECODE_PRINTF2("%x\n", srcval); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); test_word(destval, srcval); } break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); HALT_SYS(); break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("NOT\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = not_long(destval); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("NOT\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = not_word(destval); store_data_word(destoffset, destval); } break; case 3: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("NEG\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = neg_long(destval); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("NEG\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = neg_word(destval); store_data_word(destoffset, destval); } break; case 4: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("MUL\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); mul_long(destval); } else { u16 destval; DECODE_PRINTF("MUL\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); mul_word(destval); } break; case 5: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("IMUL\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); imul_long(destval); } else { u16 destval; DECODE_PRINTF("IMUL\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); imul_word(destval); } break; case 6: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DIV\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); div_long(destval); } else { u16 destval; DECODE_PRINTF("DIV\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); div_word(destval); } break; case 7: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("IDIV\tDWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); idiv_long(destval); } else { u16 destval; DECODE_PRINTF("IDIV\tWORD PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); idiv_word(destval); } break; } break; /* end mod==00 */ case 1: /* mod=01 */ switch (rh) { case 0: /* test word imm */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,srcval; DECODE_PRINTF("TEST\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcval = fetch_long_imm(); DECODE_PRINTF2("%x\n", srcval); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); test_long(destval, srcval); } else { u16 destval,srcval; DECODE_PRINTF("TEST\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); srcval = fetch_word_imm(); DECODE_PRINTF2("%x\n", srcval); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); test_word(destval, srcval); } break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("NOT\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = not_long(destval); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("NOT\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = not_word(destval); store_data_word(destoffset, destval); } break; case 3: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("NEG\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = neg_long(destval); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("NEG\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = neg_word(destval); store_data_word(destoffset, destval); } break; case 4: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("MUL\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); mul_long(destval); } else { u16 destval; DECODE_PRINTF("MUL\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); mul_word(destval); } break; case 5: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("IMUL\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); imul_long(destval); } else { u16 destval; DECODE_PRINTF("IMUL\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); imul_word(destval); } break; case 6: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DIV\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); div_long(destval); } else { u16 destval; DECODE_PRINTF("DIV\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); div_word(destval); } break; case 7: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("IDIV\tDWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); idiv_long(destval); } else { u16 destval; DECODE_PRINTF("IDIV\tWORD PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); idiv_word(destval); } break; } break; /* end mod==01 */ case 2: /* mod=10 */ switch (rh) { case 0: /* test word imm */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval,srcval; DECODE_PRINTF("TEST\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcval = fetch_long_imm(); DECODE_PRINTF2("%x\n", srcval); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); test_long(destval, srcval); } else { u16 destval,srcval; DECODE_PRINTF("TEST\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); srcval = fetch_word_imm(); DECODE_PRINTF2("%x\n", srcval); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); test_word(destval, srcval); } break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("NOT\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = not_long(destval); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("NOT\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = not_word(destval); store_data_word(destoffset, destval); } break; case 3: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("NEG\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = neg_long(destval); store_data_long(destoffset, destval); } else { u16 destval; DECODE_PRINTF("NEG\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = neg_word(destval); store_data_word(destoffset, destval); } break; case 4: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("MUL\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); mul_long(destval); } else { u16 destval; DECODE_PRINTF("MUL\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); mul_word(destval); } break; case 5: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("IMUL\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); imul_long(destval); } else { u16 destval; DECODE_PRINTF("IMUL\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); imul_word(destval); } break; case 6: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("DIV\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); div_long(destval); } else { u16 destval; DECODE_PRINTF("DIV\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); div_word(destval); } break; case 7: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; DECODE_PRINTF("IDIV\tDWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_long(destoffset); TRACE_AND_STEP(); idiv_long(destval); } else { u16 destval; DECODE_PRINTF("IDIV\tWORD PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); destval = fetch_data_word(destoffset); TRACE_AND_STEP(); idiv_word(destval); } break; } break; /* end mod==10 */ case 3: /* mod=11 */ switch (rh) { case 0: /* test word imm */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; DECODE_PRINTF("TEST\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcval = fetch_long_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); test_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; DECODE_PRINTF("TEST\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcval = fetch_word_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); test_word(*destreg, srcval); } break; case 1: DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; DECODE_PRINTF("NOT\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = not_long(*destreg); } else { u16 *destreg; DECODE_PRINTF("NOT\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = not_word(*destreg); } break; case 3: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; DECODE_PRINTF("NEG\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = neg_long(*destreg); } else { u16 *destreg; DECODE_PRINTF("NEG\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = neg_word(*destreg); } break; case 4: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; DECODE_PRINTF("MUL\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); mul_long(*destreg); /*!!! */ } else { u16 *destreg; DECODE_PRINTF("MUL\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); mul_word(*destreg); /*!!! */ } break; case 5: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; DECODE_PRINTF("IMUL\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); imul_long(*destreg); } else { u16 *destreg; DECODE_PRINTF("IMUL\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); imul_word(*destreg); } break; case 6: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; DECODE_PRINTF("DIV\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); div_long(*destreg); } else { u16 *destreg; DECODE_PRINTF("DIV\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); div_word(*destreg); } break; case 7: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; DECODE_PRINTF("IDIV\t"); destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); idiv_long(*destreg); } else { u16 *destreg; DECODE_PRINTF("IDIV\t"); destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); idiv_word(*destreg); } break; } break; /* end mod==11 */ } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf8 ****************************************************************************/ static void x86emuOp_clc(u8 X86EMU_UNUSED(op1)) { /* clear the carry flag. */ START_OF_INSTR(); DECODE_PRINTF("CLC\n"); TRACE_AND_STEP(); CLEAR_FLAG(F_CF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xf9 ****************************************************************************/ static void x86emuOp_stc(u8 X86EMU_UNUSED(op1)) { /* set the carry flag. */ START_OF_INSTR(); DECODE_PRINTF("STC\n"); TRACE_AND_STEP(); SET_FLAG(F_CF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xfa ****************************************************************************/ static void x86emuOp_cli(u8 X86EMU_UNUSED(op1)) { /* clear interrupts. */ START_OF_INSTR(); DECODE_PRINTF("CLI\n"); TRACE_AND_STEP(); CLEAR_FLAG(F_IF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xfb ****************************************************************************/ static void x86emuOp_sti(u8 X86EMU_UNUSED(op1)) { /* enable interrupts. */ START_OF_INSTR(); DECODE_PRINTF("STI\n"); TRACE_AND_STEP(); SET_FLAG(F_IF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xfc ****************************************************************************/ static void x86emuOp_cld(u8 X86EMU_UNUSED(op1)) { /* clear interrupts. */ START_OF_INSTR(); DECODE_PRINTF("CLD\n"); TRACE_AND_STEP(); CLEAR_FLAG(F_DF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xfd ****************************************************************************/ static void x86emuOp_std(u8 X86EMU_UNUSED(op1)) { /* clear interrupts. */ START_OF_INSTR(); DECODE_PRINTF("STD\n"); TRACE_AND_STEP(); SET_FLAG(F_DF); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xfe ****************************************************************************/ static void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) { int mod, rh, rl; u8 destval; uint destoffset; u8 *destreg; /* Yet another special case instruction. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: DECODE_PRINTF("INC\t"); break; case 1: DECODE_PRINTF("DEC\t"); break; case 2: case 3: case 4: case 5: case 6: case 7: DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod); HALT_SYS(); break; } } #endif switch (mod) { case 0: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: /* inc word ptr ... */ destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = inc_byte(destval); store_data_byte(destoffset, destval); break; case 1: /* dec word ptr ... */ destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = dec_byte(destval); store_data_byte(destoffset, destval); break; } break; case 1: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = inc_byte(destval); store_data_byte(destoffset, destval); break; case 1: destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = dec_byte(destval); store_data_byte(destoffset, destval); break; } break; case 2: DECODE_PRINTF("BYTE PTR "); destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = inc_byte(destval); store_data_byte(destoffset, destval); break; case 1: destval = fetch_data_byte(destoffset); TRACE_AND_STEP(); destval = dec_byte(destval); store_data_byte(destoffset, destval); break; } break; case 3: destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: TRACE_AND_STEP(); *destreg = inc_byte(*destreg); break; case 1: TRACE_AND_STEP(); *destreg = dec_byte(*destreg); break; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0xff ****************************************************************************/ static void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) { int mod, rh, rl; uint destoffset = 0; u16 *destreg; u16 destval,destval2; /* Yet another special case instruction. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); #ifdef DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings in the same format, even though the result is that the above test is done twice. */ switch (rh) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("INC\tDWORD PTR "); } else { DECODE_PRINTF("INC\tWORD PTR "); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("DEC\tDWORD PTR "); } else { DECODE_PRINTF("DEC\tWORD PTR "); } break; case 2: DECODE_PRINTF("CALL\t"); break; case 3: DECODE_PRINTF("CALL\tFAR "); break; case 4: DECODE_PRINTF("JMP\t"); break; case 5: DECODE_PRINTF("JMP\tFAR "); break; case 6: DECODE_PRINTF("PUSH\t"); break; case 7: DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); HALT_SYS(); break; } } #endif switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: /* inc word ptr ... */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = inc_long(destval); store_data_long(destoffset, destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = inc_word(destval); store_data_word(destoffset, destval); } break; case 1: /* dec word ptr ... */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = dec_long(destval); store_data_long(destoffset, destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = dec_word(destval); store_data_word(destoffset, destval); } break; case 2: /* call word ptr ... */ destval = fetch_data_word(destoffset); TRACE_AND_STEP(); push_word(M.x86.R_IP); M.x86.R_IP = destval; break; case 3: /* call far ptr ... */ destval = fetch_data_word(destoffset); destval2 = fetch_data_word(destoffset + 2); TRACE_AND_STEP(); push_word(M.x86.R_CS); M.x86.R_CS = destval2; push_word(M.x86.R_IP); M.x86.R_IP = destval; break; case 4: /* jmp word ptr ... */ destval = fetch_data_word(destoffset); TRACE_AND_STEP(); M.x86.R_IP = destval; break; case 5: /* jmp far ptr ... */ destval = fetch_data_word(destoffset); destval2 = fetch_data_word(destoffset + 2); TRACE_AND_STEP(); M.x86.R_IP = destval; M.x86.R_CS = destval2; break; case 6: /* push word ptr ... */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); push_long(destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); push_word(destval); } break; } break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = inc_long(destval); store_data_long(destoffset, destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = inc_word(destval); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = dec_long(destval); store_data_long(destoffset, destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = dec_word(destval); store_data_word(destoffset, destval); } break; case 2: /* call word ptr ... */ destval = fetch_data_word(destoffset); TRACE_AND_STEP(); push_word(M.x86.R_IP); M.x86.R_IP = destval; break; case 3: /* call far ptr ... */ destval = fetch_data_word(destoffset); destval2 = fetch_data_word(destoffset + 2); TRACE_AND_STEP(); push_word(M.x86.R_CS); M.x86.R_CS = destval2; push_word(M.x86.R_IP); M.x86.R_IP = destval; break; case 4: /* jmp word ptr ... */ destval = fetch_data_word(destoffset); TRACE_AND_STEP(); M.x86.R_IP = destval; break; case 5: /* jmp far ptr ... */ destval = fetch_data_word(destoffset); destval2 = fetch_data_word(destoffset + 2); TRACE_AND_STEP(); M.x86.R_IP = destval; M.x86.R_CS = destval2; break; case 6: /* push word ptr ... */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); push_long(destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); push_word(destval); } break; } break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); switch (rh) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = inc_long(destval); store_data_long(destoffset, destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = inc_word(destval); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); destval = dec_long(destval); store_data_long(destoffset, destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); destval = dec_word(destval); store_data_word(destoffset, destval); } break; case 2: /* call word ptr ... */ destval = fetch_data_word(destoffset); TRACE_AND_STEP(); push_word(M.x86.R_IP); M.x86.R_IP = destval; break; case 3: /* call far ptr ... */ destval = fetch_data_word(destoffset); destval2 = fetch_data_word(destoffset + 2); TRACE_AND_STEP(); push_word(M.x86.R_CS); M.x86.R_CS = destval2; push_word(M.x86.R_IP); M.x86.R_IP = destval; break; case 4: /* jmp word ptr ... */ destval = fetch_data_word(destoffset); TRACE_AND_STEP(); M.x86.R_IP = destval; break; case 5: /* jmp far ptr ... */ destval = fetch_data_word(destoffset); destval2 = fetch_data_word(destoffset + 2); TRACE_AND_STEP(); M.x86.R_IP = destval; M.x86.R_CS = destval2; break; case 6: /* push word ptr ... */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; destval = fetch_data_long(destoffset); TRACE_AND_STEP(); push_long(destval); } else { u16 destval; destval = fetch_data_word(destoffset); TRACE_AND_STEP(); push_word(destval); } break; } break; case 3: switch (rh) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = inc_long(*destreg); } else { u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = inc_word(*destreg); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = dec_long(*destreg); } else { u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = dec_word(*destreg); } break; case 2: /* call word ptr ... */ destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); push_word(M.x86.R_IP); M.x86.R_IP = *destreg; break; case 3: /* jmp far ptr ... */ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); TRACE_AND_STEP(); HALT_SYS(); break; case 4: /* jmp ... */ destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); M.x86.R_IP = (u16) (*destreg); break; case 5: /* jmp far ptr ... */ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); TRACE_AND_STEP(); HALT_SYS(); break; case 6: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); push_long(*destreg); } else { u16 *destreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); push_word(*destreg); } break; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /*************************************************************************** * Single byte operation code table: **************************************************************************/ void (*x86emu_optab[256])(u8) = { /* 0x00 */ x86emuOp_add_byte_RM_R, /* 0x01 */ x86emuOp_add_word_RM_R, /* 0x02 */ x86emuOp_add_byte_R_RM, /* 0x03 */ x86emuOp_add_word_R_RM, /* 0x04 */ x86emuOp_add_byte_AL_IMM, /* 0x05 */ x86emuOp_add_word_AX_IMM, /* 0x06 */ x86emuOp_push_ES, /* 0x07 */ x86emuOp_pop_ES, /* 0x08 */ x86emuOp_or_byte_RM_R, /* 0x09 */ x86emuOp_or_word_RM_R, /* 0x0a */ x86emuOp_or_byte_R_RM, /* 0x0b */ x86emuOp_or_word_R_RM, /* 0x0c */ x86emuOp_or_byte_AL_IMM, /* 0x0d */ x86emuOp_or_word_AX_IMM, /* 0x0e */ x86emuOp_push_CS, /* 0x0f */ x86emuOp_two_byte, /* 0x10 */ x86emuOp_adc_byte_RM_R, /* 0x11 */ x86emuOp_adc_word_RM_R, /* 0x12 */ x86emuOp_adc_byte_R_RM, /* 0x13 */ x86emuOp_adc_word_R_RM, /* 0x14 */ x86emuOp_adc_byte_AL_IMM, /* 0x15 */ x86emuOp_adc_word_AX_IMM, /* 0x16 */ x86emuOp_push_SS, /* 0x17 */ x86emuOp_pop_SS, /* 0x18 */ x86emuOp_sbb_byte_RM_R, /* 0x19 */ x86emuOp_sbb_word_RM_R, /* 0x1a */ x86emuOp_sbb_byte_R_RM, /* 0x1b */ x86emuOp_sbb_word_R_RM, /* 0x1c */ x86emuOp_sbb_byte_AL_IMM, /* 0x1d */ x86emuOp_sbb_word_AX_IMM, /* 0x1e */ x86emuOp_push_DS, /* 0x1f */ x86emuOp_pop_DS, /* 0x20 */ x86emuOp_and_byte_RM_R, /* 0x21 */ x86emuOp_and_word_RM_R, /* 0x22 */ x86emuOp_and_byte_R_RM, /* 0x23 */ x86emuOp_and_word_R_RM, /* 0x24 */ x86emuOp_and_byte_AL_IMM, /* 0x25 */ x86emuOp_and_word_AX_IMM, /* 0x26 */ x86emuOp_segovr_ES, /* 0x27 */ x86emuOp_daa, /* 0x28 */ x86emuOp_sub_byte_RM_R, /* 0x29 */ x86emuOp_sub_word_RM_R, /* 0x2a */ x86emuOp_sub_byte_R_RM, /* 0x2b */ x86emuOp_sub_word_R_RM, /* 0x2c */ x86emuOp_sub_byte_AL_IMM, /* 0x2d */ x86emuOp_sub_word_AX_IMM, /* 0x2e */ x86emuOp_segovr_CS, /* 0x2f */ x86emuOp_das, /* 0x30 */ x86emuOp_xor_byte_RM_R, /* 0x31 */ x86emuOp_xor_word_RM_R, /* 0x32 */ x86emuOp_xor_byte_R_RM, /* 0x33 */ x86emuOp_xor_word_R_RM, /* 0x34 */ x86emuOp_xor_byte_AL_IMM, /* 0x35 */ x86emuOp_xor_word_AX_IMM, /* 0x36 */ x86emuOp_segovr_SS, /* 0x37 */ x86emuOp_aaa, /* 0x38 */ x86emuOp_cmp_byte_RM_R, /* 0x39 */ x86emuOp_cmp_word_RM_R, /* 0x3a */ x86emuOp_cmp_byte_R_RM, /* 0x3b */ x86emuOp_cmp_word_R_RM, /* 0x3c */ x86emuOp_cmp_byte_AL_IMM, /* 0x3d */ x86emuOp_cmp_word_AX_IMM, /* 0x3e */ x86emuOp_segovr_DS, /* 0x3f */ x86emuOp_aas, /* 0x40 */ x86emuOp_inc_AX, /* 0x41 */ x86emuOp_inc_CX, /* 0x42 */ x86emuOp_inc_DX, /* 0x43 */ x86emuOp_inc_BX, /* 0x44 */ x86emuOp_inc_SP, /* 0x45 */ x86emuOp_inc_BP, /* 0x46 */ x86emuOp_inc_SI, /* 0x47 */ x86emuOp_inc_DI, /* 0x48 */ x86emuOp_dec_AX, /* 0x49 */ x86emuOp_dec_CX, /* 0x4a */ x86emuOp_dec_DX, /* 0x4b */ x86emuOp_dec_BX, /* 0x4c */ x86emuOp_dec_SP, /* 0x4d */ x86emuOp_dec_BP, /* 0x4e */ x86emuOp_dec_SI, /* 0x4f */ x86emuOp_dec_DI, /* 0x50 */ x86emuOp_push_AX, /* 0x51 */ x86emuOp_push_CX, /* 0x52 */ x86emuOp_push_DX, /* 0x53 */ x86emuOp_push_BX, /* 0x54 */ x86emuOp_push_SP, /* 0x55 */ x86emuOp_push_BP, /* 0x56 */ x86emuOp_push_SI, /* 0x57 */ x86emuOp_push_DI, /* 0x58 */ x86emuOp_pop_AX, /* 0x59 */ x86emuOp_pop_CX, /* 0x5a */ x86emuOp_pop_DX, /* 0x5b */ x86emuOp_pop_BX, /* 0x5c */ x86emuOp_pop_SP, /* 0x5d */ x86emuOp_pop_BP, /* 0x5e */ x86emuOp_pop_SI, /* 0x5f */ x86emuOp_pop_DI, /* 0x60 */ x86emuOp_push_all, /* 0x61 */ x86emuOp_pop_all, /* 0x62 */ x86emuOp_illegal_op, /* bound */ /* 0x63 */ x86emuOp_illegal_op, /* arpl */ /* 0x64 */ x86emuOp_segovr_FS, /* 0x65 */ x86emuOp_segovr_GS, /* 0x66 */ x86emuOp_prefix_data, /* 0x67 */ x86emuOp_prefix_addr, /* 0x68 */ x86emuOp_push_word_IMM, /* 0x69 */ x86emuOp_imul_word_IMM, /* 0x6a */ x86emuOp_push_byte_IMM, /* 0x6b */ x86emuOp_imul_byte_IMM, /* 0x6c */ x86emuOp_ins_byte, /* 0x6d */ x86emuOp_ins_word, /* 0x6e */ x86emuOp_outs_byte, /* 0x6f */ x86emuOp_outs_word, /* 0x70 */ x86emuOp_jump_near_O, /* 0x71 */ x86emuOp_jump_near_NO, /* 0x72 */ x86emuOp_jump_near_B, /* 0x73 */ x86emuOp_jump_near_NB, /* 0x74 */ x86emuOp_jump_near_Z, /* 0x75 */ x86emuOp_jump_near_NZ, /* 0x76 */ x86emuOp_jump_near_BE, /* 0x77 */ x86emuOp_jump_near_NBE, /* 0x78 */ x86emuOp_jump_near_S, /* 0x79 */ x86emuOp_jump_near_NS, /* 0x7a */ x86emuOp_jump_near_P, /* 0x7b */ x86emuOp_jump_near_NP, /* 0x7c */ x86emuOp_jump_near_L, /* 0x7d */ x86emuOp_jump_near_NL, /* 0x7e */ x86emuOp_jump_near_LE, /* 0x7f */ x86emuOp_jump_near_NLE, /* 0x80 */ x86emuOp_opc80_byte_RM_IMM, /* 0x81 */ x86emuOp_opc81_word_RM_IMM, /* 0x82 */ x86emuOp_opc82_byte_RM_IMM, /* 0x83 */ x86emuOp_opc83_word_RM_IMM, /* 0x84 */ x86emuOp_test_byte_RM_R, /* 0x85 */ x86emuOp_test_word_RM_R, /* 0x86 */ x86emuOp_xchg_byte_RM_R, /* 0x87 */ x86emuOp_xchg_word_RM_R, /* 0x88 */ x86emuOp_mov_byte_RM_R, /* 0x89 */ x86emuOp_mov_word_RM_R, /* 0x8a */ x86emuOp_mov_byte_R_RM, /* 0x8b */ x86emuOp_mov_word_R_RM, /* 0x8c */ x86emuOp_mov_word_RM_SR, /* 0x8d */ x86emuOp_lea_word_R_M, /* 0x8e */ x86emuOp_mov_word_SR_RM, /* 0x8f */ x86emuOp_pop_RM, /* 0x90 */ x86emuOp_nop, /* 0x91 */ x86emuOp_xchg_word_AX_CX, /* 0x92 */ x86emuOp_xchg_word_AX_DX, /* 0x93 */ x86emuOp_xchg_word_AX_BX, /* 0x94 */ x86emuOp_xchg_word_AX_SP, /* 0x95 */ x86emuOp_xchg_word_AX_BP, /* 0x96 */ x86emuOp_xchg_word_AX_SI, /* 0x97 */ x86emuOp_xchg_word_AX_DI, /* 0x98 */ x86emuOp_cbw, /* 0x99 */ x86emuOp_cwd, /* 0x9a */ x86emuOp_call_far_IMM, /* 0x9b */ x86emuOp_wait, /* 0x9c */ x86emuOp_pushf_word, /* 0x9d */ x86emuOp_popf_word, /* 0x9e */ x86emuOp_sahf, /* 0x9f */ x86emuOp_lahf, /* 0xa0 */ x86emuOp_mov_AL_M_IMM, /* 0xa1 */ x86emuOp_mov_AX_M_IMM, /* 0xa2 */ x86emuOp_mov_M_AL_IMM, /* 0xa3 */ x86emuOp_mov_M_AX_IMM, /* 0xa4 */ x86emuOp_movs_byte, /* 0xa5 */ x86emuOp_movs_word, /* 0xa6 */ x86emuOp_cmps_byte, /* 0xa7 */ x86emuOp_cmps_word, /* 0xa8 */ x86emuOp_test_AL_IMM, /* 0xa9 */ x86emuOp_test_AX_IMM, /* 0xaa */ x86emuOp_stos_byte, /* 0xab */ x86emuOp_stos_word, /* 0xac */ x86emuOp_lods_byte, /* 0xad */ x86emuOp_lods_word, /* 0xac */ x86emuOp_scas_byte, /* 0xad */ x86emuOp_scas_word, /* 0xb0 */ x86emuOp_mov_byte_AL_IMM, /* 0xb1 */ x86emuOp_mov_byte_CL_IMM, /* 0xb2 */ x86emuOp_mov_byte_DL_IMM, /* 0xb3 */ x86emuOp_mov_byte_BL_IMM, /* 0xb4 */ x86emuOp_mov_byte_AH_IMM, /* 0xb5 */ x86emuOp_mov_byte_CH_IMM, /* 0xb6 */ x86emuOp_mov_byte_DH_IMM, /* 0xb7 */ x86emuOp_mov_byte_BH_IMM, /* 0xb8 */ x86emuOp_mov_word_AX_IMM, /* 0xb9 */ x86emuOp_mov_word_CX_IMM, /* 0xba */ x86emuOp_mov_word_DX_IMM, /* 0xbb */ x86emuOp_mov_word_BX_IMM, /* 0xbc */ x86emuOp_mov_word_SP_IMM, /* 0xbd */ x86emuOp_mov_word_BP_IMM, /* 0xbe */ x86emuOp_mov_word_SI_IMM, /* 0xbf */ x86emuOp_mov_word_DI_IMM, /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM, /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM, /* 0xc2 */ x86emuOp_ret_near_IMM, /* 0xc3 */ x86emuOp_ret_near, /* 0xc4 */ x86emuOp_les_R_IMM, /* 0xc5 */ x86emuOp_lds_R_IMM, /* 0xc6 */ x86emuOp_mov_byte_RM_IMM, /* 0xc7 */ x86emuOp_mov_word_RM_IMM, /* 0xc8 */ x86emuOp_enter, /* 0xc9 */ x86emuOp_leave, /* 0xca */ x86emuOp_ret_far_IMM, /* 0xcb */ x86emuOp_ret_far, /* 0xcc */ x86emuOp_int3, /* 0xcd */ x86emuOp_int_IMM, /* 0xce */ x86emuOp_into, /* 0xcf */ x86emuOp_iret, /* 0xd0 */ x86emuOp_opcD0_byte_RM_1, /* 0xd1 */ x86emuOp_opcD1_word_RM_1, /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL, /* 0xd3 */ x86emuOp_opcD3_word_RM_CL, /* 0xd4 */ x86emuOp_aam, /* 0xd5 */ x86emuOp_aad, /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */ /* 0xd7 */ x86emuOp_xlat, /* 0xd8 */ x86emuOp_esc_coprocess_d8, /* 0xd9 */ x86emuOp_esc_coprocess_d9, /* 0xda */ x86emuOp_esc_coprocess_da, /* 0xdb */ x86emuOp_esc_coprocess_db, /* 0xdc */ x86emuOp_esc_coprocess_dc, /* 0xdd */ x86emuOp_esc_coprocess_dd, /* 0xde */ x86emuOp_esc_coprocess_de, /* 0xdf */ x86emuOp_esc_coprocess_df, /* 0xe0 */ x86emuOp_loopne, /* 0xe1 */ x86emuOp_loope, /* 0xe2 */ x86emuOp_loop, /* 0xe3 */ x86emuOp_jcxz, /* 0xe4 */ x86emuOp_in_byte_AL_IMM, /* 0xe5 */ x86emuOp_in_word_AX_IMM, /* 0xe6 */ x86emuOp_out_byte_IMM_AL, /* 0xe7 */ x86emuOp_out_word_IMM_AX, /* 0xe8 */ x86emuOp_call_near_IMM, /* 0xe9 */ x86emuOp_jump_near_IMM, /* 0xea */ x86emuOp_jump_far_IMM, /* 0xeb */ x86emuOp_jump_byte_IMM, /* 0xec */ x86emuOp_in_byte_AL_DX, /* 0xed */ x86emuOp_in_word_AX_DX, /* 0xee */ x86emuOp_out_byte_DX_AL, /* 0xef */ x86emuOp_out_word_DX_AX, /* 0xf0 */ x86emuOp_lock, /* 0xf1 */ x86emuOp_illegal_op, /* 0xf2 */ x86emuOp_repne, /* 0xf3 */ x86emuOp_repe, /* 0xf4 */ x86emuOp_halt, /* 0xf5 */ x86emuOp_cmc, /* 0xf6 */ x86emuOp_opcF6_byte_RM, /* 0xf7 */ x86emuOp_opcF7_word_RM, /* 0xf8 */ x86emuOp_clc, /* 0xf9 */ x86emuOp_stc, /* 0xfa */ x86emuOp_cli, /* 0xfb */ x86emuOp_sti, /* 0xfc */ x86emuOp_cld, /* 0xfd */ x86emuOp_std, /* 0xfe */ x86emuOp_opcFE_byte_RM, /* 0xff */ x86emuOp_opcFF_word_RM, }; v86d-0.1.10/libs/x86emu/ops2.c000066400000000000000000002555171153201731300155070ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file includes subroutines to implement the decoding * and emulation of all the x86 extended two-byte processor * instructions. * ****************************************************************************/ #include "x86emu/x86emui.h" #undef bswap_32 #define bswap_32(x) (((x & 0xff000000) >> 24) | \ ((x & 0x00ff0000) >> 8) | \ ((x & 0x0000ff00) << 8) | \ ((x & 0x000000ff) << 24)) /*----------------------------- Implementation ----------------------------*/ /**************************************************************************** PARAMETERS: op1 - Instruction op code REMARKS: Handles illegal opcodes. ****************************************************************************/ static void x86emuOp2_illegal_op( u8 op2) { int mod, rl, rh; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X /%d ILLEGAL EXTENDED X86 OPCODE! (mod=%d rl=%d)\n", M.x86.R_CS, M.x86.R_IP-2,op2, rh, mod, rl); HALT_SYS(); END_OF_INSTR(); } #define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) /**************************************************************************** REMARKS: Handles opcode 0x0f,0x01 ****************************************************************************/ static void x86emuOp2_group_g(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; u16 *destreg; uint destoffset; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); switch (rh) { case 4: // SMSW (Store Machine Status Word) // Decode the mod byte to find the addressing // Always returns 0x10 (initial value as per intel manual volume 3, figure 8-1 switch (mod) { case 0: destoffset = decode_rm00_address(rl); store_data_word(destoffset, 0x10); break; case 1: destoffset = decode_rm01_address(rl); store_data_word(destoffset, 0x10); break; case 2: destoffset = decode_rm10_address(rl); store_data_word(destoffset, 0x10); break; case 3: destreg = DECODE_RM_WORD_REGISTER(rl); *destreg = 0x10; break; } break; default: DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE IN 0F 01\n"); TRACE_REGS(); printk("%04x:%04x: 0F %02X /%d ILLEGAL EXTENDED X86 OPCODE! (mod=%d rl=%d)\n", M.x86.R_CS, M.x86.R_IP-2,op2, rh, mod, rl); HALT_SYS(); break; } END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0x31 ****************************************************************************/ static void x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2)) { #ifdef __HAS_LONG_LONG__ static u64 counter = 0; #else static u32 counter = 0; #endif counter += 0x10000; /* read timestamp counter */ /* * Note that instead of actually trying to accurately measure this, we just * increase the counter by a fixed amount every time we hit one of these * instructions. Feel free to come up with a better method. */ START_OF_INSTR(); DECODE_PRINTF("RDTSC\n"); TRACE_AND_STEP(); #ifdef __HAS_LONG_LONG__ M.x86.R_EAX = counter & 0xffffffff; M.x86.R_EDX = counter >> 32; #else M.x86.R_EAX = counter; M.x86.R_EDX = 0; #endif DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0x80-0x8F ****************************************************************************/ static void x86emuOp2_long_jump(u8 op2) { s32 target; char *name = 0; int cond = 0; /* conditional jump to word offset. */ START_OF_INSTR(); switch (op2) { case 0x80: name = "JO\t"; cond = ACCESS_FLAG(F_OF); break; case 0x81: name = "JNO\t"; cond = !ACCESS_FLAG(F_OF); break; case 0x82: name = "JB\t"; cond = ACCESS_FLAG(F_CF); break; case 0x83: name = "JNB\t"; cond = !ACCESS_FLAG(F_CF); break; case 0x84: name = "JZ\t"; cond = ACCESS_FLAG(F_ZF); break; case 0x85: name = "JNZ\t"; cond = !ACCESS_FLAG(F_ZF); break; case 0x86: name = "JBE\t"; cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); break; case 0x87: name = "JNBE\t"; cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); break; case 0x88: name = "JS\t"; cond = ACCESS_FLAG(F_SF); break; case 0x89: name = "JNS\t"; cond = !ACCESS_FLAG(F_SF); break; case 0x8a: name = "JP\t"; cond = ACCESS_FLAG(F_PF); break; case 0x8b: name = "JNP\t"; cond = !ACCESS_FLAG(F_PF); break; case 0x8c: name = "JL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x8d: name = "JNL\t"; cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); break; case 0x8e: name = "JLE\t"; cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; case 0x8f: name = "JNLE\t"; cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; } DECODE_PRINTF(name); (void)name; target = (s16) fetch_word_imm(); target += (s16) M.x86.R_IP; DECODE_PRINTF2("%04x\n", target); TRACE_AND_STEP(); if (cond) M.x86.R_IP = (u16)target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0x90-0x9F ****************************************************************************/ static void x86emuOp2_set_byte(u8 op2) { int mod, rl, rh; uint destoffset; u8 *destreg; char *name = 0; int cond = 0; START_OF_INSTR(); switch (op2) { case 0x90: name = "SETO\t"; cond = ACCESS_FLAG(F_OF); break; case 0x91: name = "SETNO\t"; cond = !ACCESS_FLAG(F_OF); break; case 0x92: name = "SETB\t"; cond = ACCESS_FLAG(F_CF); break; case 0x93: name = "SETNB\t"; cond = !ACCESS_FLAG(F_CF); break; case 0x94: name = "SETZ\t"; cond = ACCESS_FLAG(F_ZF); break; case 0x95: name = "SETNZ\t"; cond = !ACCESS_FLAG(F_ZF); break; case 0x96: name = "SETBE\t"; cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); break; case 0x97: name = "SETNBE\t"; cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); break; case 0x98: name = "SETS\t"; cond = ACCESS_FLAG(F_SF); break; case 0x99: name = "SETNS\t"; cond = !ACCESS_FLAG(F_SF); break; case 0x9a: name = "SETP\t"; cond = ACCESS_FLAG(F_PF); break; case 0x9b: name = "SETNP\t"; cond = !ACCESS_FLAG(F_PF); break; case 0x9c: name = "SETL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x9d: name = "SETNL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x9e: name = "SETLE\t"; cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; case 0x9f: name = "SETNLE\t"; cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; } DECODE_PRINTF(name); (void)name; FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); TRACE_AND_STEP(); store_data_byte(destoffset, cond ? 0x01 : 0x00); break; case 1: destoffset = decode_rm01_address(rl); TRACE_AND_STEP(); store_data_byte(destoffset, cond ? 0x01 : 0x00); break; case 2: destoffset = decode_rm10_address(rl); TRACE_AND_STEP(); store_data_byte(destoffset, cond ? 0x01 : 0x00); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); TRACE_AND_STEP(); *destreg = cond ? 0x01 : 0x00; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa0 ****************************************************************************/ static void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2)) { START_OF_INSTR(); DECODE_PRINTF("PUSH\tFS\n"); TRACE_AND_STEP(); push_word(M.x86.R_FS); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa1 ****************************************************************************/ static void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2)) { START_OF_INSTR(); DECODE_PRINTF("POP\tFS\n"); TRACE_AND_STEP(); M.x86.R_FS = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output Handles opcode 0x0f,0xa2 ****************************************************************************/ static void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2)) { START_OF_INSTR(); DECODE_PRINTF("CPUID\n"); TRACE_AND_STEP(); cpuid(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa3 ****************************************************************************/ static void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; int bit,disp; START_OF_INSTR(); DECODE_PRINTF("BT\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval; u32 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } else { u16 srcval; u16 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval; u32 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } else { u16 srcval; u16 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval; u32 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } else { u16 srcval; u16 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg,*shiftreg; srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF); } else { u16 *srcreg,*shiftreg; srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa4 ****************************************************************************/ static void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint destoffset; u8 shift; START_OF_INSTR(); DECODE_PRINTF("SHLD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*shiftreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); *destreg = shld_long(*destreg,*shiftreg,shift); } else { u16 *destreg,*shiftreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); *destreg = shld_word(*destreg,*shiftreg,shift); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa5 ****************************************************************************/ static void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("SHLD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,M.x86.R_CL); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,M.x86.R_CL); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,M.x86.R_CL); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,M.x86.R_CL); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,M.x86.R_CL); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,M.x86.R_CL); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*shiftreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL); } else { u16 *destreg,*shiftreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa8 ****************************************************************************/ static void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2)) { START_OF_INSTR(); DECODE_PRINTF("PUSH\tGS\n"); TRACE_AND_STEP(); push_word(M.x86.R_GS); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xa9 ****************************************************************************/ static void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2)) { START_OF_INSTR(); DECODE_PRINTF("POP\tGS\n"); TRACE_AND_STEP(); M.x86.R_GS = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xab ****************************************************************************/ static void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; int bit,disp; START_OF_INSTR(); DECODE_PRINTF("BTS\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval | mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, srcval | mask); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval | mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, srcval | mask); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval | mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, srcval | mask); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg,*shiftreg; u32 mask; srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; mask = (0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); *srcreg |= mask; } else { u16 *srcreg,*shiftreg; u16 mask; srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); *srcreg |= mask; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xac ****************************************************************************/ static void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint destoffset; u8 shift; START_OF_INSTR(); DECODE_PRINTF("SHLD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shrd_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shrd_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shrd_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shrd_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shrd_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shrd_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*shiftreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); *destreg = shrd_long(*destreg,*shiftreg,shift); } else { u16 *destreg,*shiftreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); *destreg = shrd_word(*destreg,*shiftreg,shift); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xad ****************************************************************************/ static void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("SHLD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shrd_long(destval,*shiftreg,M.x86.R_CL); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shrd_word(destval,*shiftreg,M.x86.R_CL); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shrd_long(destval,*shiftreg,M.x86.R_CL); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shrd_word(destval,*shiftreg,M.x86.R_CL); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shrd_long(destval,*shiftreg,M.x86.R_CL); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shrd_word(destval,*shiftreg,M.x86.R_CL); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*shiftreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL); } else { u16 *destreg,*shiftreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(",CL\n"); TRACE_AND_STEP(); *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xaf ****************************************************************************/ static void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("IMUL\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); TRACE_AND_STEP(); res = (s16)*destreg * (s16)srcval; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); TRACE_AND_STEP(); res = (s16)*destreg * (s16)srcval; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg; u16 srcval; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); TRACE_AND_STEP(); res = (s16)*destreg * (s16)srcval; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; u32 res_lo,res_hi; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); TRACE_AND_STEP(); imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg); if (res_hi != 0) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u32)res_lo; } else { u16 *destreg,*srcreg; u32 res; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); res = (s16)*destreg * (s16)*srcreg; if (res > 0xFFFF) { SET_FLAG(F_CF); SET_FLAG(F_OF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } *destreg = (u16)res; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xb2 ****************************************************************************/ static void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2)) { int mod, rh, rl; u16 *dstreg; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("LSS\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_SS = fetch_data_word(srcoffset + 2); break; case 1: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_SS = fetch_data_word(srcoffset + 2); break; case 2: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_SS = fetch_data_word(srcoffset + 2); break; case 3: /* register to register */ /* UNDEFINED! */ TRACE_AND_STEP(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xb3 ****************************************************************************/ static void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; int bit,disp; START_OF_INSTR(); DECODE_PRINTF("BTR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval & ~mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, (u16)(srcval & ~mask)); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval & ~mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, (u16)(srcval & ~mask)); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval & ~mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, (u16)(srcval & ~mask)); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg,*shiftreg; u32 mask; srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; mask = (0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); *srcreg &= ~mask; } else { u16 *srcreg,*shiftreg; u16 mask; srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); *srcreg &= ~mask; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xb4 ****************************************************************************/ static void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2)) { int mod, rh, rl; u16 *dstreg; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("LFS\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_FS = fetch_data_word(srcoffset + 2); break; case 1: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_FS = fetch_data_word(srcoffset + 2); break; case 2: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_FS = fetch_data_word(srcoffset + 2); break; case 3: /* register to register */ /* UNDEFINED! */ TRACE_AND_STEP(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xb5 ****************************************************************************/ static void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2)) { int mod, rh, rl; u16 *dstreg; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("LGS\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_GS = fetch_data_word(srcoffset + 2); break; case 1: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_GS = fetch_data_word(srcoffset + 2); break; case 2: dstreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *dstreg = fetch_data_word(srcoffset); M.x86.R_GS = fetch_data_word(srcoffset + 2); break; case 3: /* register to register */ /* UNDEFINED! */ TRACE_AND_STEP(); } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xb6 ****************************************************************************/ static void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("MOVZX\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u8 *srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; } else { u16 *destreg; u8 *srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xb7 ****************************************************************************/ static void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; u32 *destreg; u32 srcval; u16 *srcreg; START_OF_INSTR(); DECODE_PRINTF("MOVZX\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 1: destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 2: destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 3: /* register to register */ destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = *srcreg; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xba ****************************************************************************/ static void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; int bit; START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); switch (rh) { case 4: DECODE_PRINTF("BT\t"); break; case 5: DECODE_PRINTF("BTS\t"); break; case 6: DECODE_PRINTF("BTR\t"); break; case 7: DECODE_PRINTF("BTC\t"); break; default: DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n", M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl); HALT_SYS(); } switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, mask; u8 shift; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0x1F; srcval = fetch_data_long(srcoffset); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); switch (rh) { case 5: store_data_long(srcoffset, srcval | mask); break; case 6: store_data_long(srcoffset, srcval & ~mask); break; case 7: store_data_long(srcoffset, srcval ^ mask); break; default: break; } } else { u16 srcval, mask; u8 shift; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0xF; srcval = fetch_data_word(srcoffset); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); switch (rh) { case 5: store_data_word(srcoffset, srcval | mask); break; case 6: store_data_word(srcoffset, srcval & ~mask); break; case 7: store_data_word(srcoffset, srcval ^ mask); break; default: break; } } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, mask; u8 shift; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0x1F; srcval = fetch_data_long(srcoffset); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); switch (rh) { case 5: store_data_long(srcoffset, srcval | mask); break; case 6: store_data_long(srcoffset, srcval & ~mask); break; case 7: store_data_long(srcoffset, srcval ^ mask); break; default: break; } } else { u16 srcval, mask; u8 shift; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0xF; srcval = fetch_data_word(srcoffset); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); switch (rh) { case 5: store_data_word(srcoffset, srcval | mask); break; case 6: store_data_word(srcoffset, srcval & ~mask); break; case 7: store_data_word(srcoffset, srcval ^ mask); break; default: break; } } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, mask; u8 shift; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0x1F; srcval = fetch_data_long(srcoffset); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); switch (rh) { case 5: store_data_long(srcoffset, srcval | mask); break; case 6: store_data_long(srcoffset, srcval & ~mask); break; case 7: store_data_long(srcoffset, srcval ^ mask); break; default: break; } } else { u16 srcval, mask; u8 shift; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0xF; srcval = fetch_data_word(srcoffset); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); switch (rh) { case 5: store_data_word(srcoffset, srcval | mask); break; case 6: store_data_word(srcoffset, srcval & ~mask); break; case 7: store_data_word(srcoffset, srcval ^ mask); break; default: break; } } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg; u32 mask; u8 shift; srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0x1F; mask = (0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); switch (rh) { case 5: *srcreg |= mask; break; case 6: *srcreg &= ~mask; break; case 7: *srcreg ^= mask; break; default: break; } } else { u16 *srcreg; u16 mask; u8 shift; srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shift = fetch_byte_imm(); TRACE_AND_STEP(); bit = shift & 0xF; mask = (0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); switch (rh) { case 5: *srcreg |= mask; break; case 6: *srcreg &= ~mask; break; case 7: *srcreg ^= mask; break; default: break; } } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xbb ****************************************************************************/ static void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; int bit,disp; START_OF_INSTR(); DECODE_PRINTF("BTC\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval ^ mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, (u16)(srcval ^ mask)); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval ^ mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, (u16)(srcval ^ mask)); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval,mask; u32 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); mask = (0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_long(srcoffset+disp, srcval ^ mask); } else { u16 srcval,mask; u16 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(srcval & mask,F_CF); store_data_word(srcoffset+disp, (u16)(srcval ^ mask)); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg,*shiftreg; u32 mask; srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; mask = (0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); *srcreg ^= mask; } else { u16 *srcreg,*shiftreg; u16 mask; srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; mask = (u16)(0x1 << bit); CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); *srcreg ^= mask; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xbc ****************************************************************************/ static void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("BSF\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch(mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_long(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 32; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_word(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 16; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_long(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 32; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_word(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 16; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_long(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 32; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_word(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 16; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcval = *DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 32; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcval = *DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 16; (*dstreg)++) if ((srcval >> *dstreg) & 1) break; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xbd ****************************************************************************/ static void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("BSR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch(mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_long(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 31; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_word(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 15; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_long(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 31; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_word(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 15; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_long(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 31; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); srcval = fetch_data_word(srcoffset); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 15; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval, *dstreg; srcval = *DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 31; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } else { u16 srcval, *dstreg; srcval = *DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 15; *dstreg > 0; (*dstreg)--) if ((srcval >> *dstreg) & 1) break; } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xbe ****************************************************************************/ static void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("MOVSX\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = (s32)((s8)fetch_data_byte(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = (s16)((s8)fetch_data_byte(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = (s32)((s8)fetch_data_byte(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = (s16)((s8)fetch_data_byte(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = (s32)((s8)fetch_data_byte(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = (s16)((s8)fetch_data_byte(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u8 *srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = (s32)((s8)*srcreg); } else { u16 *destreg; u8 *srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = (s16)((s8)*srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /**************************************************************************** REMARKS: Handles opcode 0x0f,0xbf ****************************************************************************/ static void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2)) { int mod, rl, rh; uint srcoffset; u32 *destreg; u32 srcval; u16 *srcreg; START_OF_INSTR(); DECODE_PRINTF("MOVSX\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = (s32)((s16)fetch_data_word(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 1: destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = (s32)((s16)fetch_data_word(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 2: destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = (s32)((s16)fetch_data_word(srcoffset)); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = srcval; break; case 3: /* register to register */ destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = (s32)((s16)*srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /* Handles opcodes 0xc8-0xcf */ static void x86emuOp2_bswap(u8 X86EMU_UNUSED(op2)) { START_OF_INSTR(); DECODE_PRINTF("BSWAP\n"); TRACE_AND_STEP(); switch (op2) { case 0xc8: M.x86.R_EAX = bswap_32(M.x86.R_EAX); break; case 0xc9: M.x86.R_ECX = bswap_32(M.x86.R_ECX); break; case 0xca: M.x86.R_EDX = bswap_32(M.x86.R_EDX); break; case 0xcb: M.x86.R_EBX = bswap_32(M.x86.R_EBX); break; case 0xcc: M.x86.R_ESP = bswap_32(M.x86.R_ESP); break; case 0xcd: M.x86.R_EBP = bswap_32(M.x86.R_EBP); break; case 0xce: M.x86.R_ESI = bswap_32(M.x86.R_ESI); break; case 0xcf: M.x86.R_EDI = bswap_32(M.x86.R_EDI); break; default: /* can't happen */ break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } /*************************************************************************** * Double byte operation code table: **************************************************************************/ void (*x86emu_optab2[256])(u8) = { /* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */ /* 0x01 */ x86emuOp2_group_g, /* Group G (ring 0 PM) */ /* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */ /* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */ /* 0x04 */ x86emuOp2_illegal_op, /* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */ /* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */ /* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */ /* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */ /* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */ /* 0x0a */ x86emuOp2_illegal_op, /* 0x0b */ x86emuOp2_illegal_op, /* 0x0c */ x86emuOp2_illegal_op, /* 0x0d */ x86emuOp2_illegal_op, /* 0x0e */ x86emuOp2_illegal_op, /* 0x0f */ x86emuOp2_illegal_op, /* 0x10 */ x86emuOp2_illegal_op, /* 0x11 */ x86emuOp2_illegal_op, /* 0x12 */ x86emuOp2_illegal_op, /* 0x13 */ x86emuOp2_illegal_op, /* 0x14 */ x86emuOp2_illegal_op, /* 0x15 */ x86emuOp2_illegal_op, /* 0x16 */ x86emuOp2_illegal_op, /* 0x17 */ x86emuOp2_illegal_op, /* 0x18 */ x86emuOp2_illegal_op, /* 0x19 */ x86emuOp2_illegal_op, /* 0x1a */ x86emuOp2_illegal_op, /* 0x1b */ x86emuOp2_illegal_op, /* 0x1c */ x86emuOp2_illegal_op, /* 0x1d */ x86emuOp2_illegal_op, /* 0x1e */ x86emuOp2_illegal_op, /* 0x1f */ x86emuOp2_illegal_op, /* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */ /* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */ /* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */ /* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */ /* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */ /* 0x25 */ x86emuOp2_illegal_op, /* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */ /* 0x27 */ x86emuOp2_illegal_op, /* 0x28 */ x86emuOp2_illegal_op, /* 0x29 */ x86emuOp2_illegal_op, /* 0x2a */ x86emuOp2_illegal_op, /* 0x2b */ x86emuOp2_illegal_op, /* 0x2c */ x86emuOp2_illegal_op, /* 0x2d */ x86emuOp2_illegal_op, /* 0x2e */ x86emuOp2_illegal_op, /* 0x2f */ x86emuOp2_illegal_op, /* 0x30 */ x86emuOp2_illegal_op, /* 0x31 */ x86emuOp2_rdtsc, /* 0x32 */ x86emuOp2_illegal_op, /* 0x33 */ x86emuOp2_illegal_op, /* 0x34 */ x86emuOp2_illegal_op, /* 0x35 */ x86emuOp2_illegal_op, /* 0x36 */ x86emuOp2_illegal_op, /* 0x37 */ x86emuOp2_illegal_op, /* 0x38 */ x86emuOp2_illegal_op, /* 0x39 */ x86emuOp2_illegal_op, /* 0x3a */ x86emuOp2_illegal_op, /* 0x3b */ x86emuOp2_illegal_op, /* 0x3c */ x86emuOp2_illegal_op, /* 0x3d */ x86emuOp2_illegal_op, /* 0x3e */ x86emuOp2_illegal_op, /* 0x3f */ x86emuOp2_illegal_op, /* 0x40 */ x86emuOp2_illegal_op, /* 0x41 */ x86emuOp2_illegal_op, /* 0x42 */ x86emuOp2_illegal_op, /* 0x43 */ x86emuOp2_illegal_op, /* 0x44 */ x86emuOp2_illegal_op, /* 0x45 */ x86emuOp2_illegal_op, /* 0x46 */ x86emuOp2_illegal_op, /* 0x47 */ x86emuOp2_illegal_op, /* 0x48 */ x86emuOp2_illegal_op, /* 0x49 */ x86emuOp2_illegal_op, /* 0x4a */ x86emuOp2_illegal_op, /* 0x4b */ x86emuOp2_illegal_op, /* 0x4c */ x86emuOp2_illegal_op, /* 0x4d */ x86emuOp2_illegal_op, /* 0x4e */ x86emuOp2_illegal_op, /* 0x4f */ x86emuOp2_illegal_op, /* 0x50 */ x86emuOp2_illegal_op, /* 0x51 */ x86emuOp2_illegal_op, /* 0x52 */ x86emuOp2_illegal_op, /* 0x53 */ x86emuOp2_illegal_op, /* 0x54 */ x86emuOp2_illegal_op, /* 0x55 */ x86emuOp2_illegal_op, /* 0x56 */ x86emuOp2_illegal_op, /* 0x57 */ x86emuOp2_illegal_op, /* 0x58 */ x86emuOp2_illegal_op, /* 0x59 */ x86emuOp2_illegal_op, /* 0x5a */ x86emuOp2_illegal_op, /* 0x5b */ x86emuOp2_illegal_op, /* 0x5c */ x86emuOp2_illegal_op, /* 0x5d */ x86emuOp2_illegal_op, /* 0x5e */ x86emuOp2_illegal_op, /* 0x5f */ x86emuOp2_illegal_op, /* 0x60 */ x86emuOp2_illegal_op, /* 0x61 */ x86emuOp2_illegal_op, /* 0x62 */ x86emuOp2_illegal_op, /* 0x63 */ x86emuOp2_illegal_op, /* 0x64 */ x86emuOp2_illegal_op, /* 0x65 */ x86emuOp2_illegal_op, /* 0x66 */ x86emuOp2_illegal_op, /* 0x67 */ x86emuOp2_illegal_op, /* 0x68 */ x86emuOp2_illegal_op, /* 0x69 */ x86emuOp2_illegal_op, /* 0x6a */ x86emuOp2_illegal_op, /* 0x6b */ x86emuOp2_illegal_op, /* 0x6c */ x86emuOp2_illegal_op, /* 0x6d */ x86emuOp2_illegal_op, /* 0x6e */ x86emuOp2_illegal_op, /* 0x6f */ x86emuOp2_illegal_op, /* 0x70 */ x86emuOp2_illegal_op, /* 0x71 */ x86emuOp2_illegal_op, /* 0x72 */ x86emuOp2_illegal_op, /* 0x73 */ x86emuOp2_illegal_op, /* 0x74 */ x86emuOp2_illegal_op, /* 0x75 */ x86emuOp2_illegal_op, /* 0x76 */ x86emuOp2_illegal_op, /* 0x77 */ x86emuOp2_illegal_op, /* 0x78 */ x86emuOp2_illegal_op, /* 0x79 */ x86emuOp2_illegal_op, /* 0x7a */ x86emuOp2_illegal_op, /* 0x7b */ x86emuOp2_illegal_op, /* 0x7c */ x86emuOp2_illegal_op, /* 0x7d */ x86emuOp2_illegal_op, /* 0x7e */ x86emuOp2_illegal_op, /* 0x7f */ x86emuOp2_illegal_op, /* 0x80 */ x86emuOp2_long_jump, /* 0x81 */ x86emuOp2_long_jump, /* 0x82 */ x86emuOp2_long_jump, /* 0x83 */ x86emuOp2_long_jump, /* 0x84 */ x86emuOp2_long_jump, /* 0x85 */ x86emuOp2_long_jump, /* 0x86 */ x86emuOp2_long_jump, /* 0x87 */ x86emuOp2_long_jump, /* 0x88 */ x86emuOp2_long_jump, /* 0x89 */ x86emuOp2_long_jump, /* 0x8a */ x86emuOp2_long_jump, /* 0x8b */ x86emuOp2_long_jump, /* 0x8c */ x86emuOp2_long_jump, /* 0x8d */ x86emuOp2_long_jump, /* 0x8e */ x86emuOp2_long_jump, /* 0x8f */ x86emuOp2_long_jump, /* 0x90 */ x86emuOp2_set_byte, /* 0x91 */ x86emuOp2_set_byte, /* 0x92 */ x86emuOp2_set_byte, /* 0x93 */ x86emuOp2_set_byte, /* 0x94 */ x86emuOp2_set_byte, /* 0x95 */ x86emuOp2_set_byte, /* 0x96 */ x86emuOp2_set_byte, /* 0x97 */ x86emuOp2_set_byte, /* 0x98 */ x86emuOp2_set_byte, /* 0x99 */ x86emuOp2_set_byte, /* 0x9a */ x86emuOp2_set_byte, /* 0x9b */ x86emuOp2_set_byte, /* 0x9c */ x86emuOp2_set_byte, /* 0x9d */ x86emuOp2_set_byte, /* 0x9e */ x86emuOp2_set_byte, /* 0x9f */ x86emuOp2_set_byte, /* 0xa0 */ x86emuOp2_push_FS, /* 0xa1 */ x86emuOp2_pop_FS, /* 0xa2 */ x86emuOp2_cpuid, /* 0xa3 */ x86emuOp2_bt_R, /* 0xa4 */ x86emuOp2_shld_IMM, /* 0xa5 */ x86emuOp2_shld_CL, /* 0xa6 */ x86emuOp2_illegal_op, /* 0xa7 */ x86emuOp2_illegal_op, /* 0xa8 */ x86emuOp2_push_GS, /* 0xa9 */ x86emuOp2_pop_GS, /* 0xaa */ x86emuOp2_illegal_op, /* 0xab */ x86emuOp2_bts_R, /* 0xac */ x86emuOp2_shrd_IMM, /* 0xad */ x86emuOp2_shrd_CL, /* 0xae */ x86emuOp2_illegal_op, /* 0xaf */ x86emuOp2_imul_R_RM, /* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */ /* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */ /* 0xb2 */ x86emuOp2_lss_R_IMM, /* 0xb3 */ x86emuOp2_btr_R, /* 0xb4 */ x86emuOp2_lfs_R_IMM, /* 0xb5 */ x86emuOp2_lgs_R_IMM, /* 0xb6 */ x86emuOp2_movzx_byte_R_RM, /* 0xb7 */ x86emuOp2_movzx_word_R_RM, /* 0xb8 */ x86emuOp2_illegal_op, /* 0xb9 */ x86emuOp2_illegal_op, /* 0xba */ x86emuOp2_btX_I, /* 0xbb */ x86emuOp2_btc_R, /* 0xbc */ x86emuOp2_bsf, /* 0xbd */ x86emuOp2_bsr, /* 0xbe */ x86emuOp2_movsx_byte_R_RM, /* 0xbf */ x86emuOp2_movsx_word_R_RM, /* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */ /* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */ /* 0xc2 */ x86emuOp2_illegal_op, /* 0xc3 */ x86emuOp2_illegal_op, /* 0xc4 */ x86emuOp2_illegal_op, /* 0xc5 */ x86emuOp2_illegal_op, /* 0xc6 */ x86emuOp2_illegal_op, /* 0xc7 */ x86emuOp2_illegal_op, /* 0xc8 */ x86emuOp2_bswap, /* 0xc9 */ x86emuOp2_bswap, /* 0xca */ x86emuOp2_bswap, /* 0xcb */ x86emuOp2_bswap, /* 0xcc */ x86emuOp2_bswap, /* 0xcd */ x86emuOp2_bswap, /* 0xce */ x86emuOp2_bswap, /* 0xcf */ x86emuOp2_bswap, /* 0xd0 */ x86emuOp2_illegal_op, /* 0xd1 */ x86emuOp2_illegal_op, /* 0xd2 */ x86emuOp2_illegal_op, /* 0xd3 */ x86emuOp2_illegal_op, /* 0xd4 */ x86emuOp2_illegal_op, /* 0xd5 */ x86emuOp2_illegal_op, /* 0xd6 */ x86emuOp2_illegal_op, /* 0xd7 */ x86emuOp2_illegal_op, /* 0xd8 */ x86emuOp2_illegal_op, /* 0xd9 */ x86emuOp2_illegal_op, /* 0xda */ x86emuOp2_illegal_op, /* 0xdb */ x86emuOp2_illegal_op, /* 0xdc */ x86emuOp2_illegal_op, /* 0xdd */ x86emuOp2_illegal_op, /* 0xde */ x86emuOp2_illegal_op, /* 0xdf */ x86emuOp2_illegal_op, /* 0xe0 */ x86emuOp2_illegal_op, /* 0xe1 */ x86emuOp2_illegal_op, /* 0xe2 */ x86emuOp2_illegal_op, /* 0xe3 */ x86emuOp2_illegal_op, /* 0xe4 */ x86emuOp2_illegal_op, /* 0xe5 */ x86emuOp2_illegal_op, /* 0xe6 */ x86emuOp2_illegal_op, /* 0xe7 */ x86emuOp2_illegal_op, /* 0xe8 */ x86emuOp2_illegal_op, /* 0xe9 */ x86emuOp2_illegal_op, /* 0xea */ x86emuOp2_illegal_op, /* 0xeb */ x86emuOp2_illegal_op, /* 0xec */ x86emuOp2_illegal_op, /* 0xed */ x86emuOp2_illegal_op, /* 0xee */ x86emuOp2_illegal_op, /* 0xef */ x86emuOp2_illegal_op, /* 0xf0 */ x86emuOp2_illegal_op, /* 0xf1 */ x86emuOp2_illegal_op, /* 0xf2 */ x86emuOp2_illegal_op, /* 0xf3 */ x86emuOp2_illegal_op, /* 0xf4 */ x86emuOp2_illegal_op, /* 0xf5 */ x86emuOp2_illegal_op, /* 0xf6 */ x86emuOp2_illegal_op, /* 0xf7 */ x86emuOp2_illegal_op, /* 0xf8 */ x86emuOp2_illegal_op, /* 0xf9 */ x86emuOp2_illegal_op, /* 0xfa */ x86emuOp2_illegal_op, /* 0xfb */ x86emuOp2_illegal_op, /* 0xfc */ x86emuOp2_illegal_op, /* 0xfd */ x86emuOp2_illegal_op, /* 0xfe */ x86emuOp2_illegal_op, /* 0xff */ x86emuOp2_illegal_op, }; v86d-0.1.10/libs/x86emu/prim_ops.c000066400000000000000000002221661153201731300164460ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file contains the code to implement the primitive * machine operations used by the emulation code in ops.c * * Carry Chain Calculation * * This represents a somewhat expensive calculation which is * apparently required to emulate the setting of the OF and AF flag. * The latter is not so important, but the former is. The overflow * flag is the XOR of the top two bits of the carry chain for an * addition (similar for subtraction). Since we do not want to * simulate the addition in a bitwise manner, we try to calculate the * carry chain given the two operands and the result. * * So, given the following table, which represents the addition of two * bits, we can derive a formula for the carry chain. * * a b cin r cout * 0 0 0 0 0 * 0 0 1 1 0 * 0 1 0 1 0 * 0 1 1 0 1 * 1 0 0 1 0 * 1 0 1 0 1 * 1 1 0 0 1 * 1 1 1 1 1 * * Construction of table for cout: * * ab * r \ 00 01 11 10 * |------------------ * 0 | 0 1 1 1 * 1 | 0 0 1 0 * * By inspection, one gets: cc = ab + r'(a + b) * * That represents alot of operations, but NO CHOICE.... * * Borrow Chain Calculation. * * The following table represents the subtraction of two bits, from * which we can derive a formula for the borrow chain. * * a b bin r bout * 0 0 0 0 0 * 0 0 1 1 1 * 0 1 0 1 1 * 0 1 1 0 1 * 1 0 0 1 0 * 1 0 1 0 0 * 1 1 0 0 0 * 1 1 1 1 1 * * Construction of table for cout: * * ab * r \ 00 01 11 10 * |------------------ * 0 | 0 1 0 0 * 1 | 1 1 1 0 * * By inspection, one gets: bc = a'b + r(a' + b) * ****************************************************************************/ #include #define PRIM_OPS_NO_REDEFINE_ASM #include "x86emu/x86emui.h" /*------------------------- Global Variables ------------------------------*/ static u32 x86emu_parity_tab[8] = { 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x96696996, 0x69969669, }; #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) /*----------------------------- Implementation ----------------------------*/ /**************************************************************************** REMARKS: Implements the AAA instruction and side effects. ****************************************************************************/ u16 aaa_word(u16 d) { u16 res; if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { d += 0x6; d += 0x100; SET_FLAG(F_AF); SET_FLAG(F_CF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); } res = (u16)(d & 0xFF0F); CLEAR_FLAG(F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return res; } /**************************************************************************** REMARKS: Implements the AAA instruction and side effects. ****************************************************************************/ u16 aas_word(u16 d) { u16 res; if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { d -= 0x6; d -= 0x100; SET_FLAG(F_AF); SET_FLAG(F_CF); } else { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); } res = (u16)(d & 0xFF0F); CLEAR_FLAG(F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return res; } /**************************************************************************** REMARKS: Implements the AAD instruction and side effects. ****************************************************************************/ u16 aad_word(u16 d) { u16 l; u8 hb, lb; hb = (u8)((d >> 8) & 0xff); lb = (u8)((d & 0xff)); l = (u16)((lb + 10 * hb) & 0xFF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(l & 0x80, F_SF); CONDITIONAL_SET_FLAG(l == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); return l; } /**************************************************************************** REMARKS: Implements the AAM instruction and side effects. ****************************************************************************/ u16 aam_word(u8 d) { u16 h, l; h = (u16)(d / 10); l = (u16)(d % 10); l |= (u16)(h << 8); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(l & 0x80, F_SF); CONDITIONAL_SET_FLAG(l == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); return l; } /**************************************************************************** REMARKS: Implements the ADC instruction and side effects. ****************************************************************************/ u8 adc_byte(u8 d, u8 s) { register u32 res; /* all operands in native machine order */ register u32 cc; if (ACCESS_FLAG(F_CF)) res = 1 + d + s; else res = d + s; CONDITIONAL_SET_FLAG(res & 0x100, F_CF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return (u8)res; } /**************************************************************************** REMARKS: Implements the ADC instruction and side effects. ****************************************************************************/ u16 adc_word(u16 d, u16 s) { register u32 res; /* all operands in native machine order */ register u32 cc; if (ACCESS_FLAG(F_CF)) res = 1 + d + s; else res = d + s; CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return (u16)res; } /**************************************************************************** REMARKS: Implements the ADC instruction and side effects. ****************************************************************************/ u32 adc_long(u32 d, u32 s) { register u32 lo; /* all operands in native machine order */ register u32 hi; register u32 res; register u32 cc; if (ACCESS_FLAG(F_CF)) { lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); res = 1 + d + s; } else { lo = (d & 0xFFFF) + (s & 0xFFFF); res = d + s; } hi = (lo >> 16) + (d >> 16) + (s >> 16); CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the ADD instruction and side effects. ****************************************************************************/ u8 add_byte(u8 d, u8 s) { register u32 res; /* all operands in native machine order */ register u32 cc; res = d + s; CONDITIONAL_SET_FLAG(res & 0x100, F_CF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return (u8)res; } /**************************************************************************** REMARKS: Implements the ADD instruction and side effects. ****************************************************************************/ u16 add_word(u16 d, u16 s) { register u32 res; /* all operands in native machine order */ register u32 cc; res = d + s; CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return (u16)res; } /**************************************************************************** REMARKS: Implements the ADD instruction and side effects. ****************************************************************************/ u32 add_long(u32 d, u32 s) { register u32 lo; /* all operands in native machine order */ register u32 hi; register u32 res; register u32 cc; lo = (d & 0xFFFF) + (s & 0xFFFF); res = d + s; hi = (lo >> 16) + (d >> 16) + (s >> 16); CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (s & d) | ((~res) & (s | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the AND instruction and side effects. ****************************************************************************/ u8 and_byte(u8 d, u8 s) { register u8 res; /* all operands in native machine order */ res = d & s; /* set the flags */ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res), F_PF); return res; } /**************************************************************************** REMARKS: Implements the AND instruction and side effects. ****************************************************************************/ u16 and_word(u16 d, u16 s) { register u16 res; /* all operands in native machine order */ res = d & s; /* set the flags */ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return res; } /**************************************************************************** REMARKS: Implements the AND instruction and side effects. ****************************************************************************/ u32 and_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ res = d & s; /* set the flags */ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return res; } /**************************************************************************** REMARKS: Implements the CMP instruction and side effects. ****************************************************************************/ u8 cmp_byte(u8 d, u8 s) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - s; CLEAR_FLAG(F_CF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return d; } /**************************************************************************** REMARKS: Implements the CMP instruction and side effects. ****************************************************************************/ u16 cmp_word(u16 d, u16 s) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - s; CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return d; } /**************************************************************************** REMARKS: Implements the CMP instruction and side effects. ****************************************************************************/ u32 cmp_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - s; CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return d; } /**************************************************************************** REMARKS: Implements the DAA instruction and side effects. ****************************************************************************/ u8 daa_byte(u8 d) { u32 res = d; if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { res += 6; SET_FLAG(F_AF); } if (res > 0x9F || ACCESS_FLAG(F_CF)) { res += 0x60; SET_FLAG(F_CF); } CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return (u8)res; } /**************************************************************************** REMARKS: Implements the DAS instruction and side effects. ****************************************************************************/ u8 das_byte(u8 d) { if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { d -= 6; SET_FLAG(F_AF); } if (d > 0x9F || ACCESS_FLAG(F_CF)) { d -= 0x60; SET_FLAG(F_CF); } CONDITIONAL_SET_FLAG(d & 0x80, F_SF); CONDITIONAL_SET_FLAG(d == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); return d; } /**************************************************************************** REMARKS: Implements the DEC instruction and side effects. ****************************************************************************/ u8 dec_byte(u8 d) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - 1; CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ /* based on sub_byte, uses s==1. */ bc = (res & (~d | 1)) | (~d & 1); /* carry flag unchanged */ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return (u8)res; } /**************************************************************************** REMARKS: Implements the DEC instruction and side effects. ****************************************************************************/ u16 dec_word(u16 d) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - 1; CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ /* based on the sub_byte routine, with s==1 */ bc = (res & (~d | 1)) | (~d & 1); /* carry flag unchanged */ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return (u16)res; } /**************************************************************************** REMARKS: Implements the DEC instruction and side effects. ****************************************************************************/ u32 dec_long(u32 d) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - 1; CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | 1)) | (~d & 1); /* carry flag unchanged */ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the INC instruction and side effects. ****************************************************************************/ u8 inc_byte(u8 d) { register u32 res; /* all operands in native machine order */ register u32 cc; res = d + 1; CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = ((1 & d) | (~res)) & (1 | d); CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return (u8)res; } /**************************************************************************** REMARKS: Implements the INC instruction and side effects. ****************************************************************************/ u16 inc_word(u16 d) { register u32 res; /* all operands in native machine order */ register u32 cc; res = d + 1; CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (1 & d) | ((~res) & (1 | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return (u16)res; } /**************************************************************************** REMARKS: Implements the INC instruction and side effects. ****************************************************************************/ u32 inc_long(u32 d) { register u32 res; /* all operands in native machine order */ register u32 cc; res = d + 1; CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the carry chain SEE NOTE AT TOP. */ cc = (1 & d) | ((~res) & (1 | d)); CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the OR instruction and side effects. ****************************************************************************/ u8 or_byte(u8 d, u8 s) { register u8 res; /* all operands in native machine order */ res = d | s; CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res), F_PF); return res; } /**************************************************************************** REMARKS: Implements the OR instruction and side effects. ****************************************************************************/ u16 or_word(u16 d, u16 s) { register u16 res; /* all operands in native machine order */ res = d | s; /* set the carry flag to be bit 8 */ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return res; } /**************************************************************************** REMARKS: Implements the OR instruction and side effects. ****************************************************************************/ u32 or_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ res = d | s; /* set the carry flag to be bit 8 */ CLEAR_FLAG(F_OF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); return res; } /**************************************************************************** REMARKS: Implements the OR instruction and side effects. ****************************************************************************/ u8 neg_byte(u8 s) { register u8 res; register u8 bc; CONDITIONAL_SET_FLAG(s != 0, F_CF); res = (u8)-s; CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res), F_PF); /* calculate the borrow chain --- modified such that d=0. substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and res&0xfff... == res. Similarly ~d&s == s. So the simplified result is: */ bc = res | s; CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the OR instruction and side effects. ****************************************************************************/ u16 neg_word(u16 s) { register u16 res; register u16 bc; CONDITIONAL_SET_FLAG(s != 0, F_CF); res = (u16)-s; CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain --- modified such that d=0. substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and res&0xfff... == res. Similarly ~d&s == s. So the simplified result is: */ bc = res | s; CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the OR instruction and side effects. ****************************************************************************/ u32 neg_long(u32 s) { register u32 res; register u32 bc; CONDITIONAL_SET_FLAG(s != 0, F_CF); res = (u32)-s; CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain --- modified such that d=0. substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and res&0xfff... == res. Similarly ~d&s == s. So the simplified result is: */ bc = res | s; CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the NOT instruction and side effects. ****************************************************************************/ u8 not_byte(u8 s) { return ~s; } /**************************************************************************** REMARKS: Implements the NOT instruction and side effects. ****************************************************************************/ u16 not_word(u16 s) { return ~s; } /**************************************************************************** REMARKS: Implements the NOT instruction and side effects. ****************************************************************************/ u32 not_long(u32 s) { return ~s; } /**************************************************************************** REMARKS: Implements the RCL instruction and side effects. ****************************************************************************/ u8 rcl_byte(u8 d, u8 s) { register unsigned int res, cnt, mask, cf; /* s is the rotate distance. It varies from 0 - 8. */ /* have CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 want to rotate through the carry by "s" bits. We could loop, but that's inefficient. So the width is 9, and we split into three parts: The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in B_7 .. B_n+1 The new rotate is done mod 9, and given this, for a rotation of n bits (mod 9) the new carry flag is then located n bits from the MSB. The low part is then shifted up cnt bits, and the high part is or'd in. Using CAPS for new values, and lowercase for the original values, this can be expressed as: IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ res = d; if ((cnt = s % 9) != 0) { /* extract the new CARRY FLAG. */ /* CF <- b_(8-n) */ cf = (d >> (8 - cnt)) & 0x1; /* get the low stuff which rotated into the range B_7 .. B_cnt */ /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ /* note that the right hand side done by the mask */ res = (d << cnt) & 0xff; /* now the high stuff which rotated around into the positions B_cnt-2 .. B_0 */ /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ /* shift it downward, 7-(n-2) = 9-n positions. and mask off the result before or'ing in. */ mask = (1 << (cnt - 1)) - 1; res |= (d >> (9 - cnt)) & mask; /* if the carry flag was set, or it in. */ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ /* B_(n-1) <- cf */ res |= 1 << (cnt - 1); } /* set the new carry flag, based on the variable "cf" */ CONDITIONAL_SET_FLAG(cf, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ /* parenthesized this expression since it appears to be causing OF to be misset */ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), F_OF); } return (u8)res; } /**************************************************************************** REMARKS: Implements the RCL instruction and side effects. ****************************************************************************/ u16 rcl_word(u16 d, u8 s) { register unsigned int res, cnt, mask, cf; res = d; if ((cnt = s % 17) != 0) { cf = (d >> (16 - cnt)) & 0x1; res = (d << cnt) & 0xffff; mask = (1 << (cnt - 1)) - 1; res |= (d >> (17 - cnt)) & mask; if (ACCESS_FLAG(F_CF)) { res |= 1 << (cnt - 1); } CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), F_OF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the RCL instruction and side effects. ****************************************************************************/ u32 rcl_long(u32 d, u8 s) { register u32 res, cnt, mask, cf; res = d; if ((cnt = s % 33) != 0) { cf = (d >> (32 - cnt)) & 0x1; res = (d << cnt) & 0xffffffff; mask = (1 << (cnt - 1)) - 1; res |= (d >> (33 - cnt)) & mask; if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ res |= 1 << (cnt - 1); } CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), F_OF); } return res; } /**************************************************************************** REMARKS: Implements the RCR instruction and side effects. ****************************************************************************/ u8 rcr_byte(u8 d, u8 s) { u32 res, cnt; u32 mask, cf, ocf = 0; /* rotate right through carry */ /* s is the rotate distance. It varies from 0 - 8. d is the byte object rotated. have CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 The new rotate is done mod 9, and given this, for a rotation of n bits (mod 9) the new carry flag is then located n bits from the LSB. The low part is then shifted up cnt bits, and the high part is or'd in. Using CAPS for new values, and lowercase for the original values, this can be expressed as: IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ res = d; if ((cnt = s % 9) != 0) { /* extract the new CARRY FLAG. */ /* CF <- b_(n-1) */ if (cnt == 1) { cf = d & 0x1; /* note hackery here. Access_flag(..) evaluates to either 0 if flag not set non-zero if flag is set. doing access_flag(..) != 0 casts that into either 0..1 in any representation of the flags register (i.e. packed bit array or unpacked.) */ ocf = ACCESS_FLAG(F_CF) != 0; } else cf = (d >> (cnt - 1)) & 0x1; /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ /* note that the right hand side done by the mask This is effectively done by shifting the object to the right. The result must be masked, in case the object came in and was treated as a negative number. Needed??? */ mask = (1 << (8 - cnt)) - 1; res = (d >> cnt) & mask; /* now the high stuff which rotated around into the positions B_cnt-2 .. B_0 */ /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ /* shift it downward, 7-(n-2) = 9-n positions. and mask off the result before or'ing in. */ res |= (d << (9 - cnt)); /* if the carry flag was set, or it in. */ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ /* B_(8-n) <- cf */ res |= 1 << (8 - cnt); } /* set the new carry flag, based on the variable "cf" */ CONDITIONAL_SET_FLAG(cf, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ /* parenthesized... */ if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), F_OF); } } return (u8)res; } /**************************************************************************** REMARKS: Implements the RCR instruction and side effects. ****************************************************************************/ u16 rcr_word(u16 d, u8 s) { u32 res, cnt; u32 mask, cf, ocf = 0; /* rotate right through carry */ res = d; if ((cnt = s % 17) != 0) { if (cnt == 1) { cf = d & 0x1; ocf = ACCESS_FLAG(F_CF) != 0; } else cf = (d >> (cnt - 1)) & 0x1; mask = (1 << (16 - cnt)) - 1; res = (d >> cnt) & mask; res |= (d << (17 - cnt)); if (ACCESS_FLAG(F_CF)) { res |= 1 << (16 - cnt); } CONDITIONAL_SET_FLAG(cf, F_CF); if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), F_OF); } } return (u16)res; } /**************************************************************************** REMARKS: Implements the RCR instruction and side effects. ****************************************************************************/ u32 rcr_long(u32 d, u8 s) { u32 res, cnt; u32 mask, cf, ocf = 0; /* rotate right through carry */ res = d; if ((cnt = s % 33) != 0) { if (cnt == 1) { cf = d & 0x1; ocf = ACCESS_FLAG(F_CF) != 0; } else cf = (d >> (cnt - 1)) & 0x1; mask = (1 << (32 - cnt)) - 1; res = (d >> cnt) & mask; if (cnt != 1) res |= (d << (33 - cnt)); if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ res |= 1 << (32 - cnt); } CONDITIONAL_SET_FLAG(cf, F_CF); if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), F_OF); } } return res; } /**************************************************************************** REMARKS: Implements the ROL instruction and side effects. ****************************************************************************/ u8 rol_byte(u8 d, u8 s) { register unsigned int res, cnt, mask; /* rotate left */ /* s is the rotate distance. It varies from 0 - 8. d is the byte object rotated. have CF B_7 ... B_0 The new rotate is done mod 8. Much simpler than the "rcl" or "rcr" operations. IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ res = d; if ((cnt = s % 8) != 0) { /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ res = (d << cnt); /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ mask = (1 << cnt) - 1; res |= (d >> (8 - cnt)) & mask; /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x1, F_CF); /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and the most significant bit. Blecck. */ CONDITIONAL_SET_FLAG(s == 1 && XOR2((res & 0x1) + ((res >> 6) & 0x2)), F_OF); } if (s != 0) { /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x1, F_CF); } return (u8)res; } /**************************************************************************** REMARKS: Implements the ROL instruction and side effects. ****************************************************************************/ u16 rol_word(u16 d, u8 s) { register unsigned int res, cnt, mask; res = d; if ((cnt = s % 16) != 0) { res = (d << cnt); mask = (1 << cnt) - 1; res |= (d >> (16 - cnt)) & mask; CONDITIONAL_SET_FLAG(res & 0x1, F_CF); CONDITIONAL_SET_FLAG(s == 1 && XOR2((res & 0x1) + ((res >> 14) & 0x2)), F_OF); } if (s != 0) { /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x1, F_CF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the ROL instruction and side effects. ****************************************************************************/ u32 rol_long(u32 d, u8 s) { register u32 res, cnt, mask; res = d; if ((cnt = s % 32) != 0) { res = (d << cnt); mask = (1 << cnt) - 1; res |= (d >> (32 - cnt)) & mask; CONDITIONAL_SET_FLAG(res & 0x1, F_CF); CONDITIONAL_SET_FLAG(s == 1 && XOR2((res & 0x1) + ((res >> 30) & 0x2)), F_OF); } if (s != 0) { /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x1, F_CF); } return res; } /**************************************************************************** REMARKS: Implements the ROR instruction and side effects. ****************************************************************************/ u8 ror_byte(u8 d, u8 s) { register unsigned int res, cnt, mask; /* rotate right */ /* s is the rotate distance. It varies from 0 - 8. d is the byte object rotated. have B_7 ... B_0 The rotate is done mod 8. IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ res = d; if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ res = (d << (8 - cnt)); /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ mask = (1 << (8 - cnt)) - 1; res |= (d >> (cnt)) & mask; /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x80, F_CF); /* OVERFLOW is set *IFF* s==1, then it is the xor of the two most significant bits. Blecck. */ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); } else if (s != 0) { /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x80, F_CF); } return (u8)res; } /**************************************************************************** REMARKS: Implements the ROR instruction and side effects. ****************************************************************************/ u16 ror_word(u16 d, u8 s) { register unsigned int res, cnt, mask; res = d; if ((cnt = s % 16) != 0) { res = (d << (16 - cnt)); mask = (1 << (16 - cnt)) - 1; res |= (d >> (cnt)) & mask; CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); } else if (s != 0) { /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the ROR instruction and side effects. ****************************************************************************/ u32 ror_long(u32 d, u8 s) { register u32 res, cnt, mask; res = d; if ((cnt = s % 32) != 0) { res = (d << (32 - cnt)); mask = (1 << (32 - cnt)) - 1; res |= (d >> (cnt)) & mask; CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); } else if (s != 0) { /* set the new carry flag, Note that it is the low order bit of the result!!! */ CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); } return res; } /**************************************************************************** REMARKS: Implements the SHL instruction and side effects. ****************************************************************************/ u8 shl_byte(u8 d, u8 s) { unsigned int cnt, res, cf; if (s < 8) { cnt = s % 8; /* last bit shifted out goes into carry flag */ if (cnt > 0) { res = d << cnt; cf = d & (1 << (8 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = (u8) d; } if (cnt == 1) { /* Needs simplification. */ CONDITIONAL_SET_FLAG( (((res & 0x80) == 0x80) ^ (ACCESS_FLAG(F_CF) != 0)), /* was (M.x86.R_FLG&F_CF)==F_CF)), */ F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } return (u8)res; } /**************************************************************************** REMARKS: Implements the SHL instruction and side effects. ****************************************************************************/ u16 shl_word(u16 d, u8 s) { unsigned int cnt, res, cf; if (s < 16) { cnt = s % 16; if (cnt > 0) { res = d << cnt; cf = d & (1 << (16 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = (u16) d; } if (cnt == 1) { CONDITIONAL_SET_FLAG( (((res & 0x8000) == 0x8000) ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the SHL instruction and side effects. ****************************************************************************/ u32 shl_long(u32 d, u8 s) { unsigned int cnt, res, cf; if (s < 32) { cnt = s % 32; if (cnt > 0) { res = d << cnt; cf = d & (1 << (32 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } return res; } /**************************************************************************** REMARKS: Implements the SHR instruction and side effects. ****************************************************************************/ u8 shr_byte(u8 d, u8 s) { unsigned int cnt, res, cf; if (s < 8) { cnt = s % 8; if (cnt > 0) { cf = d & (1 << (cnt - 1)); res = d >> cnt; CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = (u8) d; } if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } return (u8)res; } /**************************************************************************** REMARKS: Implements the SHR instruction and side effects. ****************************************************************************/ u16 shr_word(u16 d, u8 s) { unsigned int cnt, res, cf; if (s < 16) { cnt = s % 16; if (cnt > 0) { cf = d & (1 << (cnt - 1)); res = d >> cnt; CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the SHR instruction and side effects. ****************************************************************************/ u32 shr_long(u32 d, u8 s) { unsigned int cnt, res, cf; if (s < 32) { cnt = s % 32; if (cnt > 0) { cf = d & (1 << (cnt - 1)); res = d >> cnt; CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } return res; } /**************************************************************************** REMARKS: Implements the SAR instruction and side effects. ****************************************************************************/ u8 sar_byte(u8 d, u8 s) { unsigned int cnt, res, cf, mask, sf; res = d; sf = d & 0x80; cnt = s % 8; if (cnt > 0 && cnt < 8) { mask = (1 << (8 - cnt)) - 1; cf = d & (1 << (cnt - 1)); res = (d >> cnt) & mask; CONDITIONAL_SET_FLAG(cf, F_CF); if (sf) { res |= ~mask; } CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); } else if (cnt >= 8) { if (sf) { res = 0xff; SET_FLAG(F_CF); CLEAR_FLAG(F_ZF); SET_FLAG(F_SF); SET_FLAG(F_PF); } else { res = 0; CLEAR_FLAG(F_CF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } } return (u8)res; } /**************************************************************************** REMARKS: Implements the SAR instruction and side effects. ****************************************************************************/ u16 sar_word(u16 d, u8 s) { unsigned int cnt, res, cf, mask, sf; sf = d & 0x8000; cnt = s % 16; res = d; if (cnt > 0 && cnt < 16) { mask = (1 << (16 - cnt)) - 1; cf = d & (1 << (cnt - 1)); res = (d >> cnt) & mask; CONDITIONAL_SET_FLAG(cf, F_CF); if (sf) { res |= ~mask; } CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else if (cnt >= 16) { if (sf) { res = 0xffff; SET_FLAG(F_CF); CLEAR_FLAG(F_ZF); SET_FLAG(F_SF); SET_FLAG(F_PF); } else { res = 0; CLEAR_FLAG(F_CF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } } return (u16)res; } /**************************************************************************** REMARKS: Implements the SAR instruction and side effects. ****************************************************************************/ u32 sar_long(u32 d, u8 s) { u32 cnt, res, cf, mask, sf; sf = d & 0x80000000; cnt = s % 32; res = d; if (cnt > 0 && cnt < 32) { mask = (1 << (32 - cnt)) - 1; cf = d & (1 << (cnt - 1)); res = (d >> cnt) & mask; CONDITIONAL_SET_FLAG(cf, F_CF); if (sf) { res |= ~mask; } CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else if (cnt >= 32) { if (sf) { res = 0xffffffff; SET_FLAG(F_CF); CLEAR_FLAG(F_ZF); SET_FLAG(F_SF); SET_FLAG(F_PF); } else { res = 0; CLEAR_FLAG(F_CF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } } return res; } /**************************************************************************** REMARKS: Implements the SHLD instruction and side effects. ****************************************************************************/ u16 shld_word (u16 d, u16 fill, u8 s) { unsigned int cnt, res, cf; if (s < 16) { cnt = s % 16; if (cnt > 0) { res = (d << cnt) | (fill >> (16-cnt)); cf = d & (1 << (16 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the SHLD instruction and side effects. ****************************************************************************/ u32 shld_long (u32 d, u32 fill, u8 s) { unsigned int cnt, res, cf; if (s < 32) { cnt = s % 32; if (cnt > 0) { res = (d << cnt) | (fill >> (32-cnt)); cf = d & (1 << (32 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } return res; } /**************************************************************************** REMARKS: Implements the SHRD instruction and side effects. ****************************************************************************/ u16 shrd_word (u16 d, u16 fill, u8 s) { unsigned int cnt, res, cf; if (s < 16) { cnt = s % 16; if (cnt > 0) { cf = d & (1 << (cnt - 1)); res = (d >> cnt) | (fill << (16 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } return (u16)res; } /**************************************************************************** REMARKS: Implements the SHRD instruction and side effects. ****************************************************************************/ u32 shrd_long (u32 d, u32 fill, u8 s) { unsigned int cnt, res, cf; if (s < 32) { cnt = s % 32; if (cnt > 0) { cf = d & (1 << (cnt - 1)); res = (d >> cnt) | (fill << (32 - cnt)); CONDITIONAL_SET_FLAG(cf, F_CF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); } else { res = d; } if (cnt == 1) { CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); } else { CLEAR_FLAG(F_OF); } } else { res = 0; CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); SET_FLAG(F_ZF); CLEAR_FLAG(F_SF); CLEAR_FLAG(F_PF); } return res; } /**************************************************************************** REMARKS: Implements the SBB instruction and side effects. ****************************************************************************/ u8 sbb_byte(u8 d, u8 s) { register u32 res; /* all operands in native machine order */ register u32 bc; if (ACCESS_FLAG(F_CF)) res = d - s - 1; else res = d - s; CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return (u8)res; } /**************************************************************************** REMARKS: Implements the SBB instruction and side effects. ****************************************************************************/ u16 sbb_word(u16 d, u16 s) { register u32 res; /* all operands in native machine order */ register u32 bc; if (ACCESS_FLAG(F_CF)) res = d - s - 1; else res = d - s; CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return (u16)res; } /**************************************************************************** REMARKS: Implements the SBB instruction and side effects. ****************************************************************************/ u32 sbb_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ register u32 bc; if (ACCESS_FLAG(F_CF)) res = d - s - 1; else res = d - s; CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the SUB instruction and side effects. ****************************************************************************/ u8 sub_byte(u8 d, u8 s) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - s; CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return (u8)res; } /**************************************************************************** REMARKS: Implements the SUB instruction and side effects. ****************************************************************************/ u16 sub_word(u16 d, u16 s) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - s; CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return (u16)res; } /**************************************************************************** REMARKS: Implements the SUB instruction and side effects. ****************************************************************************/ u32 sub_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ register u32 bc; res = d - s; CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* calculate the borrow chain. See note at top */ bc = (res & (~d | s)) | (~d & s); CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); return res; } /**************************************************************************** REMARKS: Implements the TEST instruction and side effects. ****************************************************************************/ void test_byte(u8 d, u8 s) { register u32 res; /* all operands in native machine order */ res = d & s; CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* AF == dont care */ CLEAR_FLAG(F_CF); } /**************************************************************************** REMARKS: Implements the TEST instruction and side effects. ****************************************************************************/ void test_word(u16 d, u16 s) { register u32 res; /* all operands in native machine order */ res = d & s; CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* AF == dont care */ CLEAR_FLAG(F_CF); } /**************************************************************************** REMARKS: Implements the TEST instruction and side effects. ****************************************************************************/ void test_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ res = d & s; CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); /* AF == dont care */ CLEAR_FLAG(F_CF); } /**************************************************************************** REMARKS: Implements the XOR instruction and side effects. ****************************************************************************/ u8 xor_byte(u8 d, u8 s) { register u8 res; /* all operands in native machine order */ res = d ^ s; CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res), F_PF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); return res; } /**************************************************************************** REMARKS: Implements the XOR instruction and side effects. ****************************************************************************/ u16 xor_word(u16 d, u16 s) { register u16 res; /* all operands in native machine order */ res = d ^ s; CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); return res; } /**************************************************************************** REMARKS: Implements the XOR instruction and side effects. ****************************************************************************/ u32 xor_long(u32 d, u32 s) { register u32 res; /* all operands in native machine order */ res = d ^ s; CLEAR_FLAG(F_OF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(res == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); return res; } /**************************************************************************** REMARKS: Implements the IMUL instruction and side effects. ****************************************************************************/ void imul_byte(u8 s) { s16 res = (s16)((s8)M.x86.R_AL * (s8)s); M.x86.R_AX = res; if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) || ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { SET_FLAG(F_CF); SET_FLAG(F_OF); } } /**************************************************************************** REMARKS: Implements the IMUL instruction and side effects. ****************************************************************************/ void imul_word(u16 s) { s32 res = (s16)M.x86.R_AX * (s16)s; M.x86.R_AX = (u16)res; M.x86.R_DX = (u16)(res >> 16); if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) || ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { SET_FLAG(F_CF); SET_FLAG(F_OF); } } /**************************************************************************** REMARKS: Implements the IMUL instruction and side effects. ****************************************************************************/ void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s) { #ifdef __HAS_LONG_LONG__ s64 res = (s32)d * (s32)s; *res_lo = (u32)res; *res_hi = (u32)(res >> 32); #else u32 d_lo,d_hi,d_sign; u32 s_lo,s_hi,s_sign; u32 rlo_lo,rlo_hi,rhi_lo; if ((d_sign = d & 0x80000000) != 0) d = -d; d_lo = d & 0xFFFF; d_hi = d >> 16; if ((s_sign = s & 0x80000000) != 0) s = -s; s_lo = s & 0xFFFF; s_hi = s >> 16; rlo_lo = d_lo * s_lo; rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16); rhi_lo = d_hi * s_hi + (rlo_hi >> 16); *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF); *res_hi = rhi_lo; if (d_sign != s_sign) { d = ~*res_lo; s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16); *res_lo = ~*res_lo+1; *res_hi = ~*res_hi+(s >> 16); } #endif } /**************************************************************************** REMARKS: Implements the IMUL instruction and side effects. ****************************************************************************/ void imul_long(u32 s) { imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) || ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { SET_FLAG(F_CF); SET_FLAG(F_OF); } } /**************************************************************************** REMARKS: Implements the MUL instruction and side effects. ****************************************************************************/ void mul_byte(u8 s) { u16 res = (u16)(M.x86.R_AL * s); M.x86.R_AX = res; if (M.x86.R_AH == 0) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { SET_FLAG(F_CF); SET_FLAG(F_OF); } } /**************************************************************************** REMARKS: Implements the MUL instruction and side effects. ****************************************************************************/ void mul_word(u16 s) { u32 res = M.x86.R_AX * s; M.x86.R_AX = (u16)res; M.x86.R_DX = (u16)(res >> 16); if (M.x86.R_DX == 0) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { SET_FLAG(F_CF); SET_FLAG(F_OF); } } /**************************************************************************** REMARKS: Implements the MUL instruction and side effects. ****************************************************************************/ void mul_long(u32 s) { #ifdef __HAS_LONG_LONG__ u64 res = (u32)M.x86.R_EAX * (u32)s; M.x86.R_EAX = (u32)res; M.x86.R_EDX = (u32)(res >> 32); #else u32 a,a_lo,a_hi; u32 s_lo,s_hi; u32 rlo_lo,rlo_hi,rhi_lo; a = M.x86.R_EAX; a_lo = a & 0xFFFF; a_hi = a >> 16; s_lo = s & 0xFFFF; s_hi = s >> 16; rlo_lo = a_lo * s_lo; rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16); rhi_lo = a_hi * s_hi + (rlo_hi >> 16); M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF); M.x86.R_EDX = rhi_lo; #endif if (M.x86.R_EDX == 0) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_OF); } else { SET_FLAG(F_CF); SET_FLAG(F_OF); } } /**************************************************************************** REMARKS: Implements the IDIV instruction and side effects. ****************************************************************************/ void idiv_byte(u8 s) { s32 dvd, div, mod; dvd = (s16)M.x86.R_AX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (s8)s; mod = dvd % (s8)s; if (abs(div) > 0x7f) { x86emu_intr_raise(0); return; } M.x86.R_AL = (s8) div; M.x86.R_AH = (s8) mod; } /**************************************************************************** REMARKS: Implements the IDIV instruction and side effects. ****************************************************************************/ void idiv_word(u16 s) { s32 dvd, div, mod; dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (s16)s; mod = dvd % (s16)s; if (abs(div) > 0x7fff) { x86emu_intr_raise(0); return; } CLEAR_FLAG(F_CF); CLEAR_FLAG(F_SF); CONDITIONAL_SET_FLAG(div == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); M.x86.R_AX = (u16)div; M.x86.R_DX = (u16)mod; } /**************************************************************************** REMARKS: Implements the IDIV instruction and side effects. ****************************************************************************/ void idiv_long(u32 s) { #ifdef __HAS_LONG_LONG__ s64 dvd, div, mod; dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (s32)s; mod = dvd % (s32)s; if (abs(div) > 0x7fffffff) { x86emu_intr_raise(0); return; } #else s32 div = 0, mod; s32 h_dvd = M.x86.R_EDX; u32 l_dvd = M.x86.R_EAX; u32 abs_s = s & 0x7FFFFFFF; u32 abs_h_dvd = h_dvd & 0x7FFFFFFF; u32 h_s = abs_s >> 1; u32 l_s = abs_s << 31; int counter = 31; int carry; if (s == 0) { x86emu_intr_raise(0); return; } do { div <<= 1; carry = (l_dvd >= l_s) ? 0 : 1; if (abs_h_dvd < (h_s + carry)) { h_s >>= 1; l_s = abs_s << (--counter); continue; } else { abs_h_dvd -= (h_s + carry); l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) : (l_dvd - l_s); h_s >>= 1; l_s = abs_s << (--counter); div |= 1; continue; } } while (counter > -1); /* overflow */ if (abs_h_dvd || (l_dvd > abs_s)) { x86emu_intr_raise(0); return; } /* sign */ div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000)); mod = l_dvd; #endif CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF); SET_FLAG(F_ZF); CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); M.x86.R_EAX = (u32)div; M.x86.R_EDX = (u32)mod; } /**************************************************************************** REMARKS: Implements the DIV instruction and side effects. ****************************************************************************/ void div_byte(u8 s) { u32 dvd, div, mod; dvd = M.x86.R_AX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (u8)s; mod = dvd % (u8)s; if (abs(div) > 0xff) { x86emu_intr_raise(0); return; } M.x86.R_AL = (u8)div; M.x86.R_AH = (u8)mod; } /**************************************************************************** REMARKS: Implements the DIV instruction and side effects. ****************************************************************************/ void div_word(u16 s) { u32 dvd, div, mod; dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (u16)s; mod = dvd % (u16)s; if (abs(div) > 0xffff) { x86emu_intr_raise(0); return; } CLEAR_FLAG(F_CF); CLEAR_FLAG(F_SF); CONDITIONAL_SET_FLAG(div == 0, F_ZF); CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); M.x86.R_AX = (u16)div; M.x86.R_DX = (u16)mod; } /**************************************************************************** REMARKS: Implements the DIV instruction and side effects. ****************************************************************************/ void div_long(u32 s) { #ifdef __HAS_LONG_LONG__ u64 dvd, div, mod; dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX; if (s == 0) { x86emu_intr_raise(0); return; } div = dvd / (u32)s; mod = dvd % (u32)s; if (abs(div) > 0xffffffff) { x86emu_intr_raise(0); return; } #else s32 div = 0, mod; s32 h_dvd = M.x86.R_EDX; u32 l_dvd = M.x86.R_EAX; u32 h_s = s; u32 l_s = 0; int counter = 32; int carry; if (s == 0) { x86emu_intr_raise(0); return; } do { div <<= 1; carry = (l_dvd >= l_s) ? 0 : 1; if (h_dvd < (h_s + carry)) { h_s >>= 1; l_s = s << (--counter); continue; } else { h_dvd -= (h_s + carry); l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) : (l_dvd - l_s); h_s >>= 1; l_s = s << (--counter); div |= 1; continue; } } while (counter > -1); /* overflow */ if (h_dvd || (l_dvd > s)) { x86emu_intr_raise(0); return; } mod = l_dvd; #endif CLEAR_FLAG(F_CF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF); SET_FLAG(F_ZF); CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); M.x86.R_EAX = (u32)div; M.x86.R_EDX = (u32)mod; } /**************************************************************************** REMARKS: Implements the IN string instruction and side effects. ****************************************************************************/ void ins(int size) { int inc = size; if (ACCESS_FLAG(F_DF)) { inc = -size; } if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* in until CX is ZERO. */ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? M.x86.R_ECX : M.x86.R_CX); switch (size) { case 1: while (count--) { store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, (*sys_inb)(M.x86.R_DX)); M.x86.R_DI += inc; } break; case 2: while (count--) { store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (*sys_inw)(M.x86.R_DX)); M.x86.R_DI += inc; } break; case 4: while (count--) { store_data_long_abs(M.x86.R_ES, M.x86.R_DI, (*sys_inl)(M.x86.R_DX)); M.x86.R_DI += inc; } break; } M.x86.R_CX = 0; if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = 0; } M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } else { switch (size) { case 1: store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, (*sys_inb)(M.x86.R_DX)); break; case 2: store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (*sys_inw)(M.x86.R_DX)); break; case 4: store_data_long_abs(M.x86.R_ES, M.x86.R_DI, (*sys_inl)(M.x86.R_DX)); break; } M.x86.R_DI += inc; } } /**************************************************************************** REMARKS: Implements the OUT string instruction and side effects. ****************************************************************************/ void outs(int size) { int inc = size; if (ACCESS_FLAG(F_DF)) { inc = -size; } if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { /* dont care whether REPE or REPNE */ /* out until CX is ZERO. */ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? M.x86.R_ECX : M.x86.R_CX); switch (size) { case 1: while (count--) { (*sys_outb)(M.x86.R_DX, fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); M.x86.R_SI += inc; } break; case 2: while (count--) { (*sys_outw)(M.x86.R_DX, fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); M.x86.R_SI += inc; } break; case 4: while (count--) { (*sys_outl)(M.x86.R_DX, fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI)); M.x86.R_SI += inc; } break; } M.x86.R_CX = 0; if (M.x86.mode & SYSMODE_PREFIX_DATA) { M.x86.R_ECX = 0; } M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); } else { switch (size) { case 1: (*sys_outb)(M.x86.R_DX, fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); break; case 2: (*sys_outw)(M.x86.R_DX, fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); break; case 4: (*sys_outl)(M.x86.R_DX, fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI)); break; } M.x86.R_SI += inc; } } /**************************************************************************** PARAMETERS: addr - Address to fetch word from REMARKS: Fetches a word from emulator memory using an absolute address. ****************************************************************************/ u16 mem_access_word(int addr) { DB( if (CHECK_MEM_ACCESS()) x86emu_check_mem_access(addr);) return (*sys_rdw)(addr); } /**************************************************************************** REMARKS: Pushes a word onto the stack. NOTE: Do not inline this, as (*sys_wrX) is already inline! ****************************************************************************/ void push_word(u16 w) { DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) M.x86.R_SP -= 2; (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w); } /**************************************************************************** REMARKS: Pushes a long onto the stack. NOTE: Do not inline this, as (*sys_wrX) is already inline! ****************************************************************************/ void push_long(u32 w) { DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) M.x86.R_SP -= 4; (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w); } /**************************************************************************** REMARKS: Pops a word from the stack. NOTE: Do not inline this, as (*sys_rdX) is already inline! ****************************************************************************/ u16 pop_word(void) { register u16 res; DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP); M.x86.R_SP += 2; return res; } /**************************************************************************** REMARKS: Pops a long from the stack. NOTE: Do not inline this, as (*sys_rdX) is already inline! ****************************************************************************/ u32 pop_long(void) { register u32 res; DB( if (CHECK_SP_ACCESS()) x86emu_check_sp_access();) res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP); M.x86.R_SP += 4; return res; } /**************************************************************************** REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output ****************************************************************************/ void cpuid (void) { u32 feature = M.x86.R_EAX; switch (feature) { case 0: /* Regardless if we have real data from the hardware, the emulator * will only support upto feature 1, which we set in register EAX. * Registers EBX:EDX:ECX contain a string identifying the CPU. */ M.x86.R_EAX = 1; /* EBX:EDX:ECX = "GenuineIntel" */ M.x86.R_EBX = 0x756e6547; M.x86.R_EDX = 0x49656e69; M.x86.R_ECX = 0x6c65746e; break; case 1: /* If we don't have x86 compatible hardware, we return values from an * Intel 486dx4; which was one of the first processors to have CPUID. */ M.x86.R_EAX = 0x00000480; M.x86.R_EBX = 0x00000000; M.x86.R_ECX = 0x00000000; M.x86.R_EDX = 0x00000002; /* VME */ /* In the case that we have hardware CPUID instruction, we make sure * that the features reported are limited to TSC and VME. */ M.x86.R_EDX &= 0x00000012; break; default: /* Finally, we don't support any additional features. Most CPUs * return all zeros when queried for invalid or unsupported feature * numbers. */ M.x86.R_EAX = 0; M.x86.R_EBX = 0; M.x86.R_ECX = 0; M.x86.R_EDX = 0; break; } } v86d-0.1.10/libs/x86emu/sys.c000066400000000000000000000447761153201731300154450ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: This file includes subroutines which are related to * programmed I/O and memory access. Included in this module * are default functions with limited usefulness. For real * uses these functions will most likely be overriden by the * user library. * ****************************************************************************/ #include "x86emu.h" #include "x86emu/x86emui.h" #include "x86emu/regs.h" #include "x86emu/debug.h" #include "x86emu/prim_ops.h" #ifndef NO_SYS_HEADERS #include #endif /*------------------------- Global Variables ------------------------------*/ X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ X86EMU_intrFuncs _X86EMU_intrTab[256]; /*----------------------------- Implementation ----------------------------*/ #if defined(__alpha__) || defined(__alpha) /* to cope with broken egcs-1.1.2 :-(((( */ #define ALPHA_UALOADS /* * inline functions to do unaligned accesses * from linux/include/asm-alpha/unaligned.h */ /* * EGCS 1.1 knows about arbitrary unaligned loads. Define some * packed structures to talk about such things with. */ #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) struct __una_u64 { unsigned long x __attribute__((packed)); }; struct __una_u32 { unsigned int x __attribute__((packed)); }; struct __una_u16 { unsigned short x __attribute__((packed)); }; #endif static __inline__ unsigned long ldq_u(unsigned long * r11) { #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) const struct __una_u64 *ptr = (const struct __una_u64 *) r11; return ptr->x; #else unsigned long r1,r2; __asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extql %0,%2,%0\n\t" "extqh %1,%2,%1" :"=&r" (r1), "=&r" (r2) :"r" (r11), "m" (*r11), "m" (*(const unsigned long *)(7+(char *) r11))); return r1 | r2; #endif } static __inline__ unsigned long ldl_u(unsigned int * r11) { #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) const struct __una_u32 *ptr = (const struct __una_u32 *) r11; return ptr->x; #else unsigned long r1,r2; __asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extll %0,%2,%0\n\t" "extlh %1,%2,%1" :"=&r" (r1), "=&r" (r2) :"r" (r11), "m" (*r11), "m" (*(const unsigned long *)(3+(char *) r11))); return r1 | r2; #endif } static __inline__ unsigned long ldw_u(unsigned short * r11) { #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) const struct __una_u16 *ptr = (const struct __una_u16 *) r11; return ptr->x; #else unsigned long r1,r2; __asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extwl %0,%2,%0\n\t" "extwh %1,%2,%1" :"=&r" (r1), "=&r" (r2) :"r" (r11), "m" (*r11), "m" (*(const unsigned long *)(1+(char *) r11))); return r1 | r2; #endif } /* * Elemental unaligned stores */ static __inline__ void stq_u(unsigned long r5, unsigned long * r11) { #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) struct __una_u64 *ptr = (struct __una_u64 *) r11; ptr->x = r5; #else unsigned long r1,r2,r3,r4; __asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "insqh %6,%7,%5\n\t" "insql %6,%7,%4\n\t" "mskqh %3,%7,%3\n\t" "mskql %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0" :"=m" (*r11), "=m" (*(unsigned long *)(7+(char *) r11)), "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) :"r" (r5), "r" (r11)); #endif } static __inline__ void stl_u(unsigned long r5, unsigned int * r11) { #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) struct __una_u32 *ptr = (struct __una_u32 *) r11; ptr->x = r5; #else unsigned long r1,r2,r3,r4; __asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "inslh %6,%7,%5\n\t" "insll %6,%7,%4\n\t" "msklh %3,%7,%3\n\t" "mskll %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0" :"=m" (*r11), "=m" (*(unsigned long *)(3+(char *) r11)), "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) :"r" (r5), "r" (r11)); #endif } static __inline__ void stw_u(unsigned long r5, unsigned short * r11) { #if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91)) struct __una_u16 *ptr = (struct __una_u16 *) r11; ptr->x = r5; #else unsigned long r1,r2,r3,r4; __asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "inswh %6,%7,%5\n\t" "inswl %6,%7,%4\n\t" "mskwh %3,%7,%3\n\t" "mskwl %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0" :"=m" (*r11), "=m" (*(unsigned long *)(1+(char *) r11)), "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) :"r" (r5), "r" (r11)); #endif } #elif defined(__GNUC__) && ((__GNUC__ < 3)) && \ (defined (__ia64__) || defined (ia64__)) #define IA64_UALOADS /* * EGCS 1.1 knows about arbitrary unaligned loads. Define some * packed structures to talk about such things with. */ struct __una_u64 { unsigned long x __attribute__((packed)); }; struct __una_u32 { unsigned int x __attribute__((packed)); }; struct __una_u16 { unsigned short x __attribute__((packed)); }; static __inline__ unsigned long __uldq (const unsigned long * r11) { const struct __una_u64 *ptr = (const struct __una_u64 *) r11; return ptr->x; } static __inline__ unsigned long uldl (const unsigned int * r11) { const struct __una_u32 *ptr = (const struct __una_u32 *) r11; return ptr->x; } static __inline__ unsigned long uldw (const unsigned short * r11) { const struct __una_u16 *ptr = (const struct __una_u16 *) r11; return ptr->x; } static __inline__ void ustq (unsigned long r5, unsigned long * r11) { struct __una_u64 *ptr = (struct __una_u64 *) r11; ptr->x = r5; } static __inline__ void ustl (unsigned long r5, unsigned int * r11) { struct __una_u32 *ptr = (struct __una_u32 *) r11; ptr->x = r5; } static __inline__ void ustw (unsigned long r5, unsigned short * r11) { struct __una_u16 *ptr = (struct __una_u16 *) r11; ptr->x = r5; } #endif /**************************************************************************** PARAMETERS: addr - Emulator memory address to read RETURNS: Byte value read from emulator memory. REMARKS: Reads a byte value from the emulator memory. ****************************************************************************/ u8 X86API rdb( u32 addr) { u8 val; if (addr > M.mem_size - 1) { DB(printk("mem_read: address %#lx out of range!\n", addr);) HALT_SYS(); } val = *(u8*)(M.mem_base + addr); DB( if (DEBUG_MEM_TRACE()) printk("%#08x 1 -> %#x\n", addr, val);) return val; } /**************************************************************************** PARAMETERS: addr - Emulator memory address to read RETURNS: Word value read from emulator memory. REMARKS: Reads a word value from the emulator memory. ****************************************************************************/ u16 X86API rdw( u32 addr) { u16 val = 0; if (addr > M.mem_size - 2) { DB(printk("mem_read: address %#lx out of range!\n", addr);) HALT_SYS(); } #ifdef __BIG_ENDIAN__ if (addr & 0x1) { val = (*(u8*)(M.mem_base + addr) | (*(u8*)(M.mem_base + addr + 1) << 8)); } else #endif #if defined(ALPHA_UALOADS) val = ldw_u((u16*)(M.mem_base + addr)); #elif defined(IA64_UALOADS) val = uldw((u16*)(M.mem_base + addr)); #else val = *(u16*)(M.mem_base + addr); #endif DB( if (DEBUG_MEM_TRACE()) printk("%#08x 2 -> %#x\n", addr, val);) return val; } /**************************************************************************** PARAMETERS: addr - Emulator memory address to read RETURNS: Long value read from emulator memory. REMARKS: Reads a long value from the emulator memory. ****************************************************************************/ u32 X86API rdl( u32 addr) { u32 val = 0; if (addr > M.mem_size - 4) { DB(printk("mem_read: address %#lx out of range!\n", addr);) HALT_SYS(); } #ifdef __BIG_ENDIAN__ if (addr & 0x3) { val = (*(u8*)(M.mem_base + addr + 0) | (*(u8*)(M.mem_base + addr + 1) << 8) | (*(u8*)(M.mem_base + addr + 2) << 16) | (*(u8*)(M.mem_base + addr + 3) << 24)); } else #endif #if defined(ALPHA_UALOADS) val = ldl_u((u32*)(M.mem_base + addr)); #elif defined(IA64_UALOADS) val = uldl((u32*)(M.mem_base + addr)); #else val = *(u32*)(M.mem_base + addr); #endif DB( if (DEBUG_MEM_TRACE()) printk("%#08x 4 -> %#x\n", addr, val);) return val; } /**************************************************************************** PARAMETERS: addr - Emulator memory address to read val - Value to store REMARKS: Writes a byte value to emulator memory. ****************************************************************************/ void X86API wrb( u32 addr, u8 val) { DB( if (DEBUG_MEM_TRACE()) printk("%#08x 1 <- %#x\n", addr, val);) if (addr > M.mem_size - 1) { DB(printk("mem_write: address %#lx out of range!\n", addr);) HALT_SYS(); } *(u8*)(M.mem_base + addr) = val; } /**************************************************************************** PARAMETERS: addr - Emulator memory address to read val - Value to store REMARKS: Writes a word value to emulator memory. ****************************************************************************/ void X86API wrw( u32 addr, u16 val) { DB( if (DEBUG_MEM_TRACE()) printk("%#08x 2 <- %#x\n", addr, val);) if (addr > M.mem_size - 2) { DB(printk("mem_write: address %#lx out of range!\n", addr);) HALT_SYS(); } #ifdef __BIG_ENDIAN__ if (addr & 0x1) { *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; } else #endif #if defined(ALPHA_UALOADS) stw_u(val,(u16*)(M.mem_base + addr)); #elif defined(IA64_UALOADS) ustw(val,(u16*)(M.mem_base + addr)); #else *(u16*)(M.mem_base + addr) = val; #endif } /**************************************************************************** PARAMETERS: addr - Emulator memory address to read val - Value to store REMARKS: Writes a long value to emulator memory. ****************************************************************************/ void X86API wrl( u32 addr, u32 val) { DB( if (DEBUG_MEM_TRACE()) printk("%#08x 4 <- %#x\n", addr, val);) if (addr > M.mem_size - 4) { DB(printk("mem_write: address %#lx out of range!\n", addr);) HALT_SYS(); } #ifdef __BIG_ENDIAN__ if (addr & 0x1) { *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff; *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff; } else #endif #if defined(ALPHA_UALOADS) stl_u(val,(u32*)(M.mem_base + addr)); #elif defined(IA64_UALOADS) ustl(val,(u32*)(M.mem_base + addr)); #else *(u32*)(M.mem_base + addr) = val; #endif } /**************************************************************************** PARAMETERS: addr - PIO address to read RETURN: 0 REMARKS: Default PIO byte read function. Doesn't perform real inb. ****************************************************************************/ static u8 X86API p_inb( X86EMU_pioAddr addr) { DB( if (DEBUG_IO_TRACE()) printk("inb %#04x \n", addr);) return 0; } /**************************************************************************** PARAMETERS: addr - PIO address to read RETURN: 0 REMARKS: Default PIO word read function. Doesn't perform real inw. ****************************************************************************/ static u16 X86API p_inw( X86EMU_pioAddr addr) { DB( if (DEBUG_IO_TRACE()) printk("inw %#04x \n", addr);) return 0; } /**************************************************************************** PARAMETERS: addr - PIO address to read RETURN: 0 REMARKS: Default PIO long read function. Doesn't perform real inl. ****************************************************************************/ static u32 X86API p_inl( X86EMU_pioAddr addr) { DB( if (DEBUG_IO_TRACE()) printk("inl %#04x \n", addr);) return 0; } /**************************************************************************** PARAMETERS: addr - PIO address to write val - Value to store REMARKS: Default PIO byte write function. Doesn't perform real outb. ****************************************************************************/ static void X86API p_outb( X86EMU_pioAddr addr, u8 val) { DB( if (DEBUG_IO_TRACE()) printk("outb %#02x -> %#04x \n", val, addr);) return; } /**************************************************************************** PARAMETERS: addr - PIO address to write val - Value to store REMARKS: Default PIO word write function. Doesn't perform real outw. ****************************************************************************/ static void X86API p_outw( X86EMU_pioAddr addr, u16 val) { DB( if (DEBUG_IO_TRACE()) printk("outw %#04x -> %#04x \n", val, addr);) return; } /**************************************************************************** PARAMETERS: addr - PIO address to write val - Value to store REMARKS: Default PIO ;ong write function. Doesn't perform real outl. ****************************************************************************/ static void X86API p_outl( X86EMU_pioAddr addr, u32 val) { DB( if (DEBUG_IO_TRACE()) printk("outl %#08x -> %#04x \n", val, addr);) return; } /*------------------------- Global Variables ------------------------------*/ u8 (X86APIP sys_rdb)(u32 addr) = rdb; u16 (X86APIP sys_rdw)(u32 addr) = rdw; u32 (X86APIP sys_rdl)(u32 addr) = rdl; void (X86APIP sys_wrb)(u32 addr,u8 val) = wrb; void (X86APIP sys_wrw)(u32 addr,u16 val) = wrw; void (X86APIP sys_wrl)(u32 addr,u32 val) = wrl; u8 (X86APIP sys_inb)(X86EMU_pioAddr addr) = p_inb; u16 (X86APIP sys_inw)(X86EMU_pioAddr addr) = p_inw; u32 (X86APIP sys_inl)(X86EMU_pioAddr addr) = p_inl; void (X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) = p_outb; void (X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val) = p_outw; void (X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val) = p_outl; /*----------------------------- Setup -------------------------------------*/ /**************************************************************************** PARAMETERS: funcs - New memory function pointers to make active REMARKS: This function is used to set the pointers to functions which access memory space, allowing the user application to override these functions and hook them out as necessary for their application. ****************************************************************************/ void X86EMU_setupMemFuncs( X86EMU_memFuncs *funcs) { sys_rdb = funcs->rdb; sys_rdw = funcs->rdw; sys_rdl = funcs->rdl; sys_wrb = funcs->wrb; sys_wrw = funcs->wrw; sys_wrl = funcs->wrl; } /**************************************************************************** PARAMETERS: funcs - New programmed I/O function pointers to make active REMARKS: This function is used to set the pointers to functions which access I/O space, allowing the user application to override these functions and hook them out as necessary for their application. ****************************************************************************/ void X86EMU_setupPioFuncs( X86EMU_pioFuncs *funcs) { sys_inb = funcs->inb; sys_inw = funcs->inw; sys_inl = funcs->inl; sys_outb = funcs->outb; sys_outw = funcs->outw; sys_outl = funcs->outl; } /**************************************************************************** PARAMETERS: funcs - New interrupt vector table to make active REMARKS: This function is used to set the pointers to functions which handle interrupt processing in the emulator, allowing the user application to hook interrupts as necessary for their application. Any interrupts that are not hooked by the user application, and reflected and handled internally in the emulator via the interrupt vector table. This allows the application to get control when the code being emulated executes specific software interrupts. ****************************************************************************/ void X86EMU_setupIntrFuncs( X86EMU_intrFuncs funcs[]) { int i; for (i=0; i < 256; i++) _X86EMU_intrTab[i] = NULL; if (funcs) { for (i = 0; i < 256; i++) _X86EMU_intrTab[i] = funcs[i]; } } /**************************************************************************** PARAMETERS: int - New software interrupt to prepare for REMARKS: This function is used to set up the emulator state to exceute a software interrupt. This can be used by the user application code to allow an interrupt to be hooked, examined and then reflected back to the emulator so that the code in the emulator will continue processing the software interrupt as per normal. This essentially allows system code to actively hook and handle certain software interrupts as necessary. ****************************************************************************/ void X86EMU_prepareForInt( int num) { push_word((u16)M.x86.R_FLG); CLEAR_FLAG(F_IF); CLEAR_FLAG(F_TF); push_word(M.x86.R_CS); M.x86.R_CS = mem_access_word(num * 4 + 2); push_word(M.x86.R_IP); M.x86.R_IP = mem_access_word(num * 4); M.x86.intr = 0; } v86d-0.1.10/libs/x86emu/validate.c000066400000000000000000001241601153201731300164020ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: Watcom C 10.6 or later * Environment: 32-bit DOS * Developer: Kendall Bennett * * Description: Program to validate the x86 emulator library for * correctness. We run the emulator primitive operations * functions against the real x86 CPU, and compare the result * and flags to ensure correctness. * * We use inline assembler to compile and build this program. * ****************************************************************************/ #include #include #include #include #include "x86emu.h" #include "x86emu/prim_asm.h" /*-------------------------- Implementation -------------------------------*/ #define true 1 #define false 0 #define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF) #define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \ { \ parm_type d,s; \ res_type r,r_asm; \ ulong flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < dmax; d += dincr) { \ for (s = 0; s < smax; s += sincr) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { #define VAL_TEST_BINARY(name) \ r_asm = name##_asm(&flags,d,s); \ r = name(d,s); \ if (r != r_asm || M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { #define VAL_TEST_BINARY_VOID(name) \ name##_asm(&flags,d,s); \ name(d,s); \ r = r_asm = 0; \ if (M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { #define VAL_FAIL_BYTE_BYTE_BINARY(name) \ if (failed) \ printk("fail\n"); \ printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_FAIL_WORD_WORD_BINARY(name) \ if (failed) \ printk("fail\n"); \ printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_FAIL_LONG_LONG_BINARY(name) \ if (failed) \ printk("fail\n"); \ printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_END_BINARY() \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_BYTE_BYTE_BINARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ VAL_TEST_BINARY(name) \ VAL_FAIL_BYTE_BYTE_BINARY(name) \ VAL_END_BINARY() #define VAL_WORD_WORD_BINARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ VAL_TEST_BINARY(name) \ VAL_FAIL_WORD_WORD_BINARY(name) \ VAL_END_BINARY() #define VAL_LONG_LONG_BINARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ VAL_TEST_BINARY(name) \ VAL_FAIL_LONG_LONG_BINARY(name) \ VAL_END_BINARY() #define VAL_VOID_BYTE_BINARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ VAL_TEST_BINARY_VOID(name) \ VAL_FAIL_BYTE_BYTE_BINARY(name) \ VAL_END_BINARY() #define VAL_VOID_WORD_BINARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ VAL_TEST_BINARY_VOID(name) \ VAL_FAIL_WORD_WORD_BINARY(name) \ VAL_END_BINARY() #define VAL_VOID_LONG_BINARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ VAL_TEST_BINARY_VOID(name) \ VAL_FAIL_LONG_LONG_BINARY(name) \ VAL_END_BINARY() #define VAL_BYTE_ROTATE(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u8,u8,0xFF,8,1,1) \ VAL_TEST_BINARY(name) \ VAL_FAIL_BYTE_BYTE_BINARY(name) \ VAL_END_BINARY() #define VAL_WORD_ROTATE(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \ VAL_TEST_BINARY(name) \ VAL_FAIL_WORD_WORD_BINARY(name) \ VAL_END_BINARY() #define VAL_LONG_ROTATE(name) \ printk("Validating %s ... ", #name); \ VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \ VAL_TEST_BINARY(name) \ VAL_FAIL_LONG_LONG_BINARY(name) \ VAL_END_BINARY() #define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\ { \ parm_type d,s; \ res_type r,r_asm; \ u8 shift; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < dmax; d += dincr) { \ for (s = 0; s < smax; s += sincr) { \ for (shift = 0; shift < maxshift; shift += 1) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { #define VAL_TEST_TERNARY(name) \ r_asm = name##_asm(&flags,d,s,shift); \ r = name(d,s,shift); \ if (r != r_asm || M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { #define VAL_FAIL_WORD_WORD_TERNARY(name) \ if (failed) \ printk("fail\n"); \ printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_FAIL_LONG_LONG_TERNARY(name) \ if (failed) \ printk("fail\n"); \ printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_END_TERNARY() \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_WORD_ROTATE_DBL(name) \ printk("Validating %s ... ", #name); \ VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \ VAL_TEST_TERNARY(name) \ VAL_FAIL_WORD_WORD_TERNARY(name) \ VAL_END_TERNARY() #define VAL_LONG_ROTATE_DBL(name) \ printk("Validating %s ... ", #name); \ VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \ VAL_TEST_TERNARY(name) \ VAL_FAIL_LONG_LONG_TERNARY(name) \ VAL_END_TERNARY() #define VAL_START_UNARY(parm_type,max,incr) \ { \ parm_type d,r,r_asm; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < max; d += incr) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { #define VAL_TEST_UNARY(name) \ r_asm = name##_asm(&flags,d); \ r = name(d); \ if (r != r_asm || M.x86.R_EFLG != flags) { \ failed = true; #define VAL_FAIL_BYTE_UNARY(name) \ printk("fail\n"); \ printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_FAIL_WORD_UNARY(name) \ printk("fail\n"); \ printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_FAIL_LONG_UNARY(name) \ printk("fail\n"); \ printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); #define VAL_END_UNARY() \ } \ M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_BYTE_UNARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_UNARY(u8,0xFF,0x1) \ VAL_TEST_UNARY(name) \ VAL_FAIL_BYTE_UNARY(name) \ VAL_END_UNARY() #define VAL_WORD_UNARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_UNARY(u16,0xFF00,0x100) \ VAL_TEST_UNARY(name) \ VAL_FAIL_WORD_UNARY(name) \ VAL_END_UNARY() #define VAL_WORD_BYTE_UNARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_UNARY(u16,0xFF,0x1) \ VAL_TEST_UNARY(name) \ VAL_FAIL_WORD_UNARY(name) \ VAL_END_UNARY() #define VAL_LONG_UNARY(name) \ printk("Validating %s ... ", #name); \ VAL_START_UNARY(u32,0xFF000000,0x1000000) \ VAL_TEST_UNARY(name) \ VAL_FAIL_LONG_UNARY(name) \ VAL_END_UNARY() #define VAL_BYTE_MUL(name) \ printk("Validating %s ... ", #name); \ { \ u8 d,s; \ u16 r,r_asm; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < 0xFF; d += 1) { \ for (s = 0; s < 0xFF; s += 1) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { \ name##_asm(&flags,&r_asm,d,s); \ M.x86.R_AL = d; \ name(s); \ r = M.x86.R_AX; \ if (r != r_asm || M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { \ if (failed) \ printk("fail\n"); \ printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_WORD_MUL(name) \ printk("Validating %s ... ", #name); \ { \ u16 d,s; \ u16 r_lo,r_asm_lo; \ u16 r_hi,r_asm_hi; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < 0xFF00; d += 0x100) { \ for (s = 0; s < 0xFF00; s += 0x100) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { \ name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ M.x86.R_AX = d; \ name(s); \ r_lo = M.x86.R_AX; \ r_hi = M.x86.R_DX; \ if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ failed = true; \ if (failed || trace) { \ if (failed) \ printk("fail\n"); \ printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_LONG_MUL(name) \ printk("Validating %s ... ", #name); \ { \ u32 d,s; \ u32 r_lo,r_asm_lo; \ u32 r_hi,r_asm_hi; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < 0xFF000000; d += 0x1000000) { \ for (s = 0; s < 0xFF000000; s += 0x1000000) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { \ name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ M.x86.R_EAX = d; \ name(s); \ r_lo = M.x86.R_EAX; \ r_hi = M.x86.R_EDX; \ if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ failed = true; \ if (failed || trace) { \ if (failed) \ printk("fail\n"); \ printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_BYTE_DIV(name) \ printk("Validating %s ... ", #name); \ { \ u16 d,s; \ u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < 0xFF00; d += 0x100) { \ for (s = 1; s < 0xFF; s += 1) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { \ M.x86.intr = 0; \ M.x86.R_AX = d; \ name(s); \ r_quot = M.x86.R_AL; \ r_rem = M.x86.R_AH; \ if (M.x86.intr & INTR_SYNCH) \ continue; \ name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \ if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { \ if (failed) \ printk("fail\n"); \ printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_WORD_DIV(name) \ printk("Validating %s ... ", #name); \ { \ u32 d,s; \ u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < 0xFF000000; d += 0x1000000) { \ for (s = 0x100; s < 0xFF00; s += 0x100) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { \ M.x86.intr = 0; \ M.x86.R_AX = d & 0xFFFF; \ M.x86.R_DX = d >> 16; \ name(s); \ r_quot = M.x86.R_AX; \ r_rem = M.x86.R_DX; \ if (M.x86.intr & INTR_SYNCH) \ continue; \ name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\ if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { \ if (failed) \ printk("fail\n"); \ printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } #define VAL_LONG_DIV(name) \ printk("Validating %s ... ", #name); \ { \ u32 d,s; \ u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \ u32 flags,inflags; \ int f,failed = false; \ char buf1[80],buf2[80]; \ for (d = 0; d < 0xFF000000; d += 0x1000000) { \ for (s = 0x100; s < 0xFF00; s += 0x100) { \ M.x86.R_EFLG = inflags = flags = def_flags; \ for (f = 0; f < 2; f++) { \ M.x86.intr = 0; \ M.x86.R_EAX = d; \ M.x86.R_EDX = 0; \ name(s); \ r_quot = M.x86.R_EAX; \ r_rem = M.x86.R_EDX; \ if (M.x86.intr & INTR_SYNCH) \ continue; \ name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \ if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ failed = true; \ if (failed || trace) { \ if (failed) \ printk("fail\n"); \ printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ } \ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (failed) \ break; \ } \ if (!failed) \ printk("passed\n"); \ } void printk(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); vfprintf(stdout, fmt, argptr); fflush(stdout); va_end(argptr); } char * print_flags(char *buf,ulong flags) { char *separator = ""; buf[0] = 0; if (flags & F_CF) { strcat(buf,separator); strcat(buf,"CF"); separator = ","; } if (flags & F_PF) { strcat(buf,separator); strcat(buf,"PF"); separator = ","; } if (flags & F_AF) { strcat(buf,separator); strcat(buf,"AF"); separator = ","; } if (flags & F_ZF) { strcat(buf,separator); strcat(buf,"ZF"); separator = ","; } if (flags & F_SF) { strcat(buf,separator); strcat(buf,"SF"); separator = ","; } if (flags & F_OF) { strcat(buf,separator); strcat(buf,"OF"); separator = ","; } if (separator[0] == 0) strcpy(buf,"None"); return buf; } int main(int argc) { ulong def_flags; int trace = false; if (argc > 1) trace = true; memset(&M, 0, sizeof(M)); def_flags = get_flags_asm() & ~ALL_FLAGS; VAL_WORD_UNARY(aaa_word); VAL_WORD_UNARY(aas_word); VAL_WORD_UNARY(aad_word); VAL_WORD_UNARY(aam_word); VAL_BYTE_BYTE_BINARY(adc_byte); VAL_WORD_WORD_BINARY(adc_word); VAL_LONG_LONG_BINARY(adc_long); VAL_BYTE_BYTE_BINARY(add_byte); VAL_WORD_WORD_BINARY(add_word); VAL_LONG_LONG_BINARY(add_long); VAL_BYTE_BYTE_BINARY(and_byte); VAL_WORD_WORD_BINARY(and_word); VAL_LONG_LONG_BINARY(and_long); VAL_BYTE_BYTE_BINARY(cmp_byte); VAL_WORD_WORD_BINARY(cmp_word); VAL_LONG_LONG_BINARY(cmp_long); VAL_BYTE_UNARY(daa_byte); VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway) VAL_BYTE_UNARY(dec_byte); VAL_WORD_UNARY(dec_word); VAL_LONG_UNARY(dec_long); VAL_BYTE_UNARY(inc_byte); VAL_WORD_UNARY(inc_word); VAL_LONG_UNARY(inc_long); VAL_BYTE_BYTE_BINARY(or_byte); VAL_WORD_WORD_BINARY(or_word); VAL_LONG_LONG_BINARY(or_long); VAL_BYTE_UNARY(neg_byte); VAL_WORD_UNARY(neg_word); VAL_LONG_UNARY(neg_long); VAL_BYTE_UNARY(not_byte); VAL_WORD_UNARY(not_word); VAL_LONG_UNARY(not_long); VAL_BYTE_ROTATE(rcl_byte); VAL_WORD_ROTATE(rcl_word); VAL_LONG_ROTATE(rcl_long); VAL_BYTE_ROTATE(rcr_byte); VAL_WORD_ROTATE(rcr_word); VAL_LONG_ROTATE(rcr_long); VAL_BYTE_ROTATE(rol_byte); VAL_WORD_ROTATE(rol_word); VAL_LONG_ROTATE(rol_long); VAL_BYTE_ROTATE(ror_byte); VAL_WORD_ROTATE(ror_word); VAL_LONG_ROTATE(ror_long); VAL_BYTE_ROTATE(shl_byte); VAL_WORD_ROTATE(shl_word); VAL_LONG_ROTATE(shl_long); VAL_BYTE_ROTATE(shr_byte); VAL_WORD_ROTATE(shr_word); VAL_LONG_ROTATE(shr_long); VAL_BYTE_ROTATE(sar_byte); VAL_WORD_ROTATE(sar_word); VAL_LONG_ROTATE(sar_long); VAL_WORD_ROTATE_DBL(shld_word); VAL_LONG_ROTATE_DBL(shld_long); VAL_WORD_ROTATE_DBL(shrd_word); VAL_LONG_ROTATE_DBL(shrd_long); VAL_BYTE_BYTE_BINARY(sbb_byte); VAL_WORD_WORD_BINARY(sbb_word); VAL_LONG_LONG_BINARY(sbb_long); VAL_BYTE_BYTE_BINARY(sub_byte); VAL_WORD_WORD_BINARY(sub_word); VAL_LONG_LONG_BINARY(sub_long); VAL_BYTE_BYTE_BINARY(xor_byte); VAL_WORD_WORD_BINARY(xor_word); VAL_LONG_LONG_BINARY(xor_long); VAL_VOID_BYTE_BINARY(test_byte); VAL_VOID_WORD_BINARY(test_word); VAL_VOID_LONG_BINARY(test_long); VAL_BYTE_MUL(imul_byte); VAL_WORD_MUL(imul_word); VAL_LONG_MUL(imul_long); VAL_BYTE_MUL(mul_byte); VAL_WORD_MUL(mul_word); VAL_LONG_MUL(mul_long); VAL_BYTE_DIV(idiv_byte); VAL_WORD_DIV(idiv_word); VAL_LONG_DIV(idiv_long); VAL_BYTE_DIV(div_byte); VAL_WORD_DIV(div_word); VAL_LONG_DIV(div_long); return 0; } v86d-0.1.10/libs/x86emu/x86emu.h000066400000000000000000000161431153201731300157530ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for public specific functions. * Any application linking against us should only * include this header * ****************************************************************************/ #ifndef __X86EMU_X86EMU_H #define __X86EMU_X86EMU_H #ifdef SCITECH #include "scitech.h" #define X86API _ASMAPI #define X86APIP _ASMAPIP typedef int X86EMU_pioAddr; #else #include "x86emu/types.h" #define X86API #define X86APIP * #endif #include "x86emu/regs.h" /*---------------------- Macros and type definitions ----------------------*/ #ifdef PACK # pragma PACK /* Don't pack structs with function pointers! */ #endif /**************************************************************************** REMARKS: Data structure containing ponters to programmed I/O functions used by the emulator. This is used so that the user program can hook all programmed I/O for the emulator to handled as necessary by the user program. By default the emulator contains simple functions that do not do access the hardware in any way. To allow the emualtor access the hardware, you will need to override the programmed I/O functions using the X86EMU_setupPioFuncs function. HEADER: x86emu.h MEMBERS: inb - Function to read a byte from an I/O port inw - Function to read a word from an I/O port inl - Function to read a dword from an I/O port outb - Function to write a byte to an I/O port outw - Function to write a word to an I/O port outl - Function to write a dword to an I/O port ****************************************************************************/ typedef struct { u8 (X86APIP inb)(X86EMU_pioAddr addr); u16 (X86APIP inw)(X86EMU_pioAddr addr); u32 (X86APIP inl)(X86EMU_pioAddr addr); void (X86APIP outb)(X86EMU_pioAddr addr, u8 val); void (X86APIP outw)(X86EMU_pioAddr addr, u16 val); void (X86APIP outl)(X86EMU_pioAddr addr, u32 val); } X86EMU_pioFuncs; /**************************************************************************** REMARKS: Data structure containing ponters to memory access functions used by the emulator. This is used so that the user program can hook all memory access functions as necessary for the emulator. By default the emulator contains simple functions that only access the internal memory of the emulator. If you need specialised functions to handle access to different types of memory (ie: hardware framebuffer accesses and BIOS memory access etc), you will need to override this using the X86EMU_setupMemFuncs function. HEADER: x86emu.h MEMBERS: rdb - Function to read a byte from an address rdw - Function to read a word from an address rdl - Function to read a dword from an address wrb - Function to write a byte to an address wrw - Function to write a word to an address wrl - Function to write a dword to an address ****************************************************************************/ typedef struct { u8 (X86APIP rdb)(u32 addr); u16 (X86APIP rdw)(u32 addr); u32 (X86APIP rdl)(u32 addr); void (X86APIP wrb)(u32 addr, u8 val); void (X86APIP wrw)(u32 addr, u16 val); void (X86APIP wrl)(u32 addr, u32 val); } X86EMU_memFuncs; /**************************************************************************** Here are the default memory read and write function in case they are needed as fallbacks. ***************************************************************************/ extern u8 X86API rdb(u32 addr); extern u16 X86API rdw(u32 addr); extern u32 X86API rdl(u32 addr); extern void X86API wrb(u32 addr, u8 val); extern void X86API wrw(u32 addr, u16 val); extern void X86API wrl(u32 addr, u32 val); #ifdef END_PACK # pragma END_PACK #endif /*--------------------- type definitions -----------------------------------*/ typedef void (X86APIP X86EMU_intrFuncs)(int num); extern X86EMU_intrFuncs _X86EMU_intrTab[256]; /*-------------------------- Function Prototypes --------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif void X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs); void X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs); void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]); void X86EMU_prepareForInt(int num); /* decode.c */ void X86EMU_exec(void); void X86EMU_halt_sys(void); #ifdef DEBUG #define HALT_SYS() \ printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \ X86EMU_halt_sys() #else #define HALT_SYS() X86EMU_halt_sys() #endif /* Debug options */ #define DEBUG_DECODE_F 0x000001 /* print decoded instruction */ #define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */ #define DEBUG_STEP_F 0x000004 #define DEBUG_DISASSEMBLE_F 0x000008 #define DEBUG_BREAK_F 0x000010 #define DEBUG_SVC_F 0x000020 #define DEBUG_SAVE_IP_CS_F 0x000040 #define DEBUG_FS_F 0x000080 #define DEBUG_PROC_F 0x000100 #define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */ #define DEBUG_TRACECALL_F 0x000400 #define DEBUG_INSTRUMENT_F 0x000800 #define DEBUG_MEM_TRACE_F 0x001000 #define DEBUG_IO_TRACE_F 0x002000 #define DEBUG_TRACECALL_REGS_F 0x004000 #define DEBUG_DECODE_NOPRINT_F 0x008000 #define DEBUG_EXIT 0x010000 #define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F) void X86EMU_trace_regs(void); void X86EMU_trace_xregs(void); void X86EMU_dump_memory(u16 seg, u16 off, u32 amt); int X86EMU_trace_on(void); int X86EMU_trace_off(void); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_X86EMU_H */ v86d-0.1.10/libs/x86emu/x86emu/000077500000000000000000000000001153201731300155755ustar00rootroot00000000000000v86d-0.1.10/libs/x86emu/x86emu/debug.h000066400000000000000000000170371153201731300170440ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for debug definitions. * ****************************************************************************/ #ifndef __X86EMU_DEBUG_H #define __X86EMU_DEBUG_H /*---------------------- Macros and type definitions ----------------------*/ /* checks to be enabled for "runtime" */ #define CHECK_IP_FETCH_F 0x1 #define CHECK_SP_ACCESS_F 0x2 #define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */ #define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset*/ #ifdef DEBUG # define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F) # define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F) # define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F) # define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F) #else # define CHECK_IP_FETCH() # define CHECK_SP_ACCESS() # define CHECK_MEM_ACCESS() # define CHECK_DATA_ACCESS() #endif #ifdef DEBUG # define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F) # define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F) # define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F) # define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F) # define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F) # define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F) # define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F) # define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_IP_CS_F) # define DEBUG_FS() (M.x86.debug & DEBUG_FS_F) # define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F) # define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F) # define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F) # define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F) # define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F) # define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F) # define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F) # define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F) #else # define DEBUG_INSTRUMENT() 0 # define DEBUG_DECODE() 0 # define DEBUG_TRACE() 0 # define DEBUG_STEP() 0 # define DEBUG_DISASSEMBLE() 0 # define DEBUG_BREAK() 0 # define DEBUG_SVC() 0 # define DEBUG_SAVE_IP_CS() 0 # define DEBUG_FS() 0 # define DEBUG_PROC() 0 # define DEBUG_SYSINT() 0 # define DEBUG_TRACECALL() 0 # define DEBUG_TRACECALLREGS() 0 # define DEBUG_SYS() 0 # define DEBUG_MEM_TRACE() 0 # define DEBUG_IO_TRACE() 0 # define DEBUG_DECODE_NOPRINT() 0 #endif #ifdef DEBUG # define DECODE_PRINTF(x) if (DEBUG_DECODE()) \ x86emu_decode_printf(x) # define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \ x86emu_decode_printf2(x,y) /* * The following allow us to look at the bytes of an instruction. The * first INCR_INSTRN_LEN, is called everytime bytes are consumed in * the decoding process. The SAVE_IP_CS is called initially when the * major opcode of the instruction is accessed. */ #define INC_DECODED_INST_LEN(x) \ if (DEBUG_DECODE()) \ x86emu_inc_decoded_inst_len(x) #define SAVE_IP_CS(x,y) \ if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \ | DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \ M.x86.saved_cs = x; \ M.x86.saved_ip = y; \ } #else # define INC_DECODED_INST_LEN(x) # define DECODE_PRINTF(x) # define DECODE_PRINTF2(x,y) # define SAVE_IP_CS(x,y) #endif #ifdef DEBUG #define TRACE_REGS() \ if (DEBUG_DISASSEMBLE()) { \ x86emu_just_disassemble(); \ goto EndOfTheInstructionProcedure; \ } \ if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs() #else # define TRACE_REGS() #endif #ifdef DEBUG # define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step() #else # define SINGLE_STEP() #endif #define TRACE_AND_STEP() \ TRACE_REGS(); \ SINGLE_STEP() #ifdef DEBUG # define START_OF_INSTR() # define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr(); # define END_OF_INSTR_NO_TRACE() x86emu_end_instr(); #else # define START_OF_INSTR() # define END_OF_INSTR() # define END_OF_INSTR_NO_TRACE() #endif #ifdef DEBUG # define CALL_TRACE(u,v,w,x,s) \ if (DEBUG_TRACECALLREGS()) \ x86emu_dump_regs(); \ if (DEBUG_TRACECALL()) \ printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x); # define RETURN_TRACE(n,u,v) \ if (DEBUG_TRACECALLREGS()) \ x86emu_dump_regs(); \ if (DEBUG_TRACECALL()) \ printk("%04x:%04x: %s\n",u,v,n); #else # define CALL_TRACE(u,v,w,x,s) # define RETURN_TRACE(n,u,v) #endif #ifdef DEBUG #define DB(x) x #else #define DB(x) #endif /*-------------------------- Function Prototypes --------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif extern void x86emu_inc_decoded_inst_len (int x); extern void x86emu_decode_printf (char *x); extern void x86emu_decode_printf2 (char *x, int y); extern void x86emu_just_disassemble (void); extern void x86emu_single_step (void); extern void x86emu_end_instr (void); extern void x86emu_dump_regs (void); extern void x86emu_dump_xregs (void); extern void x86emu_print_int_vect (u16 iv); extern void x86emu_instrument_instruction (void); extern void x86emu_check_ip_access (void); extern void x86emu_check_sp_access (void); extern void x86emu_check_mem_access (u32 p); extern void x86emu_check_data_access (uint s, uint o); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_DEBUG_H */ v86d-0.1.10/libs/x86emu/x86emu/decode.h000066400000000000000000000071171153201731300171770ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for instruction decoding logic. * ****************************************************************************/ #ifndef __X86EMU_DECODE_H #define __X86EMU_DECODE_H /*---------------------- Macros and type definitions ----------------------*/ /* Instruction Decoding Stuff */ #define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl) #define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r) #define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r) #define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r) #define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK /*-------------------------- Function Prototypes --------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif void x86emu_intr_raise (u8 type); void fetch_decode_modrm (int *mod,int *regh,int *regl); u8 fetch_byte_imm (void); u16 fetch_word_imm (void); u32 fetch_long_imm (void); u8 fetch_data_byte (uint offset); u8 fetch_data_byte_abs (uint segment, uint offset); u16 fetch_data_word (uint offset); u16 fetch_data_word_abs (uint segment, uint offset); u32 fetch_data_long (uint offset); u32 fetch_data_long_abs (uint segment, uint offset); void store_data_byte (uint offset, u8 val); void store_data_byte_abs (uint segment, uint offset, u8 val); void store_data_word (uint offset, u16 val); void store_data_word_abs (uint segment, uint offset, u16 val); void store_data_long (uint offset, u32 val); void store_data_long_abs (uint segment, uint offset, u32 val); u8* decode_rm_byte_register(int reg); u16* decode_rm_word_register(int reg); u32* decode_rm_long_register(int reg); u16* decode_rm_seg_register(int reg); u32 decode_rm00_address(int rm); u32 decode_rm01_address(int rm); u32 decode_rm10_address(int rm); u32 decode_sib_address(int sib, int mod); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_DECODE_H */ v86d-0.1.10/libs/x86emu/x86emu/fpu.h000066400000000000000000000046371153201731300165520ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for FPU instruction decoding. * ****************************************************************************/ #ifndef __X86EMU_FPU_H #define __X86EMU_FPU_H #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif /* these have to be defined, whether 8087 support compiled in or not. */ extern void x86emuOp_esc_coprocess_d8 (u8 op1); extern void x86emuOp_esc_coprocess_d9 (u8 op1); extern void x86emuOp_esc_coprocess_da (u8 op1); extern void x86emuOp_esc_coprocess_db (u8 op1); extern void x86emuOp_esc_coprocess_dc (u8 op1); extern void x86emuOp_esc_coprocess_dd (u8 op1); extern void x86emuOp_esc_coprocess_de (u8 op1); extern void x86emuOp_esc_coprocess_df (u8 op1); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_FPU_H */ v86d-0.1.10/libs/x86emu/x86emu/fpu_regs.h000066400000000000000000000074441153201731300175710ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for FPU register definitions. * ****************************************************************************/ #ifndef __X86EMU_FPU_REGS_H #define __X86EMU_FPU_REGS_H #ifdef X86_FPU_SUPPORT #ifdef PACK # pragma PACK #endif /* Basic 8087 register can hold any of the following values: */ union x86_fpu_reg_u { s8 tenbytes[10]; double dval; float fval; s16 sval; s32 lval; }; struct x86_fpu_reg { union x86_fpu_reg_u reg; char tag; }; /* * Since we are not going to worry about the problems of aliasing * registers, every time a register is modified, its result type is * set in the tag fields for that register. If some operation * attempts to access the type in a way inconsistent with its current * storage format, then we flag the operation. If common, we'll * attempt the conversion. */ #define X86_FPU_VALID 0x80 #define X86_FPU_REGTYP(r) ((r) & 0x7F) #define X86_FPU_WORD 0x0 #define X86_FPU_SHORT 0x1 #define X86_FPU_LONG 0x2 #define X86_FPU_FLOAT 0x3 #define X86_FPU_DOUBLE 0x4 #define X86_FPU_LDBL 0x5 #define X86_FPU_BSD 0x6 #define X86_FPU_STKTOP 0 struct x86_fpu_registers { struct x86_fpu_reg x86_fpu_stack[8]; int x86_fpu_flags; int x86_fpu_config; /* rounding modes, etc. */ short x86_fpu_tos, x86_fpu_bos; }; #ifdef END_PACK # pragma END_PACK #endif /* * There are two versions of the following macro. * * One version is for opcode D9, for which there are more than 32 * instructions encoded in the second byte of the opcode. * * The other version, deals with all the other 7 i87 opcodes, for * which there are only 32 strings needed to describe the * instructions. */ #endif /* X86_FPU_SUPPORT */ #ifdef DEBUG # define DECODE_PRINTINSTR32(t,mod,rh,rl) \ DECODE_PRINTF(t[(mod<<3)+(rh)]); # define DECODE_PRINTINSTR256(t,mod,rh,rl) \ DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]); #else # define DECODE_PRINTINSTR32(t,mod,rh,rl) # define DECODE_PRINTINSTR256(t,mod,rh,rl) #endif #endif /* __X86EMU_FPU_REGS_H */ v86d-0.1.10/libs/x86emu/x86emu/ops.h000066400000000000000000000035671153201731300165620ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for operand decoding functions. * ****************************************************************************/ #ifndef __X86EMU_OPS_H #define __X86EMU_OPS_H extern void (*x86emu_optab[0x100])(u8 op1); extern void (*x86emu_optab2[0x100])(u8 op2); #endif /* __X86EMU_OPS_H */ v86d-0.1.10/libs/x86emu/x86emu/prim_asm.h000066400000000000000000000714321153201731300175640ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: Watcom C++ 10.6 or later * Environment: Any * Developer: Kendall Bennett * * Description: Inline assembler versions of the primitive operand * functions for faster performance. At the moment this is * x86 inline assembler, but these functions could be replaced * with native inline assembler for each supported processor * platform. * ****************************************************************************/ #ifndef __X86EMU_PRIM_ASM_H #define __X86EMU_PRIM_ASM_H #ifdef __WATCOMC__ #ifndef VALIDATE #define __HAVE_INLINE_ASSEMBLER__ #endif u32 get_flags_asm(void); #pragma aux get_flags_asm = \ "pushf" \ "pop eax" \ value [eax] \ modify exact [eax]; u16 aaa_word_asm(u32 *flags,u16 d); #pragma aux aaa_word_asm = \ "push [edi]" \ "popf" \ "aaa" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u16 aas_word_asm(u32 *flags,u16 d); #pragma aux aas_word_asm = \ "push [edi]" \ "popf" \ "aas" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u16 aad_word_asm(u32 *flags,u16 d); #pragma aux aad_word_asm = \ "push [edi]" \ "popf" \ "aad" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u16 aam_word_asm(u32 *flags,u8 d); #pragma aux aam_word_asm = \ "push [edi]" \ "popf" \ "aam" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [ax] \ modify exact [ax]; u8 adc_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux adc_byte_asm = \ "push [edi]" \ "popf" \ "adc al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 adc_word_asm(u32 *flags,u16 d, u16 s); #pragma aux adc_word_asm = \ "push [edi]" \ "popf" \ "adc ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 adc_long_asm(u32 *flags,u32 d, u32 s); #pragma aux adc_long_asm = \ "push [edi]" \ "popf" \ "adc eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; u8 add_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux add_byte_asm = \ "push [edi]" \ "popf" \ "add al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 add_word_asm(u32 *flags,u16 d, u16 s); #pragma aux add_word_asm = \ "push [edi]" \ "popf" \ "add ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 add_long_asm(u32 *flags,u32 d, u32 s); #pragma aux add_long_asm = \ "push [edi]" \ "popf" \ "add eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; u8 and_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux and_byte_asm = \ "push [edi]" \ "popf" \ "and al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 and_word_asm(u32 *flags,u16 d, u16 s); #pragma aux and_word_asm = \ "push [edi]" \ "popf" \ "and ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 and_long_asm(u32 *flags,u32 d, u32 s); #pragma aux and_long_asm = \ "push [edi]" \ "popf" \ "and eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; u8 cmp_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux cmp_byte_asm = \ "push [edi]" \ "popf" \ "cmp al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 cmp_word_asm(u32 *flags,u16 d, u16 s); #pragma aux cmp_word_asm = \ "push [edi]" \ "popf" \ "cmp ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 cmp_long_asm(u32 *flags,u32 d, u32 s); #pragma aux cmp_long_asm = \ "push [edi]" \ "popf" \ "cmp eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; u8 daa_byte_asm(u32 *flags,u8 d); #pragma aux daa_byte_asm = \ "push [edi]" \ "popf" \ "daa" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [al] \ modify exact [al]; u8 das_byte_asm(u32 *flags,u8 d); #pragma aux das_byte_asm = \ "push [edi]" \ "popf" \ "das" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [al] \ modify exact [al]; u8 dec_byte_asm(u32 *flags,u8 d); #pragma aux dec_byte_asm = \ "push [edi]" \ "popf" \ "dec al" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [al] \ modify exact [al]; u16 dec_word_asm(u32 *flags,u16 d); #pragma aux dec_word_asm = \ "push [edi]" \ "popf" \ "dec ax" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u32 dec_long_asm(u32 *flags,u32 d); #pragma aux dec_long_asm = \ "push [edi]" \ "popf" \ "dec eax" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] \ value [eax] \ modify exact [eax]; u8 inc_byte_asm(u32 *flags,u8 d); #pragma aux inc_byte_asm = \ "push [edi]" \ "popf" \ "inc al" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [al] \ modify exact [al]; u16 inc_word_asm(u32 *flags,u16 d); #pragma aux inc_word_asm = \ "push [edi]" \ "popf" \ "inc ax" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u32 inc_long_asm(u32 *flags,u32 d); #pragma aux inc_long_asm = \ "push [edi]" \ "popf" \ "inc eax" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] \ value [eax] \ modify exact [eax]; u8 or_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux or_byte_asm = \ "push [edi]" \ "popf" \ "or al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 or_word_asm(u32 *flags,u16 d, u16 s); #pragma aux or_word_asm = \ "push [edi]" \ "popf" \ "or ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 or_long_asm(u32 *flags,u32 d, u32 s); #pragma aux or_long_asm = \ "push [edi]" \ "popf" \ "or eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; u8 neg_byte_asm(u32 *flags,u8 d); #pragma aux neg_byte_asm = \ "push [edi]" \ "popf" \ "neg al" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [al] \ modify exact [al]; u16 neg_word_asm(u32 *flags,u16 d); #pragma aux neg_word_asm = \ "push [edi]" \ "popf" \ "neg ax" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u32 neg_long_asm(u32 *flags,u32 d); #pragma aux neg_long_asm = \ "push [edi]" \ "popf" \ "neg eax" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] \ value [eax] \ modify exact [eax]; u8 not_byte_asm(u32 *flags,u8 d); #pragma aux not_byte_asm = \ "push [edi]" \ "popf" \ "not al" \ "pushf" \ "pop [edi]" \ parm [edi] [al] \ value [al] \ modify exact [al]; u16 not_word_asm(u32 *flags,u16 d); #pragma aux not_word_asm = \ "push [edi]" \ "popf" \ "not ax" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] \ value [ax] \ modify exact [ax]; u32 not_long_asm(u32 *flags,u32 d); #pragma aux not_long_asm = \ "push [edi]" \ "popf" \ "not eax" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] \ value [eax] \ modify exact [eax]; u8 rcl_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux rcl_byte_asm = \ "push [edi]" \ "popf" \ "rcl al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 rcl_word_asm(u32 *flags,u16 d, u8 s); #pragma aux rcl_word_asm = \ "push [edi]" \ "popf" \ "rcl ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 rcl_long_asm(u32 *flags,u32 d, u8 s); #pragma aux rcl_long_asm = \ "push [edi]" \ "popf" \ "rcl eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u8 rcr_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux rcr_byte_asm = \ "push [edi]" \ "popf" \ "rcr al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 rcr_word_asm(u32 *flags,u16 d, u8 s); #pragma aux rcr_word_asm = \ "push [edi]" \ "popf" \ "rcr ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 rcr_long_asm(u32 *flags,u32 d, u8 s); #pragma aux rcr_long_asm = \ "push [edi]" \ "popf" \ "rcr eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u8 rol_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux rol_byte_asm = \ "push [edi]" \ "popf" \ "rol al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 rol_word_asm(u32 *flags,u16 d, u8 s); #pragma aux rol_word_asm = \ "push [edi]" \ "popf" \ "rol ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 rol_long_asm(u32 *flags,u32 d, u8 s); #pragma aux rol_long_asm = \ "push [edi]" \ "popf" \ "rol eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u8 ror_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux ror_byte_asm = \ "push [edi]" \ "popf" \ "ror al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 ror_word_asm(u32 *flags,u16 d, u8 s); #pragma aux ror_word_asm = \ "push [edi]" \ "popf" \ "ror ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 ror_long_asm(u32 *flags,u32 d, u8 s); #pragma aux ror_long_asm = \ "push [edi]" \ "popf" \ "ror eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u8 shl_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux shl_byte_asm = \ "push [edi]" \ "popf" \ "shl al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 shl_word_asm(u32 *flags,u16 d, u8 s); #pragma aux shl_word_asm = \ "push [edi]" \ "popf" \ "shl ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 shl_long_asm(u32 *flags,u32 d, u8 s); #pragma aux shl_long_asm = \ "push [edi]" \ "popf" \ "shl eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u8 shr_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux shr_byte_asm = \ "push [edi]" \ "popf" \ "shr al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 shr_word_asm(u32 *flags,u16 d, u8 s); #pragma aux shr_word_asm = \ "push [edi]" \ "popf" \ "shr ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 shr_long_asm(u32 *flags,u32 d, u8 s); #pragma aux shr_long_asm = \ "push [edi]" \ "popf" \ "shr eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u8 sar_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux sar_byte_asm = \ "push [edi]" \ "popf" \ "sar al,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [cl] \ value [al] \ modify exact [al cl]; u16 sar_word_asm(u32 *flags,u16 d, u8 s); #pragma aux sar_word_asm = \ "push [edi]" \ "popf" \ "sar ax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [cl] \ value [ax] \ modify exact [ax cl]; u32 sar_long_asm(u32 *flags,u32 d, u8 s); #pragma aux sar_long_asm = \ "push [edi]" \ "popf" \ "sar eax,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [cl] \ value [eax] \ modify exact [eax cl]; u16 shld_word_asm(u32 *flags,u16 d, u16 fill, u8 s); #pragma aux shld_word_asm = \ "push [edi]" \ "popf" \ "shld ax,dx,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [dx] [cl] \ value [ax] \ modify exact [ax dx cl]; u32 shld_long_asm(u32 *flags,u32 d, u32 fill, u8 s); #pragma aux shld_long_asm = \ "push [edi]" \ "popf" \ "shld eax,edx,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [edx] [cl] \ value [eax] \ modify exact [eax edx cl]; u16 shrd_word_asm(u32 *flags,u16 d, u16 fill, u8 s); #pragma aux shrd_word_asm = \ "push [edi]" \ "popf" \ "shrd ax,dx,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [dx] [cl] \ value [ax] \ modify exact [ax dx cl]; u32 shrd_long_asm(u32 *flags,u32 d, u32 fill, u8 s); #pragma aux shrd_long_asm = \ "push [edi]" \ "popf" \ "shrd eax,edx,cl" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [edx] [cl] \ value [eax] \ modify exact [eax edx cl]; u8 sbb_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux sbb_byte_asm = \ "push [edi]" \ "popf" \ "sbb al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 sbb_word_asm(u32 *flags,u16 d, u16 s); #pragma aux sbb_word_asm = \ "push [edi]" \ "popf" \ "sbb ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 sbb_long_asm(u32 *flags,u32 d, u32 s); #pragma aux sbb_long_asm = \ "push [edi]" \ "popf" \ "sbb eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; u8 sub_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux sub_byte_asm = \ "push [edi]" \ "popf" \ "sub al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 sub_word_asm(u32 *flags,u16 d, u16 s); #pragma aux sub_word_asm = \ "push [edi]" \ "popf" \ "sub ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 sub_long_asm(u32 *flags,u32 d, u32 s); #pragma aux sub_long_asm = \ "push [edi]" \ "popf" \ "sub eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; void test_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux test_byte_asm = \ "push [edi]" \ "popf" \ "test al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ modify exact [al bl]; void test_word_asm(u32 *flags,u16 d, u16 s); #pragma aux test_word_asm = \ "push [edi]" \ "popf" \ "test ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ modify exact [ax bx]; void test_long_asm(u32 *flags,u32 d, u32 s); #pragma aux test_long_asm = \ "push [edi]" \ "popf" \ "test eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ modify exact [eax ebx]; u8 xor_byte_asm(u32 *flags,u8 d, u8 s); #pragma aux xor_byte_asm = \ "push [edi]" \ "popf" \ "xor al,bl" \ "pushf" \ "pop [edi]" \ parm [edi] [al] [bl] \ value [al] \ modify exact [al bl]; u16 xor_word_asm(u32 *flags,u16 d, u16 s); #pragma aux xor_word_asm = \ "push [edi]" \ "popf" \ "xor ax,bx" \ "pushf" \ "pop [edi]" \ parm [edi] [ax] [bx] \ value [ax] \ modify exact [ax bx]; u32 xor_long_asm(u32 *flags,u32 d, u32 s); #pragma aux xor_long_asm = \ "push [edi]" \ "popf" \ "xor eax,ebx" \ "pushf" \ "pop [edi]" \ parm [edi] [eax] [ebx] \ value [eax] \ modify exact [eax ebx]; void imul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s); #pragma aux imul_byte_asm = \ "push [edi]" \ "popf" \ "imul bl" \ "pushf" \ "pop [edi]" \ "mov [esi],ax" \ parm [edi] [esi] [al] [bl] \ modify exact [esi ax bl]; void imul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s); #pragma aux imul_word_asm = \ "push [edi]" \ "popf" \ "imul bx" \ "pushf" \ "pop [edi]" \ "mov [esi],ax" \ "mov [ecx],dx" \ parm [edi] [esi] [ecx] [ax] [bx]\ modify exact [esi edi ax bx dx]; void imul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s); #pragma aux imul_long_asm = \ "push [edi]" \ "popf" \ "imul ebx" \ "pushf" \ "pop [edi]" \ "mov [esi],eax" \ "mov [ecx],edx" \ parm [edi] [esi] [ecx] [eax] [ebx] \ modify exact [esi edi eax ebx edx]; void mul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s); #pragma aux mul_byte_asm = \ "push [edi]" \ "popf" \ "mul bl" \ "pushf" \ "pop [edi]" \ "mov [esi],ax" \ parm [edi] [esi] [al] [bl] \ modify exact [esi ax bl]; void mul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s); #pragma aux mul_word_asm = \ "push [edi]" \ "popf" \ "mul bx" \ "pushf" \ "pop [edi]" \ "mov [esi],ax" \ "mov [ecx],dx" \ parm [edi] [esi] [ecx] [ax] [bx]\ modify exact [esi edi ax bx dx]; void mul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s); #pragma aux mul_long_asm = \ "push [edi]" \ "popf" \ "mul ebx" \ "pushf" \ "pop [edi]" \ "mov [esi],eax" \ "mov [ecx],edx" \ parm [edi] [esi] [ecx] [eax] [ebx] \ modify exact [esi edi eax ebx edx]; void idiv_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s); #pragma aux idiv_byte_asm = \ "push [edi]" \ "popf" \ "idiv bl" \ "pushf" \ "pop [edi]" \ "mov [esi],al" \ "mov [ecx],ah" \ parm [edi] [esi] [ecx] [ax] [bl]\ modify exact [esi edi ax bl]; void idiv_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s); #pragma aux idiv_word_asm = \ "push [edi]" \ "popf" \ "idiv bx" \ "pushf" \ "pop [edi]" \ "mov [esi],ax" \ "mov [ecx],dx" \ parm [edi] [esi] [ecx] [ax] [dx] [bx]\ modify exact [esi edi ax dx bx]; void idiv_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s); #pragma aux idiv_long_asm = \ "push [edi]" \ "popf" \ "idiv ebx" \ "pushf" \ "pop [edi]" \ "mov [esi],eax" \ "mov [ecx],edx" \ parm [edi] [esi] [ecx] [eax] [edx] [ebx]\ modify exact [esi edi eax edx ebx]; void div_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s); #pragma aux div_byte_asm = \ "push [edi]" \ "popf" \ "div bl" \ "pushf" \ "pop [edi]" \ "mov [esi],al" \ "mov [ecx],ah" \ parm [edi] [esi] [ecx] [ax] [bl]\ modify exact [esi edi ax bl]; void div_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s); #pragma aux div_word_asm = \ "push [edi]" \ "popf" \ "div bx" \ "pushf" \ "pop [edi]" \ "mov [esi],ax" \ "mov [ecx],dx" \ parm [edi] [esi] [ecx] [ax] [dx] [bx]\ modify exact [esi edi ax dx bx]; void div_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s); #pragma aux div_long_asm = \ "push [edi]" \ "popf" \ "div ebx" \ "pushf" \ "pop [edi]" \ "mov [esi],eax" \ "mov [ecx],edx" \ parm [edi] [esi] [ecx] [eax] [edx] [ebx]\ modify exact [esi edi eax edx ebx]; #endif #endif /* __X86EMU_PRIM_ASM_H */ v86d-0.1.10/libs/x86emu/x86emu/prim_ops.h000066400000000000000000000112271153201731300176010ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for primitive operation functions. * ****************************************************************************/ #ifndef __X86EMU_PRIM_OPS_H #define __X86EMU_PRIM_OPS_H #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif u16 aaa_word (u16 d); u16 aas_word (u16 d); u16 aad_word (u16 d); u16 aam_word (u8 d); u8 adc_byte (u8 d, u8 s); u16 adc_word (u16 d, u16 s); u32 adc_long (u32 d, u32 s); u8 add_byte (u8 d, u8 s); u16 add_word (u16 d, u16 s); u32 add_long (u32 d, u32 s); u8 and_byte (u8 d, u8 s); u16 and_word (u16 d, u16 s); u32 and_long (u32 d, u32 s); u8 cmp_byte (u8 d, u8 s); u16 cmp_word (u16 d, u16 s); u32 cmp_long (u32 d, u32 s); u8 daa_byte (u8 d); u8 das_byte (u8 d); u8 dec_byte (u8 d); u16 dec_word (u16 d); u32 dec_long (u32 d); u8 inc_byte (u8 d); u16 inc_word (u16 d); u32 inc_long (u32 d); u8 or_byte (u8 d, u8 s); u16 or_word (u16 d, u16 s); u32 or_long (u32 d, u32 s); u8 neg_byte (u8 s); u16 neg_word (u16 s); u32 neg_long (u32 s); u8 not_byte (u8 s); u16 not_word (u16 s); u32 not_long (u32 s); u8 rcl_byte (u8 d, u8 s); u16 rcl_word (u16 d, u8 s); u32 rcl_long (u32 d, u8 s); u8 rcr_byte (u8 d, u8 s); u16 rcr_word (u16 d, u8 s); u32 rcr_long (u32 d, u8 s); u8 rol_byte (u8 d, u8 s); u16 rol_word (u16 d, u8 s); u32 rol_long (u32 d, u8 s); u8 ror_byte (u8 d, u8 s); u16 ror_word (u16 d, u8 s); u32 ror_long (u32 d, u8 s); u8 shl_byte (u8 d, u8 s); u16 shl_word (u16 d, u8 s); u32 shl_long (u32 d, u8 s); u8 shr_byte (u8 d, u8 s); u16 shr_word (u16 d, u8 s); u32 shr_long (u32 d, u8 s); u8 sar_byte (u8 d, u8 s); u16 sar_word (u16 d, u8 s); u32 sar_long (u32 d, u8 s); u16 shld_word (u16 d, u16 fill, u8 s); u32 shld_long (u32 d, u32 fill, u8 s); u16 shrd_word (u16 d, u16 fill, u8 s); u32 shrd_long (u32 d, u32 fill, u8 s); u8 sbb_byte (u8 d, u8 s); u16 sbb_word (u16 d, u16 s); u32 sbb_long (u32 d, u32 s); u8 sub_byte (u8 d, u8 s); u16 sub_word (u16 d, u16 s); u32 sub_long (u32 d, u32 s); void test_byte (u8 d, u8 s); void test_word (u16 d, u16 s); void test_long (u32 d, u32 s); u8 xor_byte (u8 d, u8 s); u16 xor_word (u16 d, u16 s); u32 xor_long (u32 d, u32 s); void imul_byte (u8 s); void imul_word (u16 s); void imul_long (u32 s); void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s); void mul_byte (u8 s); void mul_word (u16 s); void mul_long (u32 s); void idiv_byte (u8 s); void idiv_word (u16 s); void idiv_long (u32 s); void div_byte (u8 s); void div_word (u16 s); void div_long (u32 s); void ins (int size); void outs (int size); u16 mem_access_word (int addr); void push_word (u16 w); void push_long (u32 w); u16 pop_word (void); u32 pop_long (void); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_PRIM_OPS_H */ v86d-0.1.10/libs/x86emu/x86emu/regs.h000066400000000000000000000242661153201731300167200ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for x86 register definitions. * ****************************************************************************/ #ifndef __X86EMU_REGS_H #define __X86EMU_REGS_H /*---------------------- Macros and type definitions ----------------------*/ #ifdef PACK # pragma PACK #endif /* * General EAX, EBX, ECX, EDX type registers. Note that for * portability, and speed, the issue of byte swapping is not addressed * in the registers. All registers are stored in the default format * available on the host machine. The only critical issue is that the * registers should line up EXACTLY in the same manner as they do in * the 386. That is: * * EAX & 0xff === AL * EAX & 0xffff == AX * * etc. The result is that alot of the calculations can then be * done using the native instruction set fully. */ #ifdef __BIG_ENDIAN__ typedef struct { u32 e_reg; } I32_reg_t; typedef struct { u16 filler0, x_reg; } I16_reg_t; typedef struct { u8 filler0, filler1, h_reg, l_reg; } I8_reg_t; #else /* !__BIG_ENDIAN__ */ typedef struct { u32 e_reg; } I32_reg_t; typedef struct { u16 x_reg; } I16_reg_t; typedef struct { u8 l_reg, h_reg; } I8_reg_t; #endif /* BIG_ENDIAN */ typedef union { I32_reg_t I32_reg; I16_reg_t I16_reg; I8_reg_t I8_reg; } i386_general_register; struct i386_general_regs { i386_general_register A, B, C, D; }; typedef struct i386_general_regs Gen_reg_t; struct i386_special_regs { i386_general_register SP, BP, SI, DI, IP; u32 FLAGS; }; /* * Segment registers here represent the 16 bit quantities * CS, DS, ES, SS. */ struct i386_segment_regs { u16 CS, DS, SS, ES, FS, GS; }; /* 8 bit registers */ #define R_AH gen.A.I8_reg.h_reg #define R_AL gen.A.I8_reg.l_reg #define R_BH gen.B.I8_reg.h_reg #define R_BL gen.B.I8_reg.l_reg #define R_CH gen.C.I8_reg.h_reg #define R_CL gen.C.I8_reg.l_reg #define R_DH gen.D.I8_reg.h_reg #define R_DL gen.D.I8_reg.l_reg /* 16 bit registers */ #define R_AX gen.A.I16_reg.x_reg #define R_BX gen.B.I16_reg.x_reg #define R_CX gen.C.I16_reg.x_reg #define R_DX gen.D.I16_reg.x_reg /* 32 bit extended registers */ #define R_EAX gen.A.I32_reg.e_reg #define R_EBX gen.B.I32_reg.e_reg #define R_ECX gen.C.I32_reg.e_reg #define R_EDX gen.D.I32_reg.e_reg /* special registers */ #define R_SP spc.SP.I16_reg.x_reg #define R_BP spc.BP.I16_reg.x_reg #define R_SI spc.SI.I16_reg.x_reg #define R_DI spc.DI.I16_reg.x_reg #define R_IP spc.IP.I16_reg.x_reg #define R_FLG spc.FLAGS /* special registers */ #define R_SP spc.SP.I16_reg.x_reg #define R_BP spc.BP.I16_reg.x_reg #define R_SI spc.SI.I16_reg.x_reg #define R_DI spc.DI.I16_reg.x_reg #define R_IP spc.IP.I16_reg.x_reg #define R_FLG spc.FLAGS /* special registers */ #define R_ESP spc.SP.I32_reg.e_reg #define R_EBP spc.BP.I32_reg.e_reg #define R_ESI spc.SI.I32_reg.e_reg #define R_EDI spc.DI.I32_reg.e_reg #define R_EIP spc.IP.I32_reg.e_reg #define R_EFLG spc.FLAGS /* segment registers */ #define R_CS seg.CS #define R_DS seg.DS #define R_SS seg.SS #define R_ES seg.ES #define R_FS seg.FS #define R_GS seg.GS /* flag conditions */ #define FB_CF 0x0001 /* CARRY flag */ #define FB_PF 0x0004 /* PARITY flag */ #define FB_AF 0x0010 /* AUX flag */ #define FB_ZF 0x0040 /* ZERO flag */ #define FB_SF 0x0080 /* SIGN flag */ #define FB_TF 0x0100 /* TRAP flag */ #define FB_IF 0x0200 /* INTERRUPT ENABLE flag */ #define FB_DF 0x0400 /* DIR flag */ #define FB_OF 0x0800 /* OVERFLOW flag */ /* 80286 and above always have bit#1 set */ #define F_ALWAYS_ON (0x0002) /* flag bits always on */ /* * Define a mask for only those flag bits we will ever pass back * (via PUSHF) */ #define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF) /* following bits masked in to a 16bit quantity */ #define F_CF 0x0001 /* CARRY flag */ #define F_PF 0x0004 /* PARITY flag */ #define F_AF 0x0010 /* AUX flag */ #define F_ZF 0x0040 /* ZERO flag */ #define F_SF 0x0080 /* SIGN flag */ #define F_TF 0x0100 /* TRAP flag */ #define F_IF 0x0200 /* INTERRUPT ENABLE flag */ #define F_DF 0x0400 /* DIR flag */ #define F_OF 0x0800 /* OVERFLOW flag */ #define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag)) #define SET_FLAG(flag) (M.x86.R_FLG |= (flag)) #define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag)) #define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag)) #define CLEARALL_FLAG(m) (M.x86.R_FLG = 0) #define CONDITIONAL_SET_FLAG(COND,FLAG) \ if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG) #define F_PF_CALC 0x010000 /* PARITY flag has been calced */ #define F_ZF_CALC 0x020000 /* ZERO flag has been calced */ #define F_SF_CALC 0x040000 /* SIGN flag has been calced */ #define F_ALL_CALC 0xff0000 /* All have been calced */ /* * Emulator machine state. * Segment usage control. */ #define SYSMODE_SEG_DS_SS 0x00000001 #define SYSMODE_SEGOVR_CS 0x00000002 #define SYSMODE_SEGOVR_DS 0x00000004 #define SYSMODE_SEGOVR_ES 0x00000008 #define SYSMODE_SEGOVR_FS 0x00000010 #define SYSMODE_SEGOVR_GS 0x00000020 #define SYSMODE_SEGOVR_SS 0x00000040 #define SYSMODE_PREFIX_REPE 0x00000080 #define SYSMODE_PREFIX_REPNE 0x00000100 #define SYSMODE_PREFIX_DATA 0x00000200 #define SYSMODE_PREFIX_ADDR 0x00000400 #define SYSMODE_INTR_PENDING 0x10000000 #define SYSMODE_EXTRN_INTR 0x20000000 #define SYSMODE_HALTED 0x40000000 #define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \ SYSMODE_SEGOVR_CS | \ SYSMODE_SEGOVR_DS | \ SYSMODE_SEGOVR_ES | \ SYSMODE_SEGOVR_FS | \ SYSMODE_SEGOVR_GS | \ SYSMODE_SEGOVR_SS) #define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \ SYSMODE_SEGOVR_CS | \ SYSMODE_SEGOVR_DS | \ SYSMODE_SEGOVR_ES | \ SYSMODE_SEGOVR_FS | \ SYSMODE_SEGOVR_GS | \ SYSMODE_SEGOVR_SS | \ SYSMODE_PREFIX_DATA | \ SYSMODE_PREFIX_ADDR) #define INTR_SYNCH 0x1 #define INTR_ASYNCH 0x2 #define INTR_HALTED 0x4 typedef struct { struct i386_general_regs gen; struct i386_special_regs spc; struct i386_segment_regs seg; /* * MODE contains information on: * REPE prefix 2 bits repe,repne * SEGMENT overrides 5 bits normal,DS,SS,CS,ES * Delayed flag set 3 bits (zero, signed, parity) * reserved 6 bits * interrupt # 8 bits instruction raised interrupt * BIOS video segregs 4 bits * Interrupt Pending 1 bits * Extern interrupt 1 bits * Halted 1 bits */ u32 mode; volatile int intr; /* mask of pending interrupts */ int debug; #ifdef DEBUG int check; u16 saved_ip; u16 saved_cs; int enc_pos; int enc_str_pos; char decode_buf[32]; /* encoded byte stream */ char decoded_buf[256]; /* disassembled strings */ #endif u8 intno; u8 __pad[3]; } X86EMU_regs; /**************************************************************************** REMARKS: Structure maintaining the emulator machine state. MEMBERS: mem_base - Base real mode memory for the emulator mem_size - Size of the real mode memory block for the emulator private - private data pointer x86 - X86 registers ****************************************************************************/ typedef struct { unsigned long mem_base; unsigned long mem_size; void* private; X86EMU_regs x86; } X86EMU_sysEnv; #ifdef END_PACK # pragma END_PACK #endif /*----------------------------- Global Variables --------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif /* Global emulator machine state. * * We keep it global to avoid pointer dereferences in the code for speed. */ extern X86EMU_sysEnv _X86EMU_env; #define M _X86EMU_env /*-------------------------- Function Prototypes --------------------------*/ /* Function to log information at runtime */ void printk(const char *fmt, ...); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_REGS_H */ v86d-0.1.10/libs/x86emu/x86emu/types.h000066400000000000000000000062211153201731300171130ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for x86 emulator type definitions. * ****************************************************************************/ #ifndef __X86EMU_TYPES_H #define __X86EMU_TYPES_H #ifndef NO_SYS_HEADERS #include #endif /* * The following kludge is an attempt to work around typedef conflicts with * . */ #define u8 x86emuu8 #define u16 x86emuu16 #define u32 x86emuu32 #define u64 x86emuu64 #define s8 x86emus8 #define s16 x86emus16 #define s32 x86emus32 #define s64 x86emus64 #define uint x86emuuint #define sint x86emusint /*---------------------- Macros and type definitions ----------------------*/ /* Currently only for Linux/32bit */ #undef __HAS_LONG_LONG__ #if defined(__GNUC__) && !defined(NO_LONG_LONG) #define __HAS_LONG_LONG__ #endif /* Taken from Xmd.h */ #undef NUM32 #if defined (_LP64) || \ defined(__alpha) || defined(__alpha__) || \ defined(__ia64__) || defined(ia64) || \ defined(__sparc64__) || \ defined(__s390x__) || \ (defined(__hppa__) && defined(__LP64)) || \ defined(__amd64__) || defined(amd64) || \ (defined(__sgi) && (_MIPS_SZLONG == 64)) #define NUM32 int #else #define NUM32 long #endif typedef unsigned char u8; typedef unsigned short u16; typedef unsigned NUM32 u32; #ifdef __HAS_LONG_LONG__ typedef unsigned long long u64; #endif typedef char s8; typedef short s16; typedef NUM32 s32; #ifdef __HAS_LONG_LONG__ typedef long long s64; #endif typedef unsigned int uint; typedef int sint; typedef u16 X86EMU_pioAddr; #undef NUM32 #endif /* __X86EMU_TYPES_H */ v86d-0.1.10/libs/x86emu/x86emu/x86emui.h000066400000000000000000000071011153201731300172520ustar00rootroot00000000000000/**************************************************************************** * * Realmode X86 Emulator Library * * Copyright (C) 1996-1999 SciTech Software, Inc. * Copyright (C) David Mosberger-Tang * Copyright (C) 1999 Egbert Eich * * ======================================================================== * * 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. * * ======================================================================== * * Language: ANSI C * Environment: Any * Developer: Kendall Bennett * * Description: Header file for system specific functions. These functions * are always compiled and linked in the OS depedent libraries, * and never in a binary portable driver. * ****************************************************************************/ #ifndef __X86EMU_X86EMUI_H #define __X86EMU_X86EMUI_H /* If we are compiling in C++ mode, we can compile some functions as * inline to increase performance (however the code size increases quite * dramatically in this case). */ #if defined(__cplusplus) && !defined(_NO_INLINE) #define _INLINE inline #else #define _INLINE static #endif /* Get rid of unused parameters in C++ compilation mode */ #ifdef __cplusplus #define X86EMU_UNUSED(v) #else #define X86EMU_UNUSED(v) v #endif #include "x86emu.h" #include "x86emu/regs.h" #include "x86emu/debug.h" #include "x86emu/decode.h" #include "x86emu/ops.h" #include "x86emu/prim_ops.h" #include "x86emu/fpu.h" #include "x86emu/fpu_regs.h" #ifndef NO_SYS_HEADERS #include #include #include #endif /*--------------------------- Inline Functions ----------------------------*/ #ifdef __cplusplus extern "C" { /* Use "C" linkage when in C++ mode */ #endif extern u8 (X86APIP sys_rdb)(u32 addr); extern u16 (X86APIP sys_rdw)(u32 addr); extern u32 (X86APIP sys_rdl)(u32 addr); extern void (X86APIP sys_wrb)(u32 addr,u8 val); extern void (X86APIP sys_wrw)(u32 addr,u16 val); extern void (X86APIP sys_wrl)(u32 addr,u32 val); extern u8 (X86APIP sys_inb)(X86EMU_pioAddr addr); extern u16 (X86APIP sys_inw)(X86EMU_pioAddr addr); extern u32 (X86APIP sys_inl)(X86EMU_pioAddr addr); extern void (X86APIP sys_outb)(X86EMU_pioAddr addr,u8 val); extern void (X86APIP sys_outw)(X86EMU_pioAddr addr,u16 val); extern void (X86APIP sys_outl)(X86EMU_pioAddr addr,u32 val); #ifdef __cplusplus } /* End of "C" linkage for C++ */ #endif #endif /* __X86EMU_X86EMUI_H */ v86d-0.1.10/misc/000077500000000000000000000000001153201731300133075ustar00rootroot00000000000000v86d-0.1.10/misc/initramfs000066400000000000000000000003231153201731300152240ustar00rootroot00000000000000dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 nod /dev/tty1 0600 0 0 c 4 1 nod /dev/zero 0600 0 0 c 1 5 nod /dev/mem 0600 0 0 c 1 1 dir /root 0700 0 0 dir /sbin 0755 0 0 file /sbin/v86d /sbin/v86d 0755 0 0 v86d-0.1.10/testvbe.c000066400000000000000000000033411153201731300141750ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "v86.h" #include "testvbe.h" #define reg16(reg) (reg & 0xffff) #define failed(tsk) (reg16(tsk.regs.eax) != 0x004f) int main(int argc, char *argv[]) { struct uvesafb_task tsk; struct vbe_ib ib; u16 *s; u8 *t; if (v86_init()) return -1; memset(&tsk, 0, sizeof(tsk)); tsk.regs.eax = 0x4f00; tsk.flags = TF_VBEIB; tsk.buf_len = sizeof(ib); strncpy((char*)&ib.vbe_signature, "VBE2", 4); if (v86_task(&tsk, (u8*)&ib)) return -1; if (failed(tsk)) { fprintf(stderr, "Getting VBE Info Block failed with eax = %.4x\n", reg16(tsk.regs.eax)); return -1; } t = (u8*)&ib; printf("VBE Version: %x.%.2x\n", ((ib.vbe_version & 0xf00) >> 8), (ib.vbe_version & 0xff)); printf("OEM String: %s\n", ib.oem_string_ptr + t); printf("OEM Vendor Name: %s\n", ib.oem_vendor_name_ptr + t); printf("OEM Prod. Name: %s\n", ib.oem_product_name_ptr + t); printf("OEM Prod. Rev: %s\n", ib.oem_product_rev_ptr + t); printf("\n%-6s %-6s mode\n", "ID", "attr"); printf("---------------------------\n"); for (s = t + ib.mode_list_ptr; *s != 0xffff; s++) { struct vbe_mode_ib mib; memset(&tsk, 0, sizeof(tsk)); tsk.regs.eax = 0x4f01; tsk.regs.ecx = *s; tsk.flags = TF_BUF_RET | TF_BUF_ESDI; tsk.buf_len = sizeof(mib); if (v86_task(&tsk, (u8*)&mib)) return -1; if (failed(tsk)) { fprintf(stderr, "Getting Mode Info Block for mode %.4x " "failed with eax = %.4x\n", *s, reg16(tsk.regs.eax)); return -1; } printf("%-6.4x %-6.4x %dx%d-%d %x\n", *s, mib.mode_attr, mib.x_res, mib.y_res, mib.bits_per_pixel, mib.phys_base_ptr); } v86_cleanup(); return 0; } v86d-0.1.10/testvbe.h000066400000000000000000000026371153201731300142110ustar00rootroot00000000000000#ifndef __H_TESTVBE #define __H_TESTVBE #define VBE_MODE_VGACOMPAT 0x20 #define VBE_MODE_COLOR 0x08 #define VBE_MODE_SUPPORTEDHW 0x01 #define VBE_MODE_GRAPHICS 0x10 #define VBE_MODE_LFB 0x80 #define VBE_MODE_MASK (VBE_MODE_COLOR | VBE_MODE_SUPPORTEDHW | \ VBE_MODE_GRAPHICS | VBE_MODE_LFB) /* VBE Mode Info Block */ struct vbe_mode_ib { /* for all VBE revisions */ u16 mode_attr; u8 winA_attr; u8 winB_attr; u16 win_granularity; u16 win_size; u16 winA_seg; u16 winB_seg; u32 win_func_ptr; u16 bytes_per_scan_line; /* for VBE 1.2+ */ u16 x_res; u16 y_res; u8 x_char_size; u8 y_char_size; u8 planes; u8 bits_per_pixel; u8 banks; u8 memory_model; u8 bank_size; u8 image_pages; u8 reserved1; /* Direct color fields for direct/6 and YUV/7 memory models. */ /* Offsets are bit positions of lsb in the mask. */ u8 red_len; u8 red_off; u8 green_len; u8 green_off; u8 blue_len; u8 blue_off; u8 rsvd_len; u8 rsvd_off; u8 direct_color_info; /* direct color mode attributes */ /* for VBE 2.0+ */ u32 phys_base_ptr; u8 reserved2[6]; /* for VBE 3.0+ */ u16 lin_bytes_per_scan_line; u8 bnk_image_pages; u8 lin_image_pages; u8 lin_red_len; u8 lin_red_off; u8 lin_green_len; u8 lin_green_off; u8 lin_blue_len; u8 lin_blue_off; u8 lin_rsvd_len; u8 lin_rsvd_off; u32 max_pixel_clock; u16 mode_id; u8 depth; } __attribute__ ((packed)); #endif /* __H_TESTVBE */ v86d-0.1.10/v86.c000066400000000000000000000053101153201731300131420ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include "v86.h" static int need_exit; static __u32 seq; static int netlink_send(int s, struct cn_msg *msg) { struct nlmsghdr *nlh; unsigned int size; int err; char buf[CONNECTOR_MAX_MSG_SIZE]; struct cn_msg *m; size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); nlh = (struct nlmsghdr *)buf; nlh->nlmsg_seq = seq++; nlh->nlmsg_pid = getpid(); nlh->nlmsg_type = NLMSG_DONE; nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); nlh->nlmsg_flags = 0; m = NLMSG_DATA(nlh); memcpy(m, msg, sizeof(*m) + msg->len); err = send(s, nlh, size, 0); if (err == -1) ulog(LOG_ERR, "Failed to send: %s [%d].\n", strerror(errno), errno); return err; } int req_exec(int s, struct cn_msg *msg) { struct uvesafb_task *tsk = (struct uvesafb_task*)(msg + 1); u8 *buf = (u8*)tsk + sizeof(struct uvesafb_task); if (tsk->flags & TF_EXIT) return 1; if (v86_task(tsk, buf)) return 2; netlink_send(s, msg); return 0; } int main(int argc, char *argv[]) { char buf[CONNECTOR_MAX_MSG_SIZE]; int len, i, err = 0, s; struct nlmsghdr *reply; struct sockaddr_nl l_local; struct cn_msg *data; struct pollfd pfd; s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (s == -1) { perror("socket"); return -1; } l_local.nl_family = AF_NETLINK; l_local.nl_groups = 1 << (CN_IDX_V86D-1); /* bitmask of requested groups */ l_local.nl_pid = 0; if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { perror("bind"); close(s); return -1; } i = fork(); if (i) { exit(0); } setsid(); chdir("/"); openlog("v86d", 0, LOG_KERN); if (v86_init()) return -1; memset(buf, 0, sizeof(buf)); pfd.fd = s; while (!need_exit) { pfd.events = POLLIN; pfd.revents = 0; switch (poll(&pfd, 1, -1)) { case 0: need_exit = 1; continue; case -1: if (errno != EINTR) { need_exit = 1; break; } continue; } memset(buf, 0, sizeof(buf)); len = recv(s, buf, sizeof(buf), 0); if (len == -1) { perror("recv buf"); err = -1; goto out; } reply = (struct nlmsghdr *)buf; /* Ignore requests coming from outside the kernel. */ if (reply->nlmsg_pid != 0) { continue; } switch (reply->nlmsg_type) { case NLMSG_ERROR: ulog(LOG_ERR, "Error message received.\n"); break; case NLMSG_DONE: data = (struct cn_msg *)NLMSG_DATA(reply); if (req_exec(s, data)) goto out; break; default: break; } } out: v86_cleanup(); closelog(); close(s); return err; } v86d-0.1.10/v86.h000066400000000000000000000030241153201731300131470ustar00rootroot00000000000000#ifndef __H_V86 #define __H_V86 #include #include #include #include #include "config.h" #undef u8 #undef u16 #undef u32 #undef u64 #define u8 __u8 #define u16 __u16 #define u32 __u32 #define u64 __u64 struct completion; #include