diff --git a/config.h.in b/config.h.in index a06534ad8..2e73b115e 100644 --- a/config.h.in +++ b/config.h.in @@ -51,10 +51,6 @@ /* Define to 1 to use x86 dynamic cpu core */ #undef C_DYNAMIC_X86 -/* Define to 1 to use recompiling cpu core. Can not be used together with the - dynamic-x86 core */ -#undef C_DYNREC - /* Define to 1 to enable fluidsynth MIDI synthesis */ #undef C_FLUIDSYNTH diff --git a/configure b/configure index b8c7431e3..6475f3e6c 100755 --- a/configure +++ b/configure @@ -748,7 +748,6 @@ enable_debug enable_core_inline enable_dynamic_core enable_dynamic_x86 -enable_dynrec enable_fpu enable_fpu_x86 enable_unaligned_memory @@ -1400,7 +1399,6 @@ Optional Features: --enable-core-inline Enable inlined memory handling in CPU Core --disable-dynamic-core Disable all dynamic cores --disable-dynamic-x86 Disable x86 dynamic cpu core - --disable-dynrec Disable recompiling cpu core --disable-fpu Disable fpu support --disable-fpu-x86 Disable x86 assembly fpu core --disable-unaligned-memory @@ -6829,43 +6827,6 @@ $as_echo "no" >&6; } fi -# Check whether --enable-dynrec was given. -if test "${enable_dynrec+set}" = set; then : - enableval=$enable_dynrec; -else - enable_dynrec=yes -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether recompiling cpu core will be enabled" >&5 -$as_echo_n "checking whether recompiling cpu core will be enabled... " >&6; } -if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else - if test x$c_targetcpu = xx86 ; then - if test x$enable_dynamic_x86 = xno ; then - $as_echo "#define C_DYNREC 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using dynamic-x86" >&5 -$as_echo "no, using dynamic-x86" >&6; } - fi - else - if test x$c_targetcpu = xx86_64 ; then - $as_echo "#define C_DYNREC 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - fi -fi - - # Check whether --enable-fpu was given. if test "${enable_fpu+set}" = set; then : enableval=$enable_fpu; @@ -7693,7 +7654,7 @@ fi -ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile src/cpu/core_dynrec/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/hardware/serialport/Makefile src/hardware/reSID/Makefile src/hardware/parport/Makefile src/ints/Makefile src/libs/Makefile src/libs/zmbv/Makefile src/libs/gui_tk/Makefile src/libs/porttalk/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile include/Makefile" +ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/hardware/serialport/Makefile src/hardware/reSID/Makefile src/hardware/parport/Makefile src/ints/Makefile src/libs/Makefile src/libs/zmbv/Makefile src/libs/gui_tk/Makefile src/libs/porttalk/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile include/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -8437,7 +8398,6 @@ do "src/cpu/core_full/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_full/Makefile" ;; "src/cpu/core_normal/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_normal/Makefile" ;; "src/cpu/core_dyn_x86/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_dyn_x86/Makefile" ;; - "src/cpu/core_dynrec/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_dynrec/Makefile" ;; "src/debug/Makefile") CONFIG_FILES="$CONFIG_FILES src/debug/Makefile" ;; "src/dos/Makefile") CONFIG_FILES="$CONFIG_FILES src/dos/Makefile" ;; "src/fpu/Makefile") CONFIG_FILES="$CONFIG_FILES src/fpu/Makefile" ;; diff --git a/configure.ac b/configure.ac index 01101e1aa..de2211913 100644 --- a/configure.ac +++ b/configure.ac @@ -285,30 +285,6 @@ else fi fi -AH_TEMPLATE(C_DYNREC,[Define to 1 to use recompiling cpu core. Can not be used together with the dynamic-x86 core]) -AC_ARG_ENABLE(dynrec,AC_HELP_STRING([--disable-dynrec],[Disable recompiling cpu core]),,enable_dynrec=yes) -AC_MSG_CHECKING(whether recompiling cpu core will be enabled) -if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then - AC_MSG_RESULT(no) -else -dnl x86 only enable it if dynamic-x86 is disabled. - if test x$c_targetcpu = xx86 ; then - if test x$enable_dynamic_x86 = xno ; then - AC_DEFINE(C_DYNREC,1) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT([no, using dynamic-x86]) - fi - else - if test x$c_targetcpu = xx86_64 ; then - AC_DEFINE(C_DYNREC,1) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - fi -fi - AH_TEMPLATE(C_FPU,[Define to 1 to enable floating point emulation]) AC_ARG_ENABLE(fpu,AC_HELP_STRING([--disable-fpu],[Disable fpu support]),,enable_fpu=yes) AC_MSG_CHECKING(whether fpu emulation will be enabled) @@ -528,7 +504,6 @@ src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile -src/cpu/core_dynrec/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index f9d623e6c..d3db9add5 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -1,7 +1,7 @@ -SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec +SUBDIRS = core_full core_normal core_dyn_x86 AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ paging.cpp lazyflags.h core_normal.cpp core_simple.cpp core_prefetch.cpp \ - core_dyn_x86.cpp core_dynrec.cpp mmx.cpp + core_dyn_x86.cpp mmx.cpp diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in index e2bd987dc..0baedac38 100644 --- a/src/cpu/Makefile.in +++ b/src/cpu/Makefile.in @@ -74,8 +74,7 @@ libcpu_a_LIBADD = am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \ modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \ core_normal.$(OBJEXT) core_simple.$(OBJEXT) \ - core_prefetch.$(OBJEXT) core_dyn_x86.$(OBJEXT) \ - core_dynrec.$(OBJEXT) mmx.$(OBJEXT) + core_prefetch.$(OBJEXT) core_dyn_x86.$(OBJEXT) mmx.$(OBJEXT) libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -294,12 +293,12 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec +SUBDIRS = core_full core_normal core_dyn_x86 AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ paging.cpp lazyflags.h core_normal.cpp core_simple.cpp core_prefetch.cpp \ - core_dyn_x86.cpp core_dynrec.cpp mmx.cpp + core_dyn_x86.cpp mmx.cpp all: all-recursive @@ -351,7 +350,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dyn_x86.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dynrec.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_full.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_prefetch.Po@am__quote@ diff --git a/src/cpu/core_dynrec.cpp b/src/cpu/core_dynrec.cpp deleted file mode 100644 index 794d7488c..000000000 --- a/src/cpu/core_dynrec.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#include "dosbox.h" - -#if (C_DYNREC) - -#include -#include -#include -#include -#include -#include - -#if defined (WIN32) -#include -#include -#endif - -#if (C_HAVE_MPROTECT) -#include - -#include -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif -#endif /* C_HAVE_MPROTECT */ - -#include "callback.h" -#include "regs.h" -#include "mem.h" -#include "cpu.h" -#include "debug.h" -#include "paging.h" -#include "inout.h" -#include "lazyflags.h" -#include "pic.h" - -#define CACHE_MAXSIZE (4096*2) -#define CACHE_TOTAL (1024*1024*8) -#define CACHE_PAGES (512) -#define CACHE_BLOCKS (128*1024) -#define CACHE_ALIGN (16) -#define DYN_HASH_SHIFT (4) -#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) -#define DYN_LINKS (16) - - -//#define DYN_LOG 1 //Turn Logging on. - - -#if C_FPU -#define CPU_FPU 1 //Enable FPU escape instructions -#endif - - -// the emulated x86 registers -#define DRC_REG_EAX 0 -#define DRC_REG_ECX 1 -#define DRC_REG_EDX 2 -#define DRC_REG_EBX 3 -#define DRC_REG_ESP 4 -#define DRC_REG_EBP 5 -#define DRC_REG_ESI 6 -#define DRC_REG_EDI 7 - -// the emulated x86 segment registers -#define DRC_SEG_ES 0 -#define DRC_SEG_CS 1 -#define DRC_SEG_SS 2 -#define DRC_SEG_DS 3 -#define DRC_SEG_FS 4 -#define DRC_SEG_GS 5 - - -// access to a general register -#define DRCD_REG_VAL(reg) (&cpu_regs.regs[reg].dword) -// access to a segment register -#define DRCD_SEG_VAL(seg) (&Segs.val[seg]) -// access to the physical value of a segment register/selector -#define DRCD_SEG_PHYS(seg) (&Segs.phys[seg]) - -// access to an 8bit general register -#define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx?BH_INDEX:BL_INDEX]) -// access to 16/32bit general registers -#define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword[DW_INDEX])):((void*)(&cpu_regs.regs[reg].word[W_INDEX]))) - - -enum BlockReturn { - BR_Normal=0, - BR_Cycles, - BR_Link1,BR_Link2, - BR_Opcode, -#if (C_DEBUG) - BR_OpcodeFull, -#endif - BR_Iret, - BR_CallBack, - BR_SMCBlock -}; - -// identificator to signal self-modification of the currently executed block -#define SMC_CURRENT_BLOCK 0xffff - - -static void IllegalOptionDynrec(const char* msg) { - E_Exit("DynrecCore: illegal option in %s",msg); -} - -static struct { - BlockReturn (*runcode)(Bit8u*); // points to code that can start a block - Bitu callback; // the occurred callback - Bitu readdata; // spare space used when reading from memory - Bit32u protected_regs[8]; // space to save/restore register values -} core_dynrec; - - -#include "core_dynrec/cache.h" - -#define X86 0x01 -#define X86_64 0x02 -#define MIPSEL 0x03 -#define ARMV4LE 0x04 -#define ARMV7LE 0x05 -#define POWERPC 0x04 - -#if C_TARGETCPU == X86_64 -#include "core_dynrec/risc_x64.h" -#elif C_TARGETCPU == X86 -#include "core_dynrec/risc_x86.h" -#elif C_TARGETCPU == MIPSEL -#include "core_dynrec/risc_mipsel32.h" -#elif (C_TARGETCPU == ARMV4LE) || (C_TARGETCPU == ARMV7LE) -#include "core_dynrec/risc_armv4le.h" -#elif C_TARGETCPU == POWERPC -#include "core_dynrec/risc_ppc.h" -#endif - -#include "core_dynrec/decoder.h" - -CacheBlockDynRec * LinkBlocks(BlockReturn ret) { - CacheBlockDynRec * block=NULL; - // the last instruction was a control flow modifying instruction - Bitu temp_ip=SegPhys(cs)+reg_eip; - CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_readhandler(temp_ip); - if (temp_handler->flags & PFLAG_HASCODE) { - // see if the target is an already translated block - block=temp_handler->FindCacheBlock(temp_ip & 4095); - if (!block) return NULL; - - // found it, link the current block to - cache.block.running->LinkTo(ret==BR_Link2,block); - return block; - } - return NULL; -} - -/* - The core tries to find the block that should be executed next. - If such a block is found, it is run, otherwise the instruction - stream starting at ip_point is translated (see decoder.h) and - makes up a new code block that will be run. - When control is returned to CPU_Core_Dynrec_Run (which might - be right after the block is run, or somewhen long after that - due to the direct cacheblock linking) the returncode decides - the next action. This might be continuing the translation and - execution process, or returning from the core etc. -*/ - -Bits CPU_Core_Dynrec_Run(void) { - for (;;) { - // Determine the linear address of CS:EIP - PhysPt ip_point=SegPhys(cs)+reg_eip; - #if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; - #endif - - CodePageHandlerDynRec * chandler=0; - // see if the current page is present and contains code - if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) { - // page not present, throw the exception - CPU_Exception(cpu.exception.which,cpu.exception.error); - continue; - } - - // page doesn't contain code or is special - if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run(); - - // find correct Dynamic Block to run - CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095); - if (!block) { - // no block found, thus translate the instruction stream - // unless the instruction is known to be modified - if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) { - // translate up to 32 instructions - block=CreateCacheBlock(chandler,ip_point,32); - } else { - // let the normal core handle this instruction to avoid zero-sized blocks - Bitu old_cycles=CPU_Cycles; - CPU_Cycles=1; - Bits nc_retcode=CPU_Core_Normal_Run(); - if (!nc_retcode) { - CPU_Cycles=old_cycles-1; - continue; - } - CPU_CycleLeft+=old_cycles; - return nc_retcode; - } - } - -run_block: - cache.block.running=0; - Bitu CPU_CyclesOld = CPU_Cycles; - // now we're ready to run the dynamic code block -// BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))(); - BlockReturn ret=core_dynrec.runcode(block->cache.start); - cycle_count += CPU_CyclesOld - CPU_Cycles; - - switch (ret) { - case BR_Iret: -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - if (!GETFLAG(TF)) { - if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; - break; - } - // trapflag is set, switch to the trap-aware decoder - cpudecoder=CPU_Core_Dynrec_Trap_Run; - return CBRET_NONE; - - case BR_Normal: - // the block was exited due to a non-predictable control flow - // modifying instruction (like ret) or some nontrivial cpu state - // changing instruction (for example switch to/from pmode), - // or the maximum number of instructions to translate was reached -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - break; - - case BR_Cycles: - // cycles went negative, return from the core to handle - // external events, schedule the pic... -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - return CBRET_NONE; - - case BR_CallBack: - // the callback code is executed in dosbox.conf, return the callback number - FillFlags(); - return core_dynrec.callback; - - case BR_SMCBlock: -// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); - cpu.exception.which=0; - // fallthrough, let the normal core handle the block-modifying instruction - case BR_Opcode: - // some instruction has been encountered that could not be translated - // (thus it is not part of the code block), the normal core will - // handle this instruction - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - return CPU_Core_Normal_Run(); - -#if (C_DEBUG) - case BR_OpcodeFull: - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - return CPU_Core_Full_Run(); -#endif - - case BR_Link1: - case BR_Link2: - block=LinkBlocks(ret); - if (block) goto run_block; - break; - - default: - E_Exit("Invalid return code %d", ret); - } - } - return CBRET_NONE; -} - -Bits CPU_Core_Dynrec_Trap_Run(void) { - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - cpu.trap_skip = false; - - // let the normal core execute the next (only one!) instruction - Bits ret=CPU_Core_Normal_Run(); - - // trap to int1 unless the last instruction deferred this - // (allows hardware interrupts to be served without interaction) - if (!cpu.trap_skip) CPU_HW_Interrupt(1); - - CPU_Cycles = oldCycles-1; - // continue (either the trapflag was clear anyways, or the int1 cleared it) - cpudecoder = &CPU_Core_Dynrec_Run; - - return ret; -} - -void CPU_Core_Dynrec_Init(void) { -} - -void CPU_Core_Dynrec_Cache_Init(bool enable_cache) { - // Initialize code cache and dynamic blocks - cache_init(enable_cache); -} - -void CPU_Core_Dynrec_Cache_Close(void) { - cache_close(); -} - -#endif diff --git a/src/cpu/core_dynrec/Makefile.am b/src/cpu/core_dynrec/Makefile.am deleted file mode 100644 index 288b9154f..000000000 --- a/src/cpu/core_dynrec/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \ - dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \ - risc_armv4le.h risc_armv4le-common.h \ - risc_armv4le-o3.h risc_armv4le-thumb.h \ - risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h diff --git a/src/cpu/core_dynrec/Makefile.in b/src/cpu/core_dynrec/Makefile.in deleted file mode 100644 index 0afb533dc..000000000 --- a/src/cpu/core_dynrec/Makefile.in +++ /dev/null @@ -1,451 +0,0 @@ -# Makefile.in generated by automake 1.13.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2012 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/cpu/core_dynrec -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(noinst_HEADERS) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -HEADERS = $(noinst_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALSA_CFLAGS = @ALSA_CFLAGS@ -ALSA_LIBS = @ALSA_LIBS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -SDL_CFLAGS = @SDL_CFLAGS@ -SDL_CONFIG = @SDL_CONFIG@ -SDL_LIBS = @SDL_LIBS@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -WINDRES = @WINDRES@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \ - dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \ - risc_armv4le.h risc_armv4le-common.h \ - risc_armv4le-o3.h risc_armv4le-thumb.h \ - risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(HEADERS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - cscopelist-am ctags ctags-am distclean distclean-generic \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/cpu/core_dynrec/cache.h b/src/cpu/core_dynrec/cache.h deleted file mode 100644 index fec54fdd3..000000000 --- a/src/cpu/core_dynrec/cache.h +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -class CodePageHandlerDynRec; // forward - -// basic cache block representation -class CacheBlockDynRec { -public: - void Clear(void); - // link this cache block to another block, index specifies the code - // path (always zero for unconditional links, 0/1 for conditional ones - void LinkTo(Bitu index,CacheBlockDynRec * toblock) { - assert(toblock); - link[index].to=toblock; - link[index].next=toblock->link[index].from; // set target block - toblock->link[index].from=this; // remember who links me - } - struct { - Bit16u start,end; // where in the page is the original code - CodePageHandlerDynRec * handler; // page containing this code - } page; - struct { - Bit8u * start; // where in the cache are we - Bitu size; - CacheBlockDynRec * next; - // writemap masking maskpointer/start/length - // to allow holes in the writemap - Bit8u * wmapmask; - Bit16u maskstart; - Bit16u masklen; - } cache; - struct { - Bitu index; - CacheBlockDynRec * next; - } hash; - struct { - CacheBlockDynRec * to; // this block can transfer control to the to-block - CacheBlockDynRec * next; - CacheBlockDynRec * from; // the from-block can transfer control to this block - } link[2]; // maximum two links (conditional jumps) - CacheBlockDynRec * crossblock; -}; - -static struct { - struct { - CacheBlockDynRec * first; // the first cache block in the list - CacheBlockDynRec * active; // the current cache block - CacheBlockDynRec * free; // pointer to the free list - CacheBlockDynRec * running; // the last block that was entered for execution - } block; - Bit8u * pos; // position in the cache block - CodePageHandlerDynRec * free_pages; // pointer to the free list - CodePageHandlerDynRec * used_pages; // pointer to the list of used pages - CodePageHandlerDynRec * last_page; // the last used page -} cache; - - -// cache memory pointers, to be malloc'd later -static Bit8u * cache_code_start_ptr=NULL; -static Bit8u * cache_code=NULL; -static Bit8u * cache_code_link_blocks=NULL; - -static CacheBlockDynRec * cache_blocks=NULL; -static CacheBlockDynRec link_blocks[2]; // default linking (specially marked) - - -// the CodePageHandlerDynRec class provides access to the contained -// cache blocks and intercepts writes to the code for special treatment -class CodePageHandlerDynRec : public PageHandler { -public: - CodePageHandlerDynRec() { - invalidation_map=NULL; - } - - void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) { - // initialize this codepage handler - phys_page=_phys_page; - // save the old pagehandler to provide direct read access to the memory, - // and to be able to restore it later on - old_pagehandler=_old_pagehandler; - - // adjust flags - flags=old_pagehandler->flags|PFLAG_HASCODE; - flags&=~PFLAG_WRITEABLE; - - active_blocks=0; - active_count=16; - - // initialize the maps with zero (no cache blocks as well as code present) - memset(&hash_map,0,sizeof(hash_map)); - memset(&write_map,0,sizeof(write_map)); - if (invalidation_map!=NULL) { - free(invalidation_map); - invalidation_map=NULL; - } - } - - // clear out blocks that contain code which has been modified - bool InvalidateRange(Bitu start,Bitu end) { - Bits index=1+(end>>DYN_HASH_SHIFT); - bool is_current_block=false; // if the current block is modified, it has to be exited as soon as possible - - Bit32u ip_point=SegPhys(cs)+reg_eip; - ip_point=(PAGING_GetPhysicalPage(ip_point)-(phys_page<<12))+(ip_point&0xfff); - while (index>=0) { - Bitu map=0; - // see if there is still some code in the range - for (Bitu count=start;count<=end;count++) map+=write_map[count]; - if (!map) return is_current_block; // no more code, finished - - CacheBlockDynRec * block=hash_map[index]; - while (block) { - CacheBlockDynRec * nextblock=block->hash.next; - // test if this block is in the range - if (start<=block->page.end && end>=block->page.start) { - if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true; - block->Clear(); // clear the block, decrements the write_map accordingly - } - block=nextblock; - } - index--; - } - return is_current_block; - } - - // the following functions will clean all cache blocks that are invalid now due to the write - void writeb(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readb(hostmem+addr)==(Bit8u)val) return; - host_writeb(hostmem+addr,val); - // see if there's code where we are writing to - if (!host_readb(&write_map[addr])) { - if (active_blocks) return; // still some blocks in this page - active_count--; - if (!active_count) Release(); // delay page releasing until active_count is zero - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - invalidation_map[addr]++; - InvalidateRange(addr,addr); - } - void writew(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readw(hostmem+addr)==(Bit16u)val) return; - host_writew(hostmem+addr,val); - // see if there's code where we are writing to - if (!host_readw(&write_map[addr])) { - if (active_blocks) return; // still some blocks in this page - active_count--; - if (!active_count) Release(); // delay page releasing until active_count is zero - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writew(&invalidation_map[addr], - host_readw(&invalidation_map[addr])+0x101); -#else - (*(Bit16u*)&invalidation_map[addr])+=0x101; -#endif - InvalidateRange(addr,addr+1); - } - void writed(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readd(hostmem+addr)==(Bit32u)val) return; - host_writed(hostmem+addr,val); - // see if there's code where we are writing to - if (!host_readd(&write_map[addr])) { - if (active_blocks) return; // still some blocks in this page - active_count--; - if (!active_count) Release(); // delay page releasing until active_count is zero - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writed(&invalidation_map[addr], - host_readd(&invalidation_map[addr])+0x1010101); -#else - (*(Bit32u*)&invalidation_map[addr])+=0x1010101; -#endif - InvalidateRange(addr,addr+3); - } - bool writeb_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readb(hostmem+addr)==(Bit8u)val) return false; - // see if there's code where we are writing to - if (!host_readb(&write_map[addr])) { - if (!active_blocks) { - // no blocks left in this page, still delay the page releasing a bit - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - invalidation_map[addr]++; - if (InvalidateRange(addr,addr)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writeb(hostmem+addr,val); - return false; - } - bool writew_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readw(hostmem+addr)==(Bit16u)val) return false; - // see if there's code where we are writing to - if (!host_readw(&write_map[addr])) { - if (!active_blocks) { - // no blocks left in this page, still delay the page releasing a bit - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writew(&invalidation_map[addr], - host_readw(&invalidation_map[addr])+0x101); -#else - (*(Bit16u*)&invalidation_map[addr])+=0x101; -#endif - if (InvalidateRange(addr,addr+1)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writew(hostmem+addr,val); - return false; - } - bool writed_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readd(hostmem+addr)==(Bit32u)val) return false; - // see if there's code where we are writing to - if (!host_readd(&write_map[addr])) { - if (!active_blocks) { - // no blocks left in this page, still delay the page releasing a bit - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writed(&invalidation_map[addr], - host_readd(&invalidation_map[addr])+0x1010101); -#else - (*(Bit32u*)&invalidation_map[addr])+=0x1010101; -#endif - if (InvalidateRange(addr,addr+3)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writed(hostmem+addr,val); - return false; - } - - // add a cache block to this page and note it in the hash map - void AddCacheBlock(CacheBlockDynRec * block) { - Bitu index=1+(block->page.start>>DYN_HASH_SHIFT); - block->hash.next=hash_map[index]; // link to old block at index from the new block - block->hash.index=index; - hash_map[index]=block; // put new block at hash position - block->page.handler=this; - active_blocks++; - } - // there's a block whose code started in a different page - void AddCrossBlock(CacheBlockDynRec * block) { - block->hash.next=hash_map[0]; - block->hash.index=0; - hash_map[0]=block; - block->page.handler=this; - active_blocks++; - } - // remove a cache block - void DelCacheBlock(CacheBlockDynRec * block) { - active_blocks--; - active_count=16; - CacheBlockDynRec * * bwhere=&hash_map[block->hash.index]; - while (*bwhere!=block) { - bwhere=&((*bwhere)->hash.next); - //Will crash if a block isn't found, which should never happen. - } - *bwhere=block->hash.next; - - // remove the cleared block from the write map - if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) { - // first part is not influenced by the mask - for (Bitu i=block->page.start;icache.maskstart;i++) { - if (write_map[i]) write_map[i]--; - } - Bitu maskct=0; - // last part sticks to the writemap mask - for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) { - if (write_map[i]) { - // only adjust writemap if it isn't masked - if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--; - } - } - free(block->cache.wmapmask); - block->cache.wmapmask=NULL; - } else { - for (Bitu i=block->page.start;i<=block->page.end;i++) { - if (write_map[i]) write_map[i]--; - } - } - } - - void Release(void) { - MEM_SetPageHandler(phys_page,1,old_pagehandler); // revert to old handler - PAGING_ClearTLB(); - - // remove page from the lists - if (prev) prev->next=next; - else cache.used_pages=next; - if (next) next->prev=prev; - else cache.last_page=prev; - next=cache.free_pages; - cache.free_pages=this; - prev=0; - } - void ClearRelease(void) { - // clear out all cache blocks in this page - for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) { - CacheBlockDynRec * block=hash_map[index]; - while (block) { - CacheBlockDynRec * nextblock=block->hash.next; - block->page.handler=0; // no need, full clear - block->Clear(); - block=nextblock; - } - } - Release(); // now can release this page - } - - CacheBlockDynRec * FindCacheBlock(Bitu start) { - CacheBlockDynRec * block=hash_map[1+(start>>DYN_HASH_SHIFT)]; - // see if there's a cache block present at the start address - while (block) { - if (block->page.start==start) return block; // found - block=block->hash.next; - } - return 0; // none found - } - - HostPt GetHostReadPt(Bitu phys_page) { - hostmem=old_pagehandler->GetHostReadPt(phys_page); - return hostmem; - } - HostPt GetHostWritePt(Bitu phys_page) { - return GetHostReadPt( phys_page ); - } -public: - // the write map, there are write_map[i] cache blocks that cover the byte at address i - Bit8u write_map[4096]; - Bit8u * invalidation_map; - CodePageHandlerDynRec * next, * prev; // page linking -private: - PageHandler * old_pagehandler; - - // hash map to quickly find the cache blocks in this page - CacheBlockDynRec * hash_map[1+DYN_PAGE_HASH]; - - Bitu active_blocks; // the number of cache blocks in this page - Bitu active_count; // delaying parameter to not immediately release a page - HostPt hostmem; - Bitu phys_page; -}; - - -static INLINE void cache_addunusedblock(CacheBlockDynRec * block) { - // block has become unused, add it to the freelist - block->cache.next=cache.block.free; - cache.block.free=block; -} - -static CacheBlockDynRec * cache_getblock(void) { - // get a free cache block and advance the free pointer - CacheBlockDynRec * ret=cache.block.free; - if (!ret) E_Exit("Ran out of CacheBlocks" ); - cache.block.free=ret->cache.next; - ret->cache.next=0; - return ret; -} - -void CacheBlockDynRec::Clear(void) { - Bitu ind; - // check if this is not a cross page block - if (hash.index) for (ind=0;ind<2;ind++) { - CacheBlockDynRec * fromlink=link[ind].from; - link[ind].from=0; - while (fromlink) { - CacheBlockDynRec * nextlink=fromlink->link[ind].next; - // clear the next-link and let the block point to the standard linkcode - fromlink->link[ind].next=0; - fromlink->link[ind].to=&link_blocks[ind]; - - fromlink=nextlink; - } - if (link[ind].to!=&link_blocks[ind]) { - // not linked to the standard linkcode, find the block that links to this block - CacheBlockDynRec * * wherelink=&link[ind].to->link[ind].from; - while (*wherelink != this && *wherelink) { - wherelink = &(*wherelink)->link[ind].next; - } - // now remove the link - if(*wherelink) - *wherelink = (*wherelink)->link[ind].next; - else { - LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate"); - } - } - } else - cache_addunusedblock(this); - if (crossblock) { - // clear out the crossblock (in the page before) as well - crossblock->crossblock=0; - crossblock->Clear(); - crossblock=0; - } - if (page.handler) { - // clear out the code page handler - page.handler->DelCacheBlock(this); - page.handler=0; - } - if (cache.wmapmask){ - free(cache.wmapmask); - cache.wmapmask=NULL; - } -} - - -static CacheBlockDynRec * cache_openblock(void) { - CacheBlockDynRec * block=cache.block.active; - // check for enough space in this block - Bitu size=block->cache.size; - CacheBlockDynRec * nextblock=block->cache.next; - if (block->page.handler) - block->Clear(); - // block size must be at least CACHE_MAXSIZE - while (sizecache.size; - CacheBlockDynRec * tempblock=nextblock->cache.next; - if (nextblock->page.handler) - nextblock->Clear(); - // block is free now - cache_addunusedblock(nextblock); - nextblock=tempblock; - } -skipresize: - // adjust parameters and open this block - block->cache.size=size; - block->cache.next=nextblock; - cache.pos=block->cache.start; - return block; -} - -static void cache_closeblock(void) { - CacheBlockDynRec * block=cache.block.active; - // links point to the default linking code - block->link[0].to=&link_blocks[0]; - block->link[1].to=&link_blocks[1]; - block->link[0].from=0; - block->link[1].from=0; - block->link[0].next=0; - block->link[1].next=0; - // close the block with correct alignment - Bitu written=(Bitu)(cache.pos-block->cache.start); - if (written>block->cache.size) { - if (!block->cache.next) { - if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size); - } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size); - } else { - Bitu new_size; - Bitu left=block->cache.size-written; - // smaller than cache align then don't bother to resize - if (left>CACHE_ALIGN) { - new_size=((written-1)|(CACHE_ALIGN-1))+1; - CacheBlockDynRec * newblock=cache_getblock(); - // align block now to CACHE_ALIGN - newblock->cache.start=block->cache.start+new_size; - newblock->cache.size=block->cache.size-new_size; - newblock->cache.next=block->cache.next; - block->cache.next=newblock; - block->cache.size=new_size; - } - } - // advance the active block pointer - if (!block->cache.next || (block->cache.next->cache.start>(cache_code_start_ptr + CACHE_TOTAL - CACHE_MAXSIZE))) { -// LOG_MSG("Cache full restarting"); - cache.block.active=cache.block.first; - } else { - cache.block.active=block->cache.next; - } -} - - -// place an 8bit value into the cache -static INLINE void cache_addb(Bit8u val) { - *cache.pos++=val; -} - -// place a 16bit value into the cache -static INLINE void cache_addw(Bit16u val) { - *(Bit16u*)cache.pos=val; - cache.pos+=2; -} - -// place a 32bit value into the cache -static INLINE void cache_addd(Bit32u val) { - *(Bit32u*)cache.pos=val; - cache.pos+=4; -} - -// place a 64bit value into the cache -static INLINE void cache_addq(Bit64u val) { - *(Bit64u*)cache.pos=val; - cache.pos+=8; -} - - -static void dyn_return(BlockReturn retcode,bool ret_exception); -static void dyn_run_code(void); - - -/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */ -#if (C_HAVE_MPROTECT) -#define PAGESIZE_TEMP PAGESIZE -#else -#define PAGESIZE_TEMP 4096 -#endif - -static bool cache_initialized = false; - -static void cache_init(bool enable) { - Bits i; - if (enable) { - // see if cache is already initialized - if (cache_initialized) return; - cache_initialized = true; - if (cache_blocks == NULL) { - // allocate the cache blocks memory - cache_blocks=(CacheBlockDynRec*)malloc(CACHE_BLOCKS*sizeof(CacheBlockDynRec)); - if(!cache_blocks) E_Exit("Allocating cache_blocks has failed"); - memset(cache_blocks,0,sizeof(CacheBlockDynRec)*CACHE_BLOCKS); - cache.block.free=&cache_blocks[0]; - // initialize the cache blocks - for (i=0;icache.start=&cache_code[0]; - block->cache.size=CACHE_TOTAL; - block->cache.next=0; // last block in the list - } - // setup the default blocks for block linkage returns - cache.pos=&cache_code_link_blocks[0]; - link_blocks[0].cache.start=cache.pos; - // link code that returns with a special return code - dyn_return(BR_Link1,false); - cache.pos=&cache_code_link_blocks[32]; - link_blocks[1].cache.start=cache.pos; - // link code that returns with a special return code - dyn_return(BR_Link2,false); - - cache.pos=&cache_code_link_blocks[64]; - core_dynrec.runcode=(BlockReturn (*)(Bit8u*))cache.pos; -// link_blocks[1].cache.start=cache.pos; - dyn_run_code(); - - cache.free_pages=0; - cache.last_page=0; - cache.used_pages=0; - // setup the code pages - for (i=0;inext=cache.free_pages; - cache.free_pages=newpage; - } - } -} - -static void cache_close(void) { -/* for (;;) { - if (cache.used_pages) { - CodePageHandler * cpage=cache.used_pages; - CodePageHandler * npage=cache.used_pages->next; - cpage->ClearRelease(); - delete cpage; - cache.used_pages=npage; - } else break; - } - if (cache_blocks != NULL) { - free(cache_blocks); - cache_blocks = NULL; - } - if (cache_code_start_ptr != NULL) { - ### care: under windows VirtualFree() has to be used if - ### VirtualAlloc was used for memory allocation - free(cache_code_start_ptr); - cache_code_start_ptr = NULL; - } - cache_code = NULL; - cache_code_link_blocks = NULL; - cache_initialized = false; */ -} diff --git a/src/cpu/core_dynrec/decoder.h b/src/cpu/core_dynrec/decoder.h deleted file mode 100644 index 494cdd604..000000000 --- a/src/cpu/core_dynrec/decoder.h +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -#include "decoder_basic.h" -#include "operators.h" -#include "decoder_opcodes.h" - -#include "dyn_fpu.h" - -/* - The function CreateCacheBlock translates the instruction stream - until either an unhandled instruction is found, the maximum - number of translated instructions is reached or some critical - instruction is encountered. -*/ - -static CacheBlockDynRec * CreateCacheBlock(CodePageHandlerDynRec * codepage,PhysPt start,Bitu max_opcodes) { - // initialize a load of variables - decode.code_start=start; - decode.code=start; - decode.page.code=codepage; - decode.page.index=start&4095; - decode.page.wmap=codepage->write_map; - decode.page.invmap=codepage->invalidation_map; - decode.page.first=start >> 12; - decode.active_block=decode.block=cache_openblock(); - decode.block->page.start=(Bit16u)decode.page.index; - codepage->AddCacheBlock(decode.block); - - InitFlagsOptimization(); - - // every codeblock that is run sets cache.block.running to itself - // so the block linking knows the last executed block - gen_mov_direct_ptr(&cache.block.running,(DRC_PTR_SIZE_IM)decode.block); - - // start with the cycles check - gen_mov_word_to_reg(FC_RETOP,&CPU_Cycles,true); - save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_leqzero(FC_RETOP); - save_info_dynrec[used_save_info_dynrec].type=cycle_check; - used_save_info_dynrec++; - - decode.cycles=0; - while (max_opcodes--) { - // Init prefixes - decode.big_addr=cpu.code.big; - decode.big_op=cpu.code.big; - decode.seg_prefix=0; - decode.seg_prefix_used=false; - decode.rep=REP_NONE; - decode.cycles++; - decode.op_start=decode.code; -restart_prefix: - Bitu opcode; - if (!decode.page.invmap) opcode=decode_fetchb(); - else { - // some entries in the invalidation map, see if the next - // instruction is known to be modified a lot - if (decode.page.index<4096) { - if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode; - opcode=decode_fetchb(); - } else { - // switch to the next page - opcode=decode_fetchb(); - if (GCC_UNLIKELY(decode.page.invmap && - (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode; - } - } - switch (opcode) { - // instructions 'op reg8,reg8' and 'op [],reg8' - case 0x00:dyn_dop_ebgb(DOP_ADD);break; - case 0x08:dyn_dop_ebgb(DOP_OR);break; - case 0x10:dyn_dop_ebgb(DOP_ADC);break; - case 0x18:dyn_dop_ebgb(DOP_SBB);break; - case 0x20:dyn_dop_ebgb(DOP_AND);break; - case 0x28:dyn_dop_ebgb(DOP_SUB);break; - case 0x30:dyn_dop_ebgb(DOP_XOR);break; - case 0x38:dyn_dop_ebgb(DOP_CMP);break; - - // instructions 'op reg8,reg8' and 'op reg8,[]' - case 0x02:dyn_dop_gbeb(DOP_ADD);break; - case 0x0a:dyn_dop_gbeb(DOP_OR);break; - case 0x12:dyn_dop_gbeb(DOP_ADC);break; - case 0x1a:dyn_dop_gbeb(DOP_SBB);break; - case 0x22:dyn_dop_gbeb(DOP_AND);break; - case 0x2a:dyn_dop_gbeb(DOP_SUB);break; - case 0x32:dyn_dop_gbeb(DOP_XOR);break; - case 0x3a:dyn_dop_gbeb(DOP_CMP);break; - - // instructions 'op reg16/32,reg16/32' and 'op [],reg16/32' - case 0x01:dyn_dop_evgv(DOP_ADD);break; - case 0x09:dyn_dop_evgv(DOP_OR);break; - case 0x11:dyn_dop_evgv(DOP_ADC);break; - case 0x19:dyn_dop_evgv(DOP_SBB);break; - case 0x21:dyn_dop_evgv(DOP_AND);break; - case 0x29:dyn_dop_evgv(DOP_SUB);break; - case 0x31:dyn_dop_evgv(DOP_XOR);break; - case 0x39:dyn_dop_evgv(DOP_CMP);break; - - // instructions 'op reg16/32,reg16/32' and 'op reg16/32,[]' - case 0x03:dyn_dop_gvev(DOP_ADD);break; - case 0x0b:dyn_dop_gvev(DOP_OR);break; - case 0x13:dyn_dop_gvev(DOP_ADC);break; - case 0x1b:dyn_dop_gvev(DOP_SBB);break; - case 0x23:dyn_dop_gvev(DOP_AND);break; - case 0x2b:dyn_dop_gvev(DOP_SUB);break; - case 0x33:dyn_dop_gvev(DOP_XOR);break; - case 0x3b:dyn_dop_gvev(DOP_CMP);break; - - // instructions 'op reg8,imm8' - case 0x04:dyn_dop_byte_imm(DOP_ADD,DRC_REG_EAX,0);break; - case 0x0c:dyn_dop_byte_imm(DOP_OR,DRC_REG_EAX,0);break; - case 0x14:dyn_dop_byte_imm(DOP_ADC,DRC_REG_EAX,0);break; - case 0x1c:dyn_dop_byte_imm(DOP_SBB,DRC_REG_EAX,0);break; - case 0x24:dyn_dop_byte_imm(DOP_AND,DRC_REG_EAX,0);break; - case 0x2c:dyn_dop_byte_imm(DOP_SUB,DRC_REG_EAX,0);break; - case 0x34:dyn_dop_byte_imm(DOP_XOR,DRC_REG_EAX,0);break; - case 0x3c:dyn_dop_byte_imm(DOP_CMP,DRC_REG_EAX,0);break; - - // instructions 'op reg16/32,imm16/32' - case 0x05:dyn_dop_word_imm(DOP_ADD,DRC_REG_EAX);break; - case 0x0d:dyn_dop_word_imm_old(DOP_OR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x15:dyn_dop_word_imm_old(DOP_ADC,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x1d:dyn_dop_word_imm_old(DOP_SBB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x25:dyn_dop_word_imm(DOP_AND,DRC_REG_EAX);break; - case 0x2d:dyn_dop_word_imm_old(DOP_SUB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x35:dyn_dop_word_imm_old(DOP_XOR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x3d:dyn_dop_word_imm_old(DOP_CMP,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - - // push segment register onto stack - case 0x06:dyn_push_seg(DRC_SEG_ES);break; - case 0x0e:dyn_push_seg(DRC_SEG_CS);break; - case 0x16:dyn_push_seg(DRC_SEG_SS);break; - case 0x1e:dyn_push_seg(DRC_SEG_DS);break; - - // pop segment register from stack - case 0x07:dyn_pop_seg(DRC_SEG_ES);break; - case 0x17:dyn_pop_seg(DRC_SEG_SS);break; - case 0x1f:dyn_pop_seg(DRC_SEG_DS);break; - - // segment prefixes - case 0x26:dyn_segprefix(DRC_SEG_ES);goto restart_prefix; - case 0x2e:dyn_segprefix(DRC_SEG_CS);goto restart_prefix; - case 0x36:dyn_segprefix(DRC_SEG_SS);goto restart_prefix; - case 0x3e:dyn_segprefix(DRC_SEG_DS);goto restart_prefix; - case 0x64:dyn_segprefix(DRC_SEG_FS);goto restart_prefix; - case 0x65:dyn_segprefix(DRC_SEG_GS);goto restart_prefix; - -// case 0x27: DAA missing -// case 0x2f: DAS missing -// case 0x37: AAA missing -// case 0x3f: AAS missing - - // dual opcodes - case 0x0f: - { - Bitu dual_code=decode_fetchb(); - switch (dual_code) { - case 0x00: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - dyn_grp6(); - break; - case 0x01: - if (dyn_grp7()) goto finish_block; - break; -/* case 0x02: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - dyn_larlsl(true); - break; - case 0x03: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - dyn_larlsl(false); - break; */ - - case 0x20:dyn_mov_from_crx();break; - case 0x22:dyn_mov_to_crx();goto finish_block; - - // short conditional jumps - case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87: - case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f: - dyn_branched_exit((BranchTypes)(dual_code&0xf), - decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - goto finish_block; - - // conditional byte set instructions -/* case 0x90:case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: - case 0x98:case 0x99:case 0x9a:case 0x9b:case 0x9c:case 0x9d:case 0x9e:case 0x9f: - dyn_set_byte_on_condition((BranchTypes)(dual_code&0xf)); - AcquireFlags(FMASK_TEST); - break; */ - - // push/pop segment registers - case 0xa0:dyn_push_seg(DRC_SEG_FS);break; - case 0xa1:dyn_pop_seg(DRC_SEG_FS);break; - case 0xa8:dyn_push_seg(DRC_SEG_GS);break; - case 0xa9:dyn_pop_seg(DRC_SEG_GS);break; - - // double shift instructions - case 0xa4:dyn_dshift_ev_gv(true,true);break; - case 0xa5:dyn_dshift_ev_gv(true,false);break; - case 0xac:dyn_dshift_ev_gv(false,true);break; - case 0xad:dyn_dshift_ev_gv(false,false);break; - - case 0xaf:dyn_imul_gvev(0);break; - - // lfs - case 0xb4: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_FS); - break; - // lgs - case 0xb5: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_GS); - break; - - // zero-extending moves - case 0xb6:dyn_movx_ev_gb(false);break; - case 0xb7:dyn_movx_ev_gw(false);break; - - // sign-extending moves - case 0xbe:dyn_movx_ev_gb(true);break; - case 0xbf:dyn_movx_ev_gw(true);break; - - default: -#if DYN_LOG -// LOG_MSG("Unhandled dual opcode 0F%02X",dual_code); -#endif - goto illegalopcode; - } - break; - } - - // 'inc/dec reg16/32' - case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47: - dyn_sop_word(SOP_INC,opcode&7); - break; - case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f: - dyn_sop_word(SOP_DEC,opcode&7); - break; - - // 'push/pop reg16/32' - case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57: - dyn_push_reg(opcode&7); - break; - case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f: - dyn_pop_reg(opcode&7); - break; - - case 0x60: - if (decode.big_op) gen_call_function_raw((void *)&dynrec_pusha_dword); - else gen_call_function_raw((void *)&dynrec_pusha_word); - break; - case 0x61: - if (decode.big_op) gen_call_function_raw((void *)&dynrec_popa_dword); - else gen_call_function_raw((void *)&dynrec_popa_word); - break; - -// case 0x62: BOUND missing -// case 0x61: ARPL missing - - case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix; - case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix; - - // 'push imm8/16/32' - case 0x68: - dyn_push_word_imm(decode.big_op ? decode_fetchd() : decode_fetchw()); - break; - case 0x6a: - dyn_push_byte_imm((Bit8s)decode_fetchb()); - break; - - // signed multiplication - case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break; - case 0x6b:dyn_imul_gvev(1);break; - -// case 0x6c to 0x6f missing (ins/outs) - - // short conditional jumps - case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77: - case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f: - dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb()); - goto finish_block; - - // 'op []/reg8,imm8' - case 0x80: - case 0x82:dyn_grp1_eb_ib();break; - - // 'op []/reg16/32,imm16/32' - case 0x81:dyn_grp1_ev_iv(false);break; - case 0x83:dyn_grp1_ev_iv(true);break; - - // 'test []/reg8/16/32,reg8/16/32' - case 0x84:dyn_dop_gbeb(DOP_TEST);break; - case 0x85:dyn_dop_gvev(DOP_TEST);break; - - // 'xchg reg8/16/32,[]/reg8/16/32' - case 0x86:dyn_dop_ebgb_xchg();break; - case 0x87:dyn_dop_evgv_xchg();break; - - // 'mov []/reg8/16/32,reg8/16/32' - case 0x88:dyn_dop_ebgb_mov();break; - case 0x89:dyn_dop_evgv_mov();break; - // 'mov reg8/16/32,[]/reg8/16/32' - case 0x8a:dyn_dop_gbeb_mov();break; - case 0x8b:dyn_dop_gvev_mov();break; - - // move segment register into memory or a 16bit register - case 0x8c:dyn_mov_ev_seg();break; - - // load effective address - case 0x8d:dyn_lea();break; - - // move a value from memory or a 16bit register into a segment register - case 0x8e:dyn_mov_seg_ev();break; - - // 'pop []' - case 0x8f:dyn_pop_ev();break; - - case 0x90: // nop - case 0x9b: // wait - case 0xf0: // lock - break; - - case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: - dyn_xchg_ax(opcode&7); - break; - - // sign-extend al into ax/sign-extend ax into eax - case 0x98:dyn_cbw();break; - // sign-extend ax into dx:ax/sign-extend eax into edx:eax - case 0x99:dyn_cwd();break; - - case 0x9a:dyn_call_far_imm();goto finish_block; - - case 0x9c: // pushf - AcquireFlags(FMASK_TEST); - gen_call_function_I((void *)&CPU_PUSHF,decode.big_op); - dyn_check_exception(FC_RETOP); - break; - case 0x9d: // popf - gen_call_function_I((void *)&CPU_POPF,decode.big_op); - dyn_check_exception(FC_RETOP); - InvalidateFlags(); - break; - - case 0x9e:dyn_sahf();break; -// case 0x9f: LAHF missing - - // 'mov al/ax,[]' - case 0xa0: - dyn_mov_byte_al_direct(decode.big_addr ? decode_fetchd() : decode_fetchw()); - break; - case 0xa1: - dyn_mov_byte_ax_direct(decode.big_addr ? decode_fetchd() : decode_fetchw()); - break; - // 'mov [],al/ax' - case 0xa2: - dyn_mov_byte_direct_al(); - break; - case 0xa3: - dyn_mov_byte_direct_ax(decode.big_addr ? decode_fetchd() : decode_fetchw()); - break; - - -// case 0xa6 to 0xaf string operations, some missing - - // movsb/w/d - case 0xa4:dyn_string(STR_MOVSB);break; - case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break; - - // stosb/w/d - case 0xaa:dyn_string(STR_STOSB);break; - case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break; - - // lodsb/w/d - case 0xac:dyn_string(STR_LODSB);break; - case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break; - - - // 'test reg8/16/32,imm8/16/32' - case 0xa8:dyn_dop_byte_imm(DOP_TEST,DRC_REG_EAX,0);break; - case 0xa9:dyn_dop_word_imm_old(DOP_TEST,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - - // 'mov reg8/16/32,imm8/16/32' - case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7: - dyn_mov_byte_imm(opcode&3,(opcode>>2)&1,decode_fetchb()); - break; - case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf: - dyn_mov_word_imm(opcode&7);break; - break; - - // 'shiftop []/reg8,imm8/1/cl' - case 0xc0:dyn_grp2_eb(grp2_imm);break; - case 0xd0:dyn_grp2_eb(grp2_1);break; - case 0xd2:dyn_grp2_eb(grp2_cl);break; - - // 'shiftop []/reg16/32,imm8/1/cl' - case 0xc1:dyn_grp2_ev(grp2_imm);break; - case 0xd1:dyn_grp2_ev(grp2_1);break; - case 0xd3:dyn_grp2_ev(grp2_cl);break; - - // retn [param] - case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block; - case 0xc3:dyn_ret_near(0);goto finish_block; - - // les - case 0xc4: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_ES); - break; - // lds - case 0xc5: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_DS);break; - - // 'mov []/reg8/16/32,imm8/16/32' - case 0xc6:dyn_dop_ebib_mov();break; - case 0xc7:dyn_dop_eviv_mov();break; - - case 0xc8:dyn_enter();break; - case 0xc9:dyn_leave();break; - - // retf [param] - case 0xca:dyn_ret_far(decode_fetchw());goto finish_block; - case 0xcb:dyn_ret_far(0);goto finish_block; - - // int/iret - case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block; - case 0xcf:dyn_iret();goto finish_block; - -// case 0xd4: AAM missing -// case 0xd5: AAD missing - -// case 0xd6: SALC missing -// case 0xd7: XLAT missing - - -#ifdef CPU_FPU - // floating point instructions - case 0xd8: - dyn_fpu_esc0(); - break; - case 0xd9: - dyn_fpu_esc1(); - break; - case 0xda: - dyn_fpu_esc2(); - break; - case 0xdb: - dyn_fpu_esc3(); - break; - case 0xdc: - dyn_fpu_esc4(); - break; - case 0xdd: - dyn_fpu_esc5(); - break; - case 0xde: - dyn_fpu_esc6(); - break; - case 0xdf: - dyn_fpu_esc7(); - break; -#endif - - - // loop instructions - case 0xe0:dyn_loop(LOOP_NE);goto finish_block; - case 0xe1:dyn_loop(LOOP_E);goto finish_block; - case 0xe2:dyn_loop(LOOP_NONE);goto finish_block; - case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block; - - - // 'in al/ax/eax,port_imm' - case 0xe4:dyn_read_port_byte_direct(decode_fetchb());break; - case 0xe5:dyn_read_port_word_direct(decode_fetchb());break; - // 'out port_imm,al/ax/eax' - case 0xe6:dyn_write_port_byte_direct(decode_fetchb());break; - case 0xe7:dyn_write_port_word_direct(decode_fetchb());break; - - // 'in al/ax/eax,port_dx' - case 0xec:dyn_read_port_byte();break; - case 0xed:dyn_read_port_word();break; - // 'out port_dx,al/ax/eax' - case 0xee:dyn_write_port_byte();break; - case 0xef:dyn_write_port_word();break; - - - // 'call near imm16/32' - case 0xe8: - dyn_call_near_imm(); - goto finish_block; - // 'jmp near imm16/32' - case 0xe9: - dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - goto finish_block; - // 'jmp far' - case 0xea: - dyn_jmp_far_imm(); - goto finish_block; - // 'jmp short imm8' - case 0xeb: - dyn_exit_link((Bit8s)decode_fetchb()); - goto finish_block; - - - // repeat prefixes - case 0xf2: - decode.rep=REP_NZ; - goto restart_prefix; - case 0xf3: - decode.rep=REP_Z; - goto restart_prefix; - - case 0xf5: //CMC - gen_call_function_raw((void*)dynrec_cmc); - break; - case 0xf8: //CLC - gen_call_function_raw((void*)dynrec_clc); - break; - case 0xf9: //STC - gen_call_function_raw((void*)dynrec_stc); - break; - - case 0xf6:dyn_grp3_eb();break; - case 0xf7:dyn_grp3_ev();break; - - case 0xfa: //CLI - gen_call_function_raw((void *)&CPU_CLI); - dyn_check_exception(FC_RETOP); - break; - case 0xfb: //STI - gen_call_function_raw((void *)&CPU_STI); - dyn_check_exception(FC_RETOP); - if (max_opcodes<=0) max_opcodes=1; //Allow 1 extra opcode - break; - - case 0xfc: //CLD - gen_call_function_raw((void*)dynrec_cld); - break; - case 0xfd: //STD - gen_call_function_raw((void*)dynrec_std); - break; - - case 0xfe: - if (dyn_grp4_eb()) goto finish_block; - break; - case 0xff: - switch (dyn_grp4_ev()) { - case 0: - break; - case 1: - goto core_close_block; - case 2: - goto illegalopcode; - default: - break; - } - break; - - default: -#if DYN_LOG -// LOG_MSG("Dynrec unhandled opcode %X",opcode); -#endif - goto illegalopcode; - } - } - // link to next block because the maximum number of opcodes has been reached - dyn_set_eip_end(); - dyn_reduce_cycles(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); - goto finish_block; -core_close_block: - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); - goto finish_block; -illegalopcode: - // some unhandled opcode has been encountered - dyn_set_eip_last(); - dyn_reduce_cycles(); - dyn_return(BR_Opcode); // tell the core what happened - dyn_closeblock(); - goto finish_block; -finish_block: - - // setup the correct end-address - decode.page.index--; - decode.active_block->page.end=(Bit16u)decode.page.index; -// LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end); - - return decode.block; -} diff --git a/src/cpu/core_dynrec/decoder_basic.h b/src/cpu/core_dynrec/decoder_basic.h deleted file mode 100644 index e6c02e4ae..000000000 --- a/src/cpu/core_dynrec/decoder_basic.h +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* - This file provides some definitions and basic level functions - that use code generating functions from risc_?.h - Important is the function call generation including parameter - loading, the effective address calculation and the memory - access functions. -*/ - - -// instructions that use one operand -enum SingleOps { - SOP_INC,SOP_DEC, - SOP_NOT,SOP_NEG -}; - -// instructions that use two operand -enum DualOps { - DOP_ADD,DOP_ADC, - DOP_SUB,DOP_SBB, - DOP_CMP,DOP_XOR, - DOP_AND,DOP_OR, - DOP_TEST, - DOP_MOV, - DOP_XCHG -}; - -// shift and rotate functions -enum ShiftOps { - SHIFT_ROL,SHIFT_ROR, - SHIFT_RCL,SHIFT_RCR, - SHIFT_SHL,SHIFT_SHR, - SHIFT_SAL,SHIFT_SAR -}; - -// branch conditions -enum BranchTypes { - BR_O,BR_NO,BR_B,BR_NB, - BR_Z,BR_NZ,BR_BE,BR_NBE, - BR_S,BR_NS,BR_P,BR_NP, - BR_L,BR_NL,BR_LE,BR_NLE -}; - -// string instructions -enum StringOps { - STR_OUTSB=0,STR_OUTSW,STR_OUTSD, - STR_INSB=4,STR_INSW,STR_INSD, - STR_MOVSB=8,STR_MOVSW,STR_MOVSD, - STR_LODSB=12,STR_LODSW,STR_LODSD, - STR_STOSB=16,STR_STOSW,STR_STOSD, - STR_SCASB=20,STR_SCASW,STR_SCASD, - STR_CMPSB=24,STR_CMPSW,STR_CMPSD -}; - -// repeat prefix type (for string operations) -enum REP_Type { - REP_NONE=0,REP_NZ,REP_Z -}; - -// loop type -enum LoopTypes { - LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ -}; - -// rotate operand type -enum grp2_types { - grp2_1,grp2_imm,grp2_cl -}; - -// opcode mapping for group1 instructions -static DualOps grp1_table[8]={ - DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP -}; - - -// decoding information used during translation of a code block -static struct DynDecode { - PhysPt code; // pointer to next byte in the instruction stream - PhysPt code_start; // pointer to the start of the current code block - PhysPt op_start; // pointer to the start of the current instruction - bool big_op; // operand modifier - bool big_addr; // address modifier - REP_Type rep; // current repeat prefix - Bitu cycles; // number cycles used by currently translated code - bool seg_prefix_used; // segment overridden - Bit8u seg_prefix; // segment prefix (if seg_prefix_used==true) - - // block that contains the first instruction translated - CacheBlockDynRec * block; - // block that contains the current byte of the instruction stream - CacheBlockDynRec * active_block; - - // the active page (containing the current byte of the instruction stream) - struct { - CodePageHandlerDynRec * code; - Bitu index; // index to the current byte of the instruction stream - Bit8u * wmap; // write map that indicates code presence for every byte of this page - Bit8u * invmap; // invalidation map - Bitu first; // page number - } page; - - // modrm state of the current instruction (if used) - struct { - Bitu val; - Bitu mod; - Bitu rm; - Bitu reg; - } modrm; -} decode; - - -static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) { - Bit8u rdval; - //Ensure page contains memory: - if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; - - PageHandler * handler=get_tlb_readhandler(lin_addr); - if (handler->flags & PFLAG_HASCODE) { - // this is a codepage handler, and the one that we're looking for - cph=(CodePageHandlerDynRec *)handler; - return false; - } - if (handler->flags & PFLAG_NOCODE) { - if (PAGING_ForcePageInit(lin_addr)) { - handler=get_tlb_readhandler(lin_addr); - if (handler->flags & PFLAG_HASCODE) { - cph=(CodePageHandlerDynRec *)handler; - return false; - } - } - if (handler->flags & PFLAG_NOCODE) { - LOG_MSG("DYNREC:Can't run code in this page"); - cph=0; - return false; - } - } - Bitu lin_page=lin_addr>>12; - Bitu phys_page=lin_page; - // find the physical page that the linear page is mapped to - if (!PAGING_MakePhysPage(phys_page)) { - LOG_MSG("DYNREC:Can't find physpage"); - cph=0; - return false; - } - // find a free CodePage - if (!cache.free_pages) { - if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease(); - else { - // try another page to avoid clearing our source-crosspage - if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code)) - cache.used_pages->next->ClearRelease(); - else { - LOG_MSG("DYNREC:Invalid cache links"); - cache.used_pages->ClearRelease(); - } - } - } - CodePageHandlerDynRec * cpagehandler=cache.free_pages; - cache.free_pages=cache.free_pages->next; - - // adjust previous and next page pointer - cpagehandler->prev=cache.last_page; - cpagehandler->next=0; - if (cache.last_page) cache.last_page->next=cpagehandler; - cache.last_page=cpagehandler; - if (!cache.used_pages) cache.used_pages=cpagehandler; - - // initialize the code page handler and add the handler to the memory page - cpagehandler->SetupAt(phys_page,handler); - MEM_SetPageHandler(phys_page,1,cpagehandler); - PAGING_UnlinkPages(lin_page,1); - cph=cpagehandler; - return false; -} - -static void decode_advancepage(void) { - // Advance to the next page - decode.active_block->page.end=4095; - // trigger possible page fault here - decode.page.first++; - Bitu faddr=decode.page.first << 12; - mem_readb(faddr); - MakeCodePage(faddr,decode.page.code); - CacheBlockDynRec * newblock=cache_getblock(); - decode.active_block->crossblock=newblock; - newblock->crossblock=decode.active_block; - decode.active_block=newblock; - decode.active_block->page.start=0; - decode.page.code->AddCrossBlock(decode.active_block); - decode.page.wmap=decode.page.code->write_map; - decode.page.invmap=decode.page.code->invalidation_map; - decode.page.index=0; -} - -// fetch the next byte of the instruction stream -static Bit8u decode_fetchb(void) { - if (GCC_UNLIKELY(decode.page.index>=4096)) { - decode_advancepage(); - } - decode.page.wmap[decode.page.index]+=0x01; - decode.page.index++; - decode.code+=1; - return mem_readb(decode.code-1); -} -// fetch the next word of the instruction stream -static Bit16u decode_fetchw(void) { - if (GCC_UNLIKELY(decode.page.index>=4095)) { - Bit16u val=decode_fetchb(); - val|=decode_fetchb() << 8; - return val; - } - *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101; - decode.code+=2;decode.page.index+=2; - return mem_readw(decode.code-2); -} -// fetch the next dword of the instruction stream -static Bit32u decode_fetchd(void) { - if (GCC_UNLIKELY(decode.page.index>=4093)) { - Bit32u val=decode_fetchb(); - val|=decode_fetchb() << 8; - val|=decode_fetchb() << 16; - val|=decode_fetchb() << 24; - return val; - /* Advance to the next page */ - } - *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101; - decode.code+=4;decode.page.index+=4; - return mem_readd(decode.code-4); -} - -#define START_WMMEM 64 - -// adjust writemap mask to care for map holes due to special -// codefetch functions -static void INLINE decode_increase_wmapmask(Bitu size) { - Bitu mapidx; - CacheBlockDynRec* activecb=decode.active_block; - if (GCC_UNLIKELY(!activecb->cache.wmapmask)) { - // no mask memory yet allocated, start with a small buffer - activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM); - memset(activecb->cache.wmapmask,0,START_WMMEM); - activecb->cache.maskstart=decode.page.index; // start of buffer is current code position - activecb->cache.masklen=START_WMMEM; - mapidx=0; - } else { - mapidx=decode.page.index-activecb->cache.maskstart; - if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) { - // mask buffer too small, increase - Bitu newmasklen=activecb->cache.masklen*4; - if (newmasklencache.wmapmask,activecb->cache.masklen); - free(activecb->cache.wmapmask); - activecb->cache.wmapmask=tempmem; - activecb->cache.masklen=newmasklen; - } - } - // update mask entries - switch (size) { - case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break; - case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break; - case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break; - } -} - -// fetch a byte, val points to the code location if possible, -// otherwise val contains the current value read from the position -static bool decode_fetchb_imm(Bitu & val) { - if (GCC_UNLIKELY(decode.page.index>=4096)) { - decode_advancepage(); - } - // see if position is directly accessible - if (decode.page.invmap != NULL) { - if (decode.page.invmap[decode.page.index] == 0) { - // position not yet modified - val=(Bit32u)decode_fetchb(); - return false; - } - - HostPt tlb_addr=get_tlb_read(decode.code); - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(1); - decode.code++; - decode.page.index++; - return true; - } - } - // first time decoding or not directly accessible, just fetch the value - val=(Bit32u)decode_fetchb(); - return false; -} - -// fetch a word, val points to the code location if possible, -// otherwise val contains the current value read from the position -static bool decode_fetchw_imm(Bitu & val) { - if (decode.page.index<4095) { - if (decode.page.invmap != NULL) { - if ((decode.page.invmap[decode.page.index] == 0) && - (decode.page.invmap[decode.page.index + 1] == 0)) { - // position not yet modified - val=decode_fetchw(); - return false; - } - - HostPt tlb_addr=get_tlb_read(decode.code); - // see if position is directly accessible - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(2); - decode.code+=2; - decode.page.index+=2; - return true; - } - } - } - // first time decoding or not directly accessible, just fetch the value - val=decode_fetchw(); - return false; -} - -// fetch a dword, val points to the code location if possible, -// otherwise val contains the current value read from the position -static bool decode_fetchd_imm(Bitu & val) { - if (decode.page.index<4093) { - if (decode.page.invmap != NULL) { - if ((decode.page.invmap[decode.page.index] == 0) && - (decode.page.invmap[decode.page.index + 1] == 0) && - (decode.page.invmap[decode.page.index + 2] == 0) && - (decode.page.invmap[decode.page.index + 3] == 0)) { - // position not yet modified - val=decode_fetchd(); - return false; - } - - HostPt tlb_addr=get_tlb_read(decode.code); - // see if position is directly accessible - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(4); - decode.code+=4; - decode.page.index+=4; - return true; - } - } - } - // first time decoding or not directly accessible, just fetch the value - val=decode_fetchd(); - return false; -} - - -// modrm decoding helper -static void INLINE dyn_get_modrm(void) { - decode.modrm.val=decode_fetchb(); - decode.modrm.mod=(decode.modrm.val >> 6) & 3; - decode.modrm.reg=(decode.modrm.val >> 3) & 7; - decode.modrm.rm=(decode.modrm.val & 7); -} - - -#ifdef DRC_USE_SEGS_ADDR - -#define MOV_SEG_VAL_TO_HOST_REG(host_reg, seg_index) gen_mov_seg16_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_VAL(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs)) - -#define MOV_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_mov_seg32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_PHYS(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs)) -#define ADD_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_add_seg32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_PHYS(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs)) - -#else - -#define MOV_SEG_VAL_TO_HOST_REG(host_reg, seg_index) gen_mov_word_to_reg(host_reg,DRCD_SEG_VAL(seg_index),false) - -#define MOV_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_mov_word_to_reg(host_reg,DRCD_SEG_PHYS(seg_index),true) -#define ADD_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_add(host_reg,DRCD_SEG_PHYS(seg_index)) - -#endif - - -#ifdef DRC_USE_REGS_ADDR - -#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_VAL(reg_index)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define ADD_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_add_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_VAL(reg_index)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) - -#define MOV_REG_WORD16_TO_HOST_REG(host_reg, reg_index) gen_mov_regval16_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,false)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD32_TO_HOST_REG(host_reg, reg_index) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,true)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD_TO_HOST_REG(host_reg, reg_index, dword) gen_mov_regword_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,dword)) - (DRC_PTR_SIZE_IM)(&cpu_regs), dword) - -#define MOV_REG_WORD16_FROM_HOST_REG(host_reg, reg_index) gen_mov_regval16_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,false)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD32_FROM_HOST_REG(host_reg, reg_index) gen_mov_regval32_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,true)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD_FROM_HOST_REG(host_reg, reg_index, dword) gen_mov_regword_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,dword)) - (DRC_PTR_SIZE_IM)(&cpu_regs), dword) - -#define MOV_REG_BYTE_TO_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low_canuseword(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_from_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) - -#else - -#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_VAL(reg_index),true) -#define ADD_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_add(host_reg,DRCD_REG_VAL(reg_index)) - -#define MOV_REG_WORD16_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,false),false) -#define MOV_REG_WORD32_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,true),true) -#define MOV_REG_WORD_TO_HOST_REG(host_reg, reg_index, dword) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,dword),dword) - -#define MOV_REG_WORD16_FROM_HOST_REG(host_reg, reg_index) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,false),false) -#define MOV_REG_WORD32_FROM_HOST_REG(host_reg, reg_index) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,true),true) -#define MOV_REG_WORD_FROM_HOST_REG(host_reg, reg_index, dword) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,dword),dword) - -#define MOV_REG_BYTE_TO_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte)) -#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low_canuseword(host_reg,DRCD_REG_BYTE(reg_index,high_byte)) -#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_from_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte)) - -#endif - - -#define DYN_LEA_MEM_MEM(ea_reg, op1, op2, scale, imm) dyn_lea_mem_mem(ea_reg,op1,op2,scale,imm) - -#if defined(DRC_USE_REGS_ADDR) && defined(DRC_USE_SEGS_ADDR) - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_segphys_regval(ea_reg,op1_index,op2_index,scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_regval_regval(ea_reg,op1_index,op2_index,scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,op1,op2_index,scale,imm) - -#elif defined(DRC_USE_REGS_ADDR) - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,DRCD_SEG_PHYS(op1_index),op2_index,scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_regval_regval(ea_reg,op1_index,op2_index,scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,op1,op2_index,scale,imm) - -#elif defined(DRC_USE_SEGS_ADDR) - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_segphys_mem(ea_reg,op1_index,DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_REG_VAL(op1_index),DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,op1,DRCD_REG_VAL(op2_index),scale,imm) - -#else - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_SEG_PHYS(op1_index),DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_REG_VAL(op1_index),DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,op1,DRCD_REG_VAL(op2_index),scale,imm) - -#endif - - - -// adjust CPU_Cycles value -static void dyn_reduce_cycles(void) { - if (!decode.cycles) decode.cycles++; - gen_sub_direct_word(&CPU_Cycles,decode.cycles,true); -} - - -// set reg to the start of the next instruction -// set reg_eip to the start of the current instruction -static INLINE void dyn_set_eip_last_end(HostReg reg) { - gen_mov_word_to_reg(reg,®_eip,true); - gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start)); - gen_add_direct_word(®_eip,decode.op_start-decode.code_start,decode.big_op); -} - -// set reg_eip to the start of the current instruction -static INLINE void dyn_set_eip_last(void) { - gen_add_direct_word(®_eip,decode.op_start-decode.code_start,cpu.code.big); -} - -// set reg_eip to the start of the next instruction -static INLINE void dyn_set_eip_end(void) { - gen_add_direct_word(®_eip,decode.code-decode.code_start,cpu.code.big); -} - -// set reg_eip to the start of the next instruction plus an offset (imm) -static INLINE void dyn_set_eip_end(HostReg reg,Bit32u imm=0) { - gen_mov_word_to_reg(reg,®_eip,decode.big_op); - gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start+imm)); - if (!decode.big_op) gen_extend_word(false,reg); -} - - - -// the following functions generate function calls -// parameters are loaded by generating code using gen_load_param_ which -// is architecture dependent -// R=host register; I=32bit immediate value; A=address value; m=memory - -static DRC_PTR_SIZE_IM INLINE gen_call_function_R(void * func,Bitu op) { - gen_load_param_reg(op,0); - return gen_call_function_setup(func, 1); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_R3(void * func,Bitu op) { - gen_load_param_reg(op,2); - return gen_call_function_setup(func, 3, true); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_RI(void * func,Bitu op1,Bitu op2) { - gen_load_param_imm(op2,1); - gen_load_param_reg(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_RA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) { - gen_load_param_addr(op2,1); - gen_load_param_reg(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_RR(void * func,Bitu op1,Bitu op2) { - gen_load_param_reg(op2,1); - gen_load_param_reg(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IR(void * func,Bitu op1,Bitu op2) { - gen_load_param_reg(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_I(void * func,Bitu op) { - gen_load_param_imm(op,0); - return gen_call_function_setup(func, 1); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_II(void * func,Bitu op1,Bitu op2) { - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_III(void * func,Bitu op1,Bitu op2,Bitu op3) { - gen_load_param_imm(op3,2); - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 3); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) { - gen_load_param_addr(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IIR(void * func,Bitu op1,Bitu op2,Bitu op3) { - gen_load_param_reg(op3,2); - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 3); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IIIR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) { - gen_load_param_reg(op4,3); - gen_load_param_imm(op3,2); - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 4); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IRRR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) { - gen_load_param_reg(op4,3); - gen_load_param_reg(op3,2); - gen_load_param_reg(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 4); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_m(void * func,Bitu op) { - gen_load_param_mem(op,2); - return gen_call_function_setup(func, 3, true); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_mm(void * func,Bitu op1,Bitu op2) { - gen_load_param_mem(op2,3); - gen_load_param_mem(op1,2); - return gen_call_function_setup(func, 4, true); -} - - - -enum save_info_type {db_exception, cycle_check, string_break}; - - -// function that is called on exceptions -static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub) { - reg_eip+=eip_add; - CPU_Cycles-=cycle_sub; - if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock; - CPU_Exception(cpu.exception.which,cpu.exception.error); - return BR_Normal; -} - - -// array with information about code that is generated at the -// end of a cache block because it is rarely reached (like exceptions) -static struct { - save_info_type type; - DRC_PTR_SIZE_IM branch_pos; - Bit32u eip_change; - Bitu cycles; -} save_info_dynrec[512]; - -Bitu used_save_info_dynrec=0; - - -// return from current block, with returncode -static void dyn_return(BlockReturn retcode,bool ret_exception=false) { - if (!ret_exception) { - gen_mov_dword_to_reg_imm(FC_RETOP,retcode); - } - gen_return_function(); -} - -static void dyn_run_code(void) { - gen_run_code(); - gen_return_function(); -} - -// fill in code at the end of the block that contains rarely-executed code -// which is executed conditionally (like exceptions) -static void dyn_fill_blocks(void) { - for (Bitu sct=0; sctcache.start,decode.block->cache.size); -} - - -// add a check that can branch to the exception handling -static void dyn_check_exception(HostReg reg) { - save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_nonzero(reg,false); - if (!decode.cycles) decode.cycles++; - save_info_dynrec[used_save_info_dynrec].cycles=decode.cycles; - // in case of an exception eip will point to the start of the current instruction - save_info_dynrec[used_save_info_dynrec].eip_change=decode.op_start-decode.code_start; - if (!cpu.code.big) save_info_dynrec[used_save_info_dynrec].eip_change&=0xffff; - save_info_dynrec[used_save_info_dynrec].type=db_exception; - used_save_info_dynrec++; -} - - - -bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) DRC_FC; -bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *((Bit8u*)(&core_dynrec.readdata))=host_readb(tlb_addr+address); - return false; - } else { - return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dynrec.readdata)); - } -} - -bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) DRC_FC; -bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writeb(tlb_addr+address,val); - return false; - } else return get_tlb_writehandler(address)->writeb_checked(address,val); -} - -bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) DRC_FC; -bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *((Bit16u*)(&core_dynrec.readdata))=host_readw(tlb_addr+address); - return false; - } else return get_tlb_readhandler(address)->readw_checked(address, (Bit16u*)(&core_dynrec.readdata)); - } else return mem_unalignedreadw_checked(address, ((Bit16u*)(&core_dynrec.readdata))); -} - -bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) DRC_FC; -bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *((Bit32u*)(&core_dynrec.readdata))=host_readd(tlb_addr+address); - return false; - } else return get_tlb_readhandler(address)->readd_checked(address, (Bit32u*)(&core_dynrec.readdata)); - } else return mem_unalignedreadd_checked(address, ((Bit32u*)(&core_dynrec.readdata))); -} - -bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) DRC_FC; -bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writew(tlb_addr+address,val); - return false; - } else return get_tlb_writehandler(address)->writew_checked(address,val); - } else return mem_unalignedwritew_checked(address,val); -} - -bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) DRC_FC; -bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writed(tlb_addr+address,val); - return false; - } else return get_tlb_writehandler(address)->writed_checked(address,val); - } else return mem_unalignedwrited_checked(address,val); -} - - -// functions that enable access to the memory - -// read a byte from a given address and store it in reg_dst -static void dyn_read_byte(HostReg reg_addr,HostReg reg_dst) { - gen_mov_regs(FC_OP1,reg_addr); - gen_call_function_raw((void *)&mem_readb_checked_drc); - dyn_check_exception(FC_RETOP); - gen_mov_byte_to_reg_low(reg_dst,&core_dynrec.readdata); -} -static void dyn_read_byte_canuseword(HostReg reg_addr,HostReg reg_dst) { - gen_mov_regs(FC_OP1,reg_addr); - gen_call_function_raw((void *)&mem_readb_checked_drc); - dyn_check_exception(FC_RETOP); - gen_mov_byte_to_reg_low_canuseword(reg_dst,&core_dynrec.readdata); -} - -// write a byte from reg_val into the memory given by the address -static void dyn_write_byte(HostReg reg_addr,HostReg reg_val) { - gen_mov_regs(FC_OP2,reg_val); - gen_mov_regs(FC_OP1,reg_addr); - gen_call_function_raw((void *)&mem_writeb_checked_drc); - dyn_check_exception(FC_RETOP); -} - -// read a 32bit (dword=true) or 16bit (dword=false) value -// from a given address and store it in reg_dst -static void dyn_read_word(HostReg reg_addr,HostReg reg_dst,bool dword) { - gen_mov_regs(FC_OP1,reg_addr); - if (dword) gen_call_function_raw((void *)&mem_readd_checked_drc); - else gen_call_function_raw((void *)&mem_readw_checked_drc); - dyn_check_exception(FC_RETOP); - gen_mov_word_to_reg(reg_dst,&core_dynrec.readdata,dword); -} - -// write a 32bit (dword=true) or 16bit (dword=false) value -// from reg_val into the memory given by the address -static void dyn_write_word(HostReg reg_addr,HostReg reg_val,bool dword) { -// if (!dword) gen_extend_word(false,reg_val); - gen_mov_regs(FC_OP2,reg_val); - gen_mov_regs(FC_OP1,reg_addr); - if (dword) gen_call_function_raw((void *)&mem_writed_checked_drc); - else gen_call_function_raw((void *)&mem_writew_checked_drc); - dyn_check_exception(FC_RETOP); -} - - - -// effective address calculation helper, op2 has to be present! -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -static void dyn_lea_mem_mem(HostReg ea_reg,void* op1,void* op2,Bitu scale,Bits imm) { - if (scale || imm) { - if (op1!=NULL) { - gen_mov_word_to_reg(ea_reg,op1,true); - gen_mov_word_to_reg(TEMP_REG_DRC,op2,true); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - gen_mov_word_to_reg(ea_reg,op2,true); - gen_lea(ea_reg,scale,imm); - } - } else { - gen_mov_word_to_reg(ea_reg,op2,true); - if (op1!=NULL) gen_add(ea_reg,op1); - } -} - -#ifdef DRC_USE_REGS_ADDR -// effective address calculation helper -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op1 is cpu_regs[op1_index], op2 is cpu_regs[op2_index] -static void dyn_lea_regval_regval(HostReg ea_reg,Bitu op1_index,Bitu op2_index,Bitu scale,Bits imm) { - if (scale || imm) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op1_index); - MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - ADD_REG_VAL_TO_HOST_REG(ea_reg,op1_index); - } -} - -// effective address calculation helper -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op2 is cpu_regs[op2_index] -static void dyn_lea_mem_regval(HostReg ea_reg,void* op1,Bitu op2_index,Bitu scale,Bits imm) { - if (scale || imm) { - if (op1!=NULL) { - gen_mov_word_to_reg(ea_reg,op1,true); - MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - gen_lea(ea_reg,scale,imm); - } - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - if (op1!=NULL) gen_add(ea_reg,op1); - } -} -#endif - -#ifdef DRC_USE_SEGS_ADDR -#ifdef DRC_USE_REGS_ADDR -// effective address calculation helper -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op1 is Segs[op1_index], op2 is cpu_regs[op2_index] -static void dyn_lea_segphys_regval(HostReg ea_reg,Bitu op1_index,Bitu op2_index,Bitu scale,Bits imm) { - if (scale || imm) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - ADD_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - } -} - -#else - -// effective address calculation helper, op2 has to be present! -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op1 is Segs[op1_index] -static void dyn_lea_segphys_mem(HostReg ea_reg,Bitu op1_index,void* op2,Bitu scale,Bits imm) { - if (scale || imm) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - gen_mov_word_to_reg(TEMP_REG_DRC,op2,true); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - gen_mov_word_to_reg(ea_reg,op2,true); - ADD_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - } -} -#endif -#endif - -// calculate the effective address and store it in ea_reg -static void dyn_fill_ea(HostReg ea_reg,bool addseg=true) { - Bit8u seg_base=DRC_SEG_DS; - if (!decode.big_addr) { - Bits imm; - switch (decode.modrm.mod) { - case 0:imm=0;break; - case 1:imm=(Bit8s)decode_fetchb();break; - case 2:imm=(Bit16s)decode_fetchw();break; - } - switch (decode.modrm.rm) { - case 0:// BX+SI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBX,DRC_REG_ESI,0,imm); - break; - case 1:// BX+DI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBX,DRC_REG_EDI,0,imm); - break; - case 2:// BP+SI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBP,DRC_REG_ESI,0,imm); - seg_base=DRC_SEG_SS; - break; - case 3:// BP+DI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBP,DRC_REG_EDI,0,imm); - seg_base=DRC_SEG_SS; - break; - case 4:// SI - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_ESI); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - break; - case 5:// DI - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EDI); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - break; - case 6:// imm/BP - if (!decode.modrm.mod) { - imm=decode_fetchw(); - gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); - goto skip_extend_word; - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EBP); - gen_add_imm(ea_reg,(Bit32u)imm); - seg_base=DRC_SEG_SS; - } - break; - case 7: // BX - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EBX); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - break; - } - // zero out the high 16bit so ea_reg can be used as full register - gen_extend_word(false,ea_reg); -skip_extend_word: - if (addseg) { - // add the physical segment value if requested - ADD_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - } - } else { - Bits imm=0; - Bit8u base_reg; - Bit8u scaled_reg; - Bitu scale=0; - switch (decode.modrm.rm) { - case 0:base_reg=DRC_REG_EAX;break; - case 1:base_reg=DRC_REG_ECX;break; - case 2:base_reg=DRC_REG_EDX;break; - case 3:base_reg=DRC_REG_EBX;break; - case 4: // SIB - { - Bitu sib=decode_fetchb(); - bool scaled_reg_used=false; - static Bit8u scaledtable[8]={ - DRC_REG_EAX,DRC_REG_ECX,DRC_REG_EDX,DRC_REG_EBX, - 0,DRC_REG_EBP,DRC_REG_ESI,DRC_REG_EDI - }; - // see if scaling should be used and which register is to be scaled in this case - if (((sib >> 3) &7)!=4) scaled_reg_used=true; - scaled_reg=scaledtable[(sib >> 3) &7]; - scale=(sib >> 6); - - switch (sib & 7) { - case 0:base_reg=DRC_REG_EAX;break; - case 1:base_reg=DRC_REG_ECX;break; - case 2:base_reg=DRC_REG_EDX;break; - case 3:base_reg=DRC_REG_EBX;break; - case 4:base_reg=DRC_REG_ESP;seg_base=DRC_SEG_SS;break; - case 5: - if (decode.modrm.mod) { - base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS; - } else { - // no basereg, maybe scalereg - Bitu val; - // try to get a pointer to the next dword code position - if (decode_fetchd_imm(val)) { - // succeeded, use the pointer to avoid code invalidation - if (!addseg) { - if (!scaled_reg_used) { - gen_mov_word_to_reg(ea_reg,(void*)val,true); - } else { - DYN_LEA_MEM_REG_VAL(ea_reg,NULL,scaled_reg,scale,0); - gen_add(ea_reg,(void*)val); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,0); - } - gen_add(ea_reg,(void*)val); - } - return; - } - // couldn't get a pointer, use the current value - imm=(Bit32s)val; - - if (!addseg) { - if (!scaled_reg_used) { - gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_MEM_REG_VAL(ea_reg,NULL,scaled_reg,scale,imm); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,imm); - } - } - - return; - } - break; - case 6:base_reg=DRC_REG_ESI;break; - case 7:base_reg=DRC_REG_EDI;break; - } - // basereg, maybe scalereg - switch (decode.modrm.mod) { - case 1: - imm=(Bit8s)decode_fetchb(); - break; - case 2: { - Bitu val; - // try to get a pointer to the next dword code position - if (decode_fetchd_imm(val)) { - // succeeded, use the pointer to avoid code invalidation - if (!addseg) { - if (!scaled_reg_used) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } else { - DYN_LEA_REG_VAL_REG_VAL(ea_reg,base_reg,scaled_reg,scale,0); - gen_add(ea_reg,(void*)val); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,0); - } - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } - return; - } - // couldn't get a pointer, use the current value - imm=(Bit32s)val; - break; - } - } - - if (!addseg) { - if (!scaled_reg_used) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_REG_VAL_REG_VAL(ea_reg,base_reg,scaled_reg,scale,imm); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,imm); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - } - } - - return; - } - break; // SIB Break - case 5: - if (decode.modrm.mod) { - base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS; - } else { - // no base, no scalereg - - imm=(Bit32s)decode_fetchd(); - if (!addseg) { - gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); - } else { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } - - return; - } - break; - case 6:base_reg=DRC_REG_ESI;break; - case 7:base_reg=DRC_REG_EDI;break; - } - - // no scalereg, but basereg - - switch (decode.modrm.mod) { - case 1: - imm=(Bit8s)decode_fetchb(); - break; - case 2: { - Bitu val; - // try to get a pointer to the next dword code position - if (decode_fetchd_imm(val)) { - // succeeded, use the pointer to avoid code invalidation - if (!addseg) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } else { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } - return; - } - // couldn't get a pointer, use the current value - imm=(Bit32s)val; - break; - } - } - - if (!addseg) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } else { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } - } -} - - - -// add code that checks if port access is allowed -// the port is given in a register -static void dyn_add_iocheck(HostReg reg_port,Bitu access_size) { - if (cpu.pmode) { - gen_call_function_RI((void *)&CPU_IO_Exception,reg_port,access_size); - dyn_check_exception(FC_RETOP); - } -} - -// add code that checks if port access is allowed -// the port is a constant -static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) { - if (cpu.pmode) { - gen_call_function_II((void *)&CPU_IO_Exception,accessed_port,access_size); - dyn_check_exception(FC_RETOP); - } -} - - - -// save back the address register -static void gen_protect_addr_reg(void) { -#ifdef DRC_PROTECT_ADDR_REG - gen_mov_word_from_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true); -#endif -} - -// restore the address register -static void gen_restore_addr_reg(void) { -#ifdef DRC_PROTECT_ADDR_REG - gen_mov_word_to_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true); -#endif -} - -// save back an arbitrary register -static void gen_protect_reg(HostReg reg) { - gen_mov_word_from_reg(reg,&core_dynrec.protected_regs[reg],true); -} - -// restore an arbitrary register -static void gen_restore_reg(HostReg reg) { - gen_mov_word_to_reg(reg,&core_dynrec.protected_regs[reg],true); -} - -// restore an arbitrary register into a different register -static void gen_restore_reg(HostReg reg,HostReg dest_reg) { - gen_mov_word_to_reg(dest_reg,&core_dynrec.protected_regs[reg],true); -} - - - -// flags optimization functions -// they try to find out if a function can be replaced by another -// one that does not generate any flags at all - -static Bitu mf_functions_num=0; -static struct { - Bit8u* pos; - void* fct_ptr; - Bitu ftype; -} mf_functions[64]; - -static void InitFlagsOptimization(void) { - mf_functions_num=0; -} - -// replace all queued functions with their simpler variants -// because the current instruction destroys all condition flags and -// the flags are not required before -static void InvalidateFlags(void) { -#ifdef DRC_FLAGS_INVALIDATION - for (Bitu ct=0; ct>2)&1); - dyn_dop_byte_gencall(op); - - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_ebgb_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_write_byte(FC_ADDR,FC_TMP_BA1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_ebib_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); - dyn_write_byte(FC_ADDR,FC_TMP_BA1); - } else { - gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_ebgb_xchg(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_TMP_BA2); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_gbeb(DualOps op) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_byte_canuseword(FC_ADDR,FC_OP2); - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } -} - -static void dyn_dop_gbeb_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } -} - -static void dyn_dop_evgv(DualOps op) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - gen_protect_addr_reg(); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_dop_evgv_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_dop_eviv_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); - dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_dop_evgv_xchg(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - - gen_protect_reg(FC_OP1); - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_OP2,decode.big_op); - gen_restore_reg(FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_xchg_ax(Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP2,DRC_REG_EAX,decode.big_op); -} - -static void dyn_dop_gvev(DualOps op) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); - } - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); - } -} - -static void dyn_dop_gvev_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } -} - -static void dyn_dop_byte_imm(DualOps op,Bit8u reg,Bit8u idx) { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx); - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx); -} - -static void dyn_dop_byte_imm_mem(DualOps op,Bit8u reg,Bit8u idx) { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx); - Bitu val; - if (decode_fetchb_imm(val)) { - gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); - } else { - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,(Bit8u)val); - } - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx); -} - -static void dyn_prep_word_imm(Bit8u reg) { - Bitu val; - if (decode.big_op) { - if (decode_fetchd_imm(val)) { - gen_mov_word_to_reg(FC_OP2,(void*)val,true); - return; - } - } else { - if (decode_fetchw_imm(val)) { - gen_mov_word_to_reg(FC_OP2,(void*)val,false); - return; - } - } - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)val); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)val); -} - -static void dyn_dop_word_imm(DualOps op,Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - dyn_prep_word_imm(reg); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - -static void dyn_dop_word_imm_old(DualOps op,Bit8u reg,Bitu imm) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - -static void dyn_mov_byte_imm(Bit8u reg,Bit8u idx,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,imm); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,reg,idx); -} - -static void dyn_mov_word_imm(Bit8u reg) { - Bitu val; - if (decode.big_op) { - if (decode_fetchd_imm(val)) { - gen_mov_word_to_reg(FC_OP1,(void*)val,true); - MOV_REG_WORD32_FROM_HOST_REG(FC_OP1,reg); - return; - } - } else { - if (decode_fetchw_imm(val)) { - gen_mov_word_to_reg(FC_OP1,(void*)val,false); - MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,reg); - return; - } - } - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)val); - else gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)val); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op); -} - - -static void dyn_sop_word(SingleOps op,Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - dyn_sop_word_gencall(op,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - - -static void dyn_mov_byte_al_direct(Bitu imm) { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - gen_add_imm(FC_ADDR,imm); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0); -} - -static void dyn_mov_byte_ax_direct(Bitu imm) { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - gen_add_imm(FC_ADDR,imm); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); -} - -static void dyn_mov_byte_direct_al() { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - if (decode.big_addr) { - Bitu val; - if (decode_fetchd_imm(val)) { - gen_add(FC_ADDR,(void*)val); - } else { - gen_add_imm(FC_ADDR,(Bit32u)val); - } - } else { - gen_add_imm(FC_ADDR,decode_fetchw()); - } - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0); - dyn_write_byte(FC_ADDR,FC_TMP_BA1); -} - -static void dyn_mov_byte_direct_ax(Bitu imm) { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - gen_add_imm(FC_ADDR,imm); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); - dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); -} - - -static void dyn_movx_ev_gb(bool sign) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - gen_extend_byte(sign,FC_TMP_BA1); - MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - gen_extend_byte(sign,FC_TMP_BA1); - MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op); - } -} - -static void dyn_movx_ev_gw(bool sign) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,false); - gen_extend_word(sign,FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_OP1,decode.modrm.rm); - gen_extend_word(sign,FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } -} - - -static void dyn_mov_ev_seg(void) { - dyn_get_modrm(); - MOV_SEG_VAL_TO_HOST_REG(FC_OP1,decode.modrm.reg); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_write_word(FC_ADDR,FC_OP1,false); - } else { - if (decode.big_op) gen_extend_word(false,FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_lea(void) { - dyn_get_modrm(); - dyn_fill_ea(FC_ADDR,false); - MOV_REG_WORD_FROM_HOST_REG(FC_ADDR,decode.modrm.reg,decode.big_op); -} - - -static void dyn_push_seg(Bit8u seg) { - MOV_SEG_VAL_TO_HOST_REG(FC_OP1,seg); - if (decode.big_op) { - gen_extend_word(false,FC_OP1); - gen_call_function_raw((void*)&dynrec_push_dword); - } else { - gen_call_function_raw((void*)&dynrec_push_word); - } -} - -static void dyn_pop_seg(Bit8u seg) { - gen_call_function_II((void *)&CPU_PopSeg,seg,decode.big_op); - dyn_check_exception(FC_RETOP); -} - -static void dyn_push_reg(Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); -} - -static void dyn_pop_reg(Bit8u reg) { - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else gen_call_function_raw((void*)&dynrec_pop_word); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - -static void dyn_push_byte_imm(Bit8s imm) { - gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); -} - -static void dyn_push_word_imm(Bitu imm) { - if (decode.big_op) { - gen_mov_dword_to_reg_imm(FC_OP1,imm); - gen_call_function_raw((void*)&dynrec_push_dword); - } else { - gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)imm); - gen_call_function_raw((void*)&dynrec_push_word); - } -} - -static void dyn_pop_ev(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { -/* dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); // dummy read to trigger possible page faults */ - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else gen_call_function_raw((void*)&dynrec_pop_word); - dyn_fill_ea(FC_ADDR); -// gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else gen_call_function_raw((void*)&dynrec_pop_word); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_segprefix(Bit8u seg) { -// if (GCC_UNLIKELY(decode.seg_prefix_used)) IllegalOptionDynrec("dyn_segprefix"); - decode.seg_prefix=seg; - decode.seg_prefix_used=true; -} - - static void dyn_mov_seg_ev(void) { - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.reg==DRC_SEG_CS)) IllegalOptionDynrec("dyn_mov_seg_ev"); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - } - gen_call_function_IR((void *)&CPU_SetSegGeneral,decode.modrm.reg,FC_RETOP); - dyn_check_exception(FC_RETOP); -} - -static void dyn_load_seg_off_ea(Bit8u seg) { - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - gen_protect_reg(FC_OP1); - - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,decode.big_op ? 4:2); - dyn_read_word(FC_ADDR,FC_RETOP,false); - - gen_call_function_IR((void *)&CPU_SetSegGeneral,seg,FC_RETOP); - dyn_check_exception(FC_RETOP); - - gen_restore_reg(FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - IllegalOptionDynrec("dyn_load_seg_off_ea"); - } -} - - - -static void dyn_imul_gvev(Bitu immsize) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - - switch (immsize) { - case 0: - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - break; - case 1: - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); - break; - case 2: - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); - break; - case 4: - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32s)decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)((Bit32s)decode_fetchd())); - break; - } - - if (decode.big_op) gen_call_function_raw((void*)dynrec_dimul_dword); - else gen_call_function_raw((void*)dynrec_dimul_word); - - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); -} - -static void dyn_dshift_ev_gv(bool left,bool immediate) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - if (immediate) gen_mov_byte_to_reg_low_imm(FC_OP3,decode_fetchb()); - else MOV_REG_BYTE_TO_HOST_REG_LOW(FC_OP3,DRC_REG_ECX,0); - if (decode.big_op) dyn_dpshift_dword_gencall(left); - else dyn_dpshift_word_gencall(left); - - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_grp1_eb_ib(void) { - dyn_get_modrm(); - DualOps op=grp1_table[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); - dyn_dop_byte_gencall(op); - - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } - } else { - dyn_dop_byte_imm_mem(op,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_grp1_ev_iv(bool withbyte) { - dyn_get_modrm(); - DualOps op=grp1_table[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - - if (!withbyte) { - dyn_prep_word_imm(FC_OP2); - } else { - Bits imm=(Bit8s)decode_fetchb(); - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); - } - - dyn_dop_word_gencall(op,decode.big_op); - - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } - } else { - if (!withbyte) { - dyn_dop_word_imm(op,decode.modrm.rm); - } else { - Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); - dyn_dop_word_imm_old(op,decode.modrm.rm,imm); - } - } -} - - -static void dyn_grp2_eb(grp2_types type) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } - switch (type) { - case grp2_1: - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); - dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); - break; - case grp2_imm: { - Bit8u imm=decode_fetchb(); - if (imm) { - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); - dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); - } else return; - } - break; - case grp2_cl: - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0); - gen_and_imm(FC_OP2,0x1f); - dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); - break; - } - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_grp2_ev(grp2_types type) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - switch (type) { - case grp2_1: - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - break; - case grp2_imm: { - Bitu val; - if (decode_fetchb_imm(val)) { - gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); - gen_and_imm(FC_OP2,0x1f); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - break; - } - Bit8u imm=(Bit8u)val; - if (imm) { - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - } else return; - } - break; - case grp2_cl: - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0); - gen_and_imm(FC_OP2,0x1f); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - break; - } - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_grp3_eb(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } - switch (decode.modrm.reg) { - case 0x0: // test eb,ib - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); - dyn_dop_byte_gencall(DOP_TEST); - return; - case 0x2: // NOT Eb - dyn_sop_byte_gencall(SOP_NOT); - break; - case 0x3: // NEG Eb - dyn_sop_byte_gencall(SOP_NEG); - break; - case 0x4: // mul Eb - gen_call_function_raw((void*)&dynrec_mul_byte); - return; - case 0x5: // imul Eb - gen_call_function_raw((void*)&dynrec_imul_byte); - return; - case 0x6: // div Eb - gen_call_function_raw((void*)&dynrec_div_byte); - dyn_check_exception(FC_RETOP); - return; - case 0x7: // idiv Eb - gen_call_function_raw((void*)&dynrec_idiv_byte); - dyn_check_exception(FC_RETOP); - return; - } - // Save the result if memory op - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_grp3_ev(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - switch (decode.modrm.reg) { - case 0x0: // test ev,iv - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP2,decode_fetchw()); - dyn_dop_word_gencall(DOP_TEST,decode.big_op); - return; - case 0x2: // NOT Ev - dyn_sop_word_gencall(SOP_NOT,decode.big_op); - break; - case 0x3: // NEG Eb - dyn_sop_word_gencall(SOP_NEG,decode.big_op); - break; - case 0x4: // mul Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_mul_dword); - else gen_call_function_raw((void*)&dynrec_mul_word); - return; - case 0x5: // imul Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_imul_dword); - else gen_call_function_raw((void*)&dynrec_imul_word); - return; - case 0x6: // div Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_div_dword); - else gen_call_function_raw((void*)&dynrec_div_word); - dyn_check_exception(FC_RETOP); - return; - case 0x7: // idiv Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_idiv_dword); - else gen_call_function_raw((void*)&dynrec_idiv_word); - dyn_check_exception(FC_RETOP); - return; - } - // Save the result if memory op - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static bool dyn_grp4_eb(void) { - dyn_get_modrm(); - switch (decode.modrm.reg) { - case 0x0://INC Eb - case 0x1://DEC Eb - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } - break; - case 0x7: //CALBACK Iw - gen_mov_direct_dword(&core_dynrec.callback,decode_fetchw()); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_CallBack); - dyn_closeblock(); - return true; - default: - IllegalOptionDynrec("dyn_grp4_eb"); - break; - } - return false; -} - -static Bitu dyn_grp4_ev(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if ((decode.modrm.reg<2) || (decode.modrm.reg==3) || (decode.modrm.reg==5)) gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - switch (decode.modrm.reg) { - case 0x0://INC Ev - case 0x1://DEC Ev - dyn_sop_word_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op); - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } - break; - case 0x2: // CALL Ev - gen_mov_regs(FC_ADDR,FC_OP1); - gen_protect_addr_reg(); - gen_mov_word_to_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - gen_add_imm(FC_OP1,(Bit32u)(decode.code-decode.code_start)); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); - - gen_restore_addr_reg(); - gen_mov_word_from_reg(FC_ADDR,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - return 1; - case 0x4: // JMP Ev - gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - return 1; - case 0x3: // CALL Ep - case 0x5: // JMP Ep - if (!decode.big_op) gen_extend_word(false,FC_OP1); - if (decode.modrm.mod<3) gen_restore_addr_reg(); - gen_protect_reg(FC_OP1); - gen_add_imm(FC_ADDR,decode.big_op?4:2); - dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); - gen_extend_word(false,FC_OP2); - - dyn_set_eip_last_end(FC_RETOP); - gen_restore_reg(FC_OP1,FC_ADDR); - gen_call_function_IRRR(decode.modrm.reg == 3 ? (void*)(&CPU_CALL) : (void*)(&CPU_JMP), - decode.big_op,FC_OP2,FC_ADDR,FC_RETOP); - return 1; - case 0x6: // PUSH Ev - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); - break; - default: -// IllegalOptionDynrec("dyn_grp4_ev"); - return 2; - } - return 0; -} - - -static bool dyn_grp6(void) { - dyn_get_modrm(); - switch (decode.modrm.reg) { - case 0x00: // SLDT - case 0x01: // STR - if (decode.modrm.reg==0) gen_call_function_raw((void*)CPU_SLDT); - else gen_call_function_raw((void*)CPU_STR); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_write_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm); - } - break; - case 0x02: // LLDT - case 0x03: // LTR - case 0x04: // VERR - case 0x05: // VERW - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - } - gen_extend_word(false,FC_RETOP); - switch (decode.modrm.reg) { - case 0x02: // LLDT -// if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); - if (cpu.cpl) E_Exit("lldt cpl>0"); - gen_call_function_R((void*)CPU_LLDT,FC_RETOP); - dyn_check_exception(FC_RETOP); - break; - case 0x03: // LTR -// if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); - if (cpu.cpl) E_Exit("ltr cpl>0"); - gen_call_function_R((void*)CPU_LTR,FC_RETOP); - dyn_check_exception(FC_RETOP); - break; - case 0x04: // VERR - gen_call_function_R((void*)CPU_VERR,FC_RETOP); - break; - case 0x05: // VERW - gen_call_function_R((void*)CPU_VERW,FC_RETOP); - break; - } - break; - default: IllegalOptionDynrec("dyn_grp6"); - } - return false; -} - -static bool dyn_grp7(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - switch (decode.modrm.reg) { - case 0x00: // SGDT - gen_call_function_raw((void*)CPU_SGDT_limit); - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,false); - gen_call_function_raw((void*)CPU_SGDT_base); - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,2); - dyn_write_word(FC_ADDR,FC_RETOP,true); - break; - case 0x01: // SIDT - gen_call_function_raw((void*)CPU_SIDT_limit); - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,false); - gen_call_function_raw((void*)CPU_SIDT_base); - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,2); - dyn_write_word(FC_ADDR,FC_RETOP,true); - break; - case 0x02: // LGDT - case 0x03: // LIDT -// if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("lgdt nonpriviledged"); - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,false); - gen_extend_word(false,FC_OP1); - gen_protect_reg(FC_OP1); - - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,2); - dyn_read_word(FC_ADDR,FC_OP2,true); - if (!decode.big_op) gen_and_imm(FC_OP2,0xffffff); - - gen_restore_reg(FC_OP1); - if (decode.modrm.reg==2) gen_call_function_RR((void*)CPU_LGDT,FC_OP1,FC_OP2); - else gen_call_function_RR((void*)CPU_LIDT,FC_OP1,FC_OP2); - break; - case 0x04: // SMSW - gen_call_function_raw((void*)CPU_SMSW); - dyn_fill_ea(FC_ADDR); - dyn_write_word(FC_ADDR,FC_RETOP,false); - break; - case 0x06: // LMSW - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - gen_call_function_R((void*)CPU_LMSW,FC_RETOP); - dyn_check_exception(FC_RETOP); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); - return true; - case 0x07: // INVLPG -// if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("invlpg nonpriviledged"); - gen_call_function_raw((void*)PAGING_ClearTLB); - break; - default: IllegalOptionDynrec("dyn_grp7_1"); - } - } else { - switch (decode.modrm.reg) { - case 0x04: // SMSW - gen_call_function_raw((void*)CPU_SMSW); - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm); - break; - case 0x06: // LMSW - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - gen_call_function_R((void*)CPU_LMSW,FC_RETOP); - dyn_check_exception(FC_RETOP); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); - return true; - default: IllegalOptionDynrec("dyn_grp7_2"); - } - } - return false; -} - - -/* -static void dyn_larlsl(bool is_lar) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - } - gen_extend_word(false,FC_RETOP); - if (is_lar) gen_call_function((void*)CPU_LAR,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); - else gen_call_function((void*)CPU_LSL,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); - DRC_PTR_SIZE_IM brnz=gen_create_branch_on_nonzero(FC_RETOP,true); - gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); - MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - gen_fill_branch(brnz); -} -*/ - - -static void dyn_mov_from_crx(void) { - dyn_get_modrm(); - gen_call_function_IA((void*)CPU_READ_CRX,decode.modrm.reg,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); - dyn_check_exception(FC_RETOP); - gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); - MOV_REG_WORD32_FROM_HOST_REG(FC_OP2,decode.modrm.rm); -} - -static void dyn_mov_to_crx(void) { - dyn_get_modrm(); - MOV_REG_WORD32_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - gen_call_function_IR((void*)CPU_WRITE_CRX,decode.modrm.reg,FC_RETOP); - dyn_check_exception(FC_RETOP); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); -} - - -static void dyn_cbw(void) { - if (decode.big_op) { - MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX); - gen_call_function_raw((void *)&dynrec_cwde); - MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,DRC_REG_EAX,0); - gen_call_function_raw((void *)&dynrec_cbw); - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX); - } -} - -static void dyn_cwd(void) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); - if (decode.big_op) { - gen_call_function_raw((void *)&dynrec_cdq); - MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX); - } else { - gen_call_function_raw((void *)&dynrec_cwd); - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX); - } -} - -static void dyn_sahf(void) { - MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX); - gen_call_function_raw((void *)&dynrec_sahf); - InvalidateFlags(); -} - - -static void dyn_exit_link(Bits eip_change) { - gen_add_direct_word(®_eip,(decode.code-decode.code_start)+eip_change,decode.big_op); - dyn_reduce_cycles(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - - -static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { - Bitu eip_base=decode.code-decode.code_start; - dyn_reduce_cycles(); - - dyn_branchflag_to_reg(btype); - DRC_PTR_SIZE_IM data=gen_create_branch_on_nonzero(FC_RETOP,true); - - // Branch not taken - gen_add_direct_word(®_eip,eip_base,decode.big_op); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - gen_fill_branch(data); - - // Branch taken - gen_add_direct_word(®_eip,eip_base+eip_add,decode.big_op); - gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - -/* -static void dyn_set_byte_on_condition(BranchTypes btype) { - dyn_get_modrm(); - dyn_branchflag_to_reg(btype); - gen_and_imm(FC_RETOP,1); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} -*/ - -static void dyn_loop(LoopTypes type) { - dyn_reduce_cycles(); - Bits eip_add=(Bit8s)decode_fetchb(); - Bitu eip_base=decode.code-decode.code_start; - DRC_PTR_SIZE_IM branch1=0; - DRC_PTR_SIZE_IM branch2=0; - switch (type) { - case LOOP_E: - dyn_branchflag_to_reg(BR_NZ); - branch1=gen_create_branch_on_nonzero(FC_RETOP,true); - break; - case LOOP_NE: - dyn_branchflag_to_reg(BR_Z); - branch1=gen_create_branch_on_nonzero(FC_RETOP,true); - break; - } - switch (type) { - case LOOP_E: - case LOOP_NE: - case LOOP_NONE: - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - gen_add_imm(FC_OP1,(Bit32u)(-1)); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - branch2=gen_create_branch_on_zero(FC_OP1,decode.big_addr); - break; - case LOOP_JCXZ: - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - branch2=gen_create_branch_on_nonzero(FC_OP1,decode.big_addr); - break; - } - gen_add_direct_word(®_eip,eip_base+eip_add,true); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - if (branch1) { - gen_fill_branch(branch1); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - gen_add_imm(FC_OP1,(Bit32u)(-1)); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - } - // Branch taken - gen_fill_branch(branch2); - gen_add_direct_word(®_eip,eip_base,decode.big_op); - gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - - -static void dyn_ret_near(Bitu bytes) { - dyn_reduce_cycles(); - - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else { - gen_call_function_raw((void*)&dynrec_pop_word); - gen_extend_word(false,FC_RETOP); - } - gen_mov_word_from_reg(FC_RETOP,decode.big_op?(void*)(®_eip):(void*)(®_ip),true); - - if (bytes) gen_add_direct_word(®_esp,bytes,true); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_call_near_imm(void) { - Bits imm; - if (decode.big_op) imm=(Bit32s)decode_fetchd(); - else imm=(Bit16s)decode_fetchw(); - dyn_set_eip_end(FC_OP1); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); - - dyn_set_eip_end(FC_OP1,imm); - gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - - dyn_reduce_cycles(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - -static void dyn_ret_far(Bitu bytes) { - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIR((void*)&CPU_RET,decode.big_op,bytes,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_call_far_imm(void) { - Bitu sel,off; - off=decode.big_op ? decode_fetchd() : decode_fetchw(); - sel=decode_fetchw(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIIR((void*)&CPU_CALL,decode.big_op,sel,off,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_jmp_far_imm(void) { - Bitu sel,off; - off=decode.big_op ? decode_fetchd() : decode_fetchw(); - sel=decode_fetchw(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIIR((void*)&CPU_JMP,decode.big_op,sel,off,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_iret(void) { - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IR((void*)&CPU_IRET,decode.big_op,FC_RETOP); - dyn_return(BR_Iret); - dyn_closeblock(); -} - -static void dyn_interrupt(Bit8u num) { - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIR((void*)&CPU_Interrupt,num,CPU_INT_SOFTWARE,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - - - -static void dyn_string(StringOps op) { - if (decode.rep) MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - else gen_mov_dword_to_reg_imm(FC_OP1,1); - gen_mov_word_to_reg(FC_OP2,&cpu.direction,true); - Bit8u di_base_addr=decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS; - switch (op) { - case STR_MOVSB: - if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_mm((void*)&dynrec_movsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_MOVSW: - if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_mm((void*)&dynrec_movsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_MOVSD: - if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_mm((void*)&dynrec_movsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - - case STR_LODSB: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - else gen_call_function_m((void*)&dynrec_lodsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - break; - case STR_LODSW: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - else gen_call_function_m((void*)&dynrec_lodsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - break; - case STR_LODSD: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - else gen_call_function_m((void*)&dynrec_lodsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - break; - - case STR_STOSB: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosb_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_m((void*)&dynrec_stosb_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_STOSW: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosw_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_m((void*)&dynrec_stosw_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_STOSD: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosd_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_m((void*)&dynrec_stosd_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - default: IllegalOptionDynrec("dyn_string"); - } - if (decode.rep) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_ECX,decode.big_addr); - - if (op -#include -#include "cross.h" -#include "mem.h" -#include "fpu.h" -#include "cpu.h" - - -static void FPU_FDECSTP(){ - TOP = (TOP - 1) & 7; -} - -static void FPU_FINCSTP(){ - TOP = (TOP + 1) & 7; -} - -static void FPU_FNSTCW(PhysPt addr){ - mem_writew(addr,fpu.cw); -} - -static void FPU_FFREE(Bitu st) { - fpu.tags[st]=TAG_Empty; -} - - -#if C_FPU_X86 -#include "../../fpu/fpu_instructions_x86.h" -#else -#include "../../fpu/fpu_instructions.h" -#endif - - -static INLINE void dyn_fpu_top() { - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_add_imm(FC_OP2,decode.modrm.rm); - gen_and_imm(FC_OP2,7); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); -} - -static INLINE void dyn_fpu_top_swapped() { - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_add_imm(FC_OP1,decode.modrm.rm); - gen_and_imm(FC_OP1,7); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); -} - -static void dyn_eatree() { - Bitu group=(decode.modrm.val >> 3) & 7; - switch (group){ - case 0x00: // FADD ST,STi - gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1); - break; - case 0x01: // FMUL ST,STi - gen_call_function_R((void*)&FPU_FMUL_EA,FC_OP1); - break; - case 0x02: // FCOM STi - gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); - break; - case 0x03: // FCOMP STi - gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: // FSUB ST,STi - gen_call_function_R((void*)&FPU_FSUB_EA,FC_OP1); - break; - case 0x05: // FSUBR ST,STi - gen_call_function_R((void*)&FPU_FSUBR_EA,FC_OP1); - break; - case 0x06: // FDIV ST,STi - gen_call_function_R((void*)&FPU_FDIV_EA,FC_OP1); - break; - case 0x07: // FDIVR ST,STi - gen_call_function_R((void*)&FPU_FDIVR_EA,FC_OP1); - break; - default: - break; - } -} - -static void dyn_fpu_esc0(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch (decode.modrm.reg){ - case 0x00: //FADD ST,STi - gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); - break; - case 0x01: // FMUL ST,STi - gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); - break; - case 0x02: // FCOM STi - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - break; - case 0x03: // FCOMP STi - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: // FSUB ST,STi - gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); - break; - case 0x05: // FSUBR ST,STi - gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); - break; - case 0x06: // FDIV ST,STi - gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); - break; - case 0x07: // FDIVR ST,STi - gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); - break; - default: - break; - } - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_F32_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - - -static void dyn_fpu_esc1(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch (decode.modrm.reg){ - case 0x00: /* FLD STi */ - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_add_imm(FC_OP1,decode.modrm.rm); - gen_and_imm(FC_OP1,7); - gen_protect_reg(FC_OP1); - gen_call_function_raw((void*)&FPU_PREP_PUSH); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_restore_reg(FC_OP1); - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - break; - case 0x01: /* FXCH STi */ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); - break; - case 0x02: /* FNOP */ - gen_call_function_raw((void*)&FPU_FNOP); - break; - case 0x03: /* FSTP STi */ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: - switch(decode.modrm.rm){ - case 0x00: /* FCHS */ - gen_call_function_raw((void*)&FPU_FCHS); - break; - case 0x01: /* FABS */ - gen_call_function_raw((void*)&FPU_FABS); - break; - case 0x02: /* UNKNOWN */ - case 0x03: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - case 0x04: /* FTST */ - gen_call_function_raw((void*)&FPU_FTST); - break; - case 0x05: /* FXAM */ - gen_call_function_raw((void*)&FPU_FXAM); - break; - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - case 0x05: - switch(decode.modrm.rm){ - case 0x00: /* FLD1 */ - gen_call_function_raw((void*)&FPU_FLD1); - break; - case 0x01: /* FLDL2T */ - gen_call_function_raw((void*)&FPU_FLDL2T); - break; - case 0x02: /* FLDL2E */ - gen_call_function_raw((void*)&FPU_FLDL2E); - break; - case 0x03: /* FLDPI */ - gen_call_function_raw((void*)&FPU_FLDPI); - break; - case 0x04: /* FLDLG2 */ - gen_call_function_raw((void*)&FPU_FLDLG2); - break; - case 0x05: /* FLDLN2 */ - gen_call_function_raw((void*)&FPU_FLDLN2); - break; - case 0x06: /* FLDZ*/ - gen_call_function_raw((void*)&FPU_FLDZ); - break; - case 0x07: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - case 0x06: - switch(decode.modrm.rm){ - case 0x00: /* F2XM1 */ - gen_call_function_raw((void*)&FPU_F2XM1); - break; - case 0x01: /* FYL2X */ - gen_call_function_raw((void*)&FPU_FYL2X); - break; - case 0x02: /* FPTAN */ - gen_call_function_raw((void*)&FPU_FPTAN); - break; - case 0x03: /* FPATAN */ - gen_call_function_raw((void*)&FPU_FPATAN); - break; - case 0x04: /* FXTRACT */ - gen_call_function_raw((void*)&FPU_FXTRACT); - break; - case 0x05: /* FPREM1 */ - gen_call_function_raw((void*)&FPU_FPREM1); - break; - case 0x06: /* FDECSTP */ - gen_call_function_raw((void*)&FPU_FDECSTP); - break; - case 0x07: /* FINCSTP */ - gen_call_function_raw((void*)&FPU_FINCSTP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - case 0x07: - switch(decode.modrm.rm){ - case 0x00: /* FPREM */ - gen_call_function_raw((void*)&FPU_FPREM); - break; - case 0x01: /* FYL2XP1 */ - gen_call_function_raw((void*)&FPU_FYL2XP1); - break; - case 0x02: /* FSQRT */ - gen_call_function_raw((void*)&FPU_FSQRT); - break; - case 0x03: /* FSINCOS */ - gen_call_function_raw((void*)&FPU_FSINCOS); - break; - case 0x04: /* FRNDINT */ - gen_call_function_raw((void*)&FPU_FRNDINT); - break; - case 0x05: /* FSCALE */ - gen_call_function_raw((void*)&FPU_FSCALE); - break; - case 0x06: /* FSIN */ - gen_call_function_raw((void*)&FPU_FSIN); - break; - case 0x07: /* FCOS */ - gen_call_function_raw((void*)&FPU_FCOS); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FLD float*/ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_F32,FC_OP1,FC_OP2); - break; - case 0x01: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FST float*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); - break; - case 0x03: /* FSTP float*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FLDENV */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLDENV,FC_ADDR); - break; - case 0x05: /* FLDCW */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void *)&FPU_FLDCW,FC_ADDR); - break; - case 0x06: /* FSTENV */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void *)&FPU_FSTENV,FC_ADDR); - break; - case 0x07: /* FNSTCW*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void *)&FPU_FNSTCW,FC_ADDR); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } -} - -static void dyn_fpu_esc2(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch(decode.modrm.reg){ - case 0x05: - switch(decode.modrm.rm){ - case 0x01: /* FUCOMPP */ - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_add_imm(FC_OP2,1); - gen_and_imm(FC_OP2,7); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_RR((void *)&FPU_FUCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void *)&FPU_FPOP); - gen_call_function_raw((void *)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_I32_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - -static void dyn_fpu_esc3(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch (decode.modrm.reg) { - case 0x04: - switch (decode.modrm.rm) { - case 0x00: //FNENI - case 0x01: //FNDIS - LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion: %d",decode.modrm.rm); - break; - case 0x02: //FNCLEX FCLEX - gen_call_function_raw((void*)&FPU_FCLEX); - break; - case 0x03: //FNINIT FINIT - gen_call_function_raw((void*)&FPU_FINIT); - break; - case 0x04: //FNSETPM - case 0x05: //FRSTPM -// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); - break; - default: - E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FILD */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_I32,FC_OP1,FC_OP2); - break; - case 0x01: /* FISTTP */ - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FIST */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); - break; - case 0x03: /* FISTP */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x05: /* FLD 80 Bits Real */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_F80,FC_ADDR); - break; - case 0x07: /* FSTP 80 Bits Real */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F80,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - } - } -} - -static void dyn_fpu_esc4(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch(decode.modrm.reg){ - case 0x00: /* FADD STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); - break; - case 0x01: /* FMUL STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); - break; - case 0x02: /* FCOM*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - break; - case 0x03: /* FCOMP*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FSUBR STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); - break; - case 0x05: /* FSUB STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); - break; - case 0x06: /* FDIVR STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); - break; - case 0x07: /* FDIV STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); - break; - default: - break; - } - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_F64_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - -static void dyn_fpu_esc5(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch(decode.modrm.reg){ - case 0x00: /* FFREE STi */ - gen_call_function_R((void*)&FPU_FFREE,FC_OP2); - break; - case 0x01: /* FXCH STi*/ - gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); - break; - case 0x02: /* FST STi */ - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - break; - case 0x03: /* FSTP STi*/ - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FUCOM STi */ - gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); - break; - case 0x05: /*FUCOMP STi */ - gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FLD double real*/ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2); - break; - case 0x01: /* FISTTP longint*/ - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FST double real*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); - break; - case 0x03: /* FSTP double real*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FRSTOR */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FRSTOR,FC_ADDR); - break; - case 0x06: /* FSAVE */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FSAVE,FC_ADDR); - break; - case 0x07: /*FNSTSW */ - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),true); - gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - } - } -} - -static void dyn_fpu_esc6(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch(decode.modrm.reg){ - case 0x00: /*FADDP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); - break; - case 0x01: /* FMULP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); - break; - case 0x02: /* FCOMP5*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - break; /* TODO IS THIS ALLRIGHT ????????? */ - case 0x03: /*FCOMPP*/ - if(decode.modrm.rm != 1) { - LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - return; - } - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_add_imm(FC_OP2,1); - gen_and_imm(FC_OP2,7); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); /* extra pop at the bottom*/ - break; - case 0x04: /* FSUBRP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); - break; - case 0x05: /* FSUBP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); - break; - case 0x06: /* FDIVRP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); - break; - case 0x07: /* FDIVP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); - break; - default: - break; - } - gen_call_function_raw((void*)&FPU_FPOP); - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_I16_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - -static void dyn_fpu_esc7(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch (decode.modrm.reg){ - case 0x00: /* FFREEP STi */ - dyn_fpu_top(); - gen_call_function_R((void*)&FPU_FFREE,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x01: /* FXCH STi*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); - break; - case 0x02: /* FSTP STi*/ - case 0x03: /* FSTP STi*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: - switch(decode.modrm.rm){ - case 0x00: /* FNSTSW AX*/ - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); - gen_mov_word_to_reg(FC_OP1,(void*)(&fpu.sw),false); - MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,DRC_REG_EAX); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FILD Bit16s */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_I16,FC_OP1,FC_OP2); - break; - case 0x01: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FIST Bit16s */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); - break; - case 0x03: /* FISTP Bit16s */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FBLD packed BCD */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FBLD,FC_OP1,FC_OP2); - break; - case 0x05: /* FILD Bit64s */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_I64,FC_OP1,FC_OP2); - break; - case 0x06: /* FBSTP packed BCD */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FBST,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x07: /* FISTP Bit64s */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I64,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } -} - -#endif diff --git a/src/cpu/core_dynrec/operators.h b/src/cpu/core_dynrec/operators.h deleted file mode 100644 index 253e1df8f..000000000 --- a/src/cpu/core_dynrec/operators.h +++ /dev/null @@ -1,1996 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b+lf_var2b); - lflags.type=t_ADDb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) { - return op1+op2; -} - -static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b+lf_var2b+lflags.oldcf); - lflags.type=t_ADCb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) { - return (Bit8u)(op1+op2+(Bitu)(get_CF()!=0)); -} - -static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b-lf_var2b); - lflags.type=t_SUBb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) { - return op1-op2; -} - -static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b-(lf_var2b+lflags.oldcf)); - lflags.type=t_SBBb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) { - return (Bit8u)(op1-(op2+(Bitu)(get_CF()!=0))); -} - -static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b-lf_var2b); - lflags.type=t_CMPb; -} - -static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) { -} - -static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b ^ lf_var2b; - lflags.type=t_XORb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) { - return op1 ^ op2; -} - -static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b & lf_var2b; - lflags.type=t_ANDb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) { - return op1 & op2; -} - -static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b | lf_var2b; - lflags.type=t_ORb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) { - return op1 | op2; -} - -static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b & lf_var2b; - lflags.type=t_TESTb; -} - -static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) { -} - -static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w+lf_var2w); - lflags.type=t_ADDw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) { - return op1+op2; -} - -static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w+lf_var2w+lflags.oldcf); - lflags.type=t_ADCw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) { - return (Bit16u)(op1+op2+(Bitu)(get_CF()!=0)); -} - -static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w-lf_var2w); - lflags.type=t_SUBw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) { - return op1-op2; -} - -static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w-(lf_var2w+lflags.oldcf)); - lflags.type=t_SBBw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) { - return (Bit16u)(op1-(op2+(Bitu)(get_CF()!=0))); -} - -static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w-lf_var2w); - lflags.type=t_CMPw; -} - -static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) { -} - -static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w ^ lf_var2w; - lflags.type=t_XORw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) { - return op1 ^ op2; -} - -static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w & lf_var2w; - lflags.type=t_ANDw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) { - return op1 & op2; -} - -static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w | lf_var2w; - lflags.type=t_ORw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) { - return op1 | op2; -} - -static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w & lf_var2w; - lflags.type=t_TESTw; -} - -static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) { -} - -static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d+lf_var2d; - lflags.type=t_ADDd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) { - return op1 + op2; -} - -static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d+lf_var2d+lflags.oldcf; - lflags.type=t_ADCd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) { - return op1+op2+(Bitu)(get_CF()!=0); -} - -static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d-lf_var2d; - lflags.type=t_SUBd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) { - return op1-op2; -} - -static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); - lflags.type=t_SBBd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) { - return op1-(op2+(Bitu)(get_CF()!=0)); -} - -static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d-lf_var2d; - lflags.type=t_CMPd; -} - -static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) { -} - -static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d ^ lf_var2d; - lflags.type=t_XORd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) { - return op1 ^ op2; -} - -static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d & lf_var2d; - lflags.type=t_ANDd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) { - return op1 & op2; -} - -static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d | lf_var2d; - lflags.type=t_ORd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) { - return op1 | op2; -} - -static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d & lf_var2d; - lflags.type=t_TESTd; -} - -static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) { -} - - -static void dyn_dop_byte_gencall(DualOps op) { - switch (op) { - case DOP_ADD: - InvalidateFlags((void*)&dynrec_add_byte_simple,t_ADDb); - gen_call_function_raw((void*)&dynrec_add_byte); - break; - case DOP_ADC: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_adc_byte_simple,t_ADCb); - gen_call_function_raw((void*)&dynrec_adc_byte); - break; - case DOP_SUB: - InvalidateFlags((void*)&dynrec_sub_byte_simple,t_SUBb); - gen_call_function_raw((void*)&dynrec_sub_byte); - break; - case DOP_SBB: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_sbb_byte_simple,t_SBBb); - gen_call_function_raw((void*)&dynrec_sbb_byte); - break; - case DOP_CMP: - InvalidateFlags((void*)&dynrec_cmp_byte_simple,t_CMPb); - gen_call_function_raw((void*)&dynrec_cmp_byte); - break; - case DOP_XOR: - InvalidateFlags((void*)&dynrec_xor_byte_simple,t_XORb); - gen_call_function_raw((void*)&dynrec_xor_byte); - break; - case DOP_AND: - InvalidateFlags((void*)&dynrec_and_byte_simple,t_ANDb); - gen_call_function_raw((void*)&dynrec_and_byte); - break; - case DOP_OR: - InvalidateFlags((void*)&dynrec_or_byte_simple,t_ORb); - gen_call_function_raw((void*)&dynrec_or_byte); - break; - case DOP_TEST: - InvalidateFlags((void*)&dynrec_test_byte_simple,t_TESTb); - gen_call_function_raw((void*)&dynrec_test_byte); - break; - default: IllegalOptionDynrec("dyn_dop_byte_gencall"); - } -} - -static void dyn_dop_word_gencall(DualOps op,bool dword) { - if (dword) { - switch (op) { - case DOP_ADD: - InvalidateFlags((void*)&dynrec_add_dword_simple,t_ADDd); - gen_call_function_raw((void*)&dynrec_add_dword); - break; - case DOP_ADC: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_adc_dword_simple,t_ADCd); - gen_call_function_raw((void*)&dynrec_adc_dword); - break; - case DOP_SUB: - InvalidateFlags((void*)&dynrec_sub_dword_simple,t_SUBd); - gen_call_function_raw((void*)&dynrec_sub_dword); - break; - case DOP_SBB: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_sbb_dword_simple,t_SBBd); - gen_call_function_raw((void*)&dynrec_sbb_dword); - break; - case DOP_CMP: - InvalidateFlags((void*)&dynrec_cmp_dword_simple,t_CMPd); - gen_call_function_raw((void*)&dynrec_cmp_dword); - break; - case DOP_XOR: - InvalidateFlags((void*)&dynrec_xor_dword_simple,t_XORd); - gen_call_function_raw((void*)&dynrec_xor_dword); - break; - case DOP_AND: - InvalidateFlags((void*)&dynrec_and_dword_simple,t_ANDd); - gen_call_function_raw((void*)&dynrec_and_dword); - break; - case DOP_OR: - InvalidateFlags((void*)&dynrec_or_dword_simple,t_ORd); - gen_call_function_raw((void*)&dynrec_or_dword); - break; - case DOP_TEST: - InvalidateFlags((void*)&dynrec_test_dword_simple,t_TESTd); - gen_call_function_raw((void*)&dynrec_test_dword); - break; - default: IllegalOptionDynrec("dyn_dop_dword_gencall"); - } - } else { - switch (op) { - case DOP_ADD: - InvalidateFlags((void*)&dynrec_add_word_simple,t_ADDw); - gen_call_function_raw((void*)&dynrec_add_word); - break; - case DOP_ADC: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_adc_word_simple,t_ADCw); - gen_call_function_raw((void*)&dynrec_adc_word); - break; - case DOP_SUB: - InvalidateFlags((void*)&dynrec_sub_word_simple,t_SUBw); - gen_call_function_raw((void*)&dynrec_sub_word); - break; - case DOP_SBB: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_sbb_word_simple,t_SBBw); - gen_call_function_raw((void*)&dynrec_sbb_word); - break; - case DOP_CMP: - InvalidateFlags((void*)&dynrec_cmp_word_simple,t_CMPw); - gen_call_function_raw((void*)&dynrec_cmp_word); - break; - case DOP_XOR: - InvalidateFlags((void*)&dynrec_xor_word_simple,t_XORw); - gen_call_function_raw((void*)&dynrec_xor_word); - break; - case DOP_AND: - InvalidateFlags((void*)&dynrec_and_word_simple,t_ANDw); - gen_call_function_raw((void*)&dynrec_and_word); - break; - case DOP_OR: - InvalidateFlags((void*)&dynrec_or_word_simple,t_ORw); - gen_call_function_raw((void*)&dynrec_or_word); - break; - case DOP_TEST: - InvalidateFlags((void*)&dynrec_test_word_simple,t_TESTw); - gen_call_function_raw((void*)&dynrec_test_word); - break; - default: IllegalOptionDynrec("dyn_dop_word_gencall"); - } - } -} - - -static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) { - LoadCF; - lf_var1b=op; - lf_resb=lf_var1b+1; - lflags.type=t_INCb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) { - return op+1; -} - -static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) { - LoadCF; - lf_var1b=op; - lf_resb=lf_var1b-1; - lflags.type=t_DECb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) { - return op-1; -} - -static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) { - return ~op; -} - -static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) { - lf_var1b=op; - lf_resb=0-lf_var1b; - lflags.type=t_NEGb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) { - return 0-op; -} - -static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) { - LoadCF; - lf_var1w=op; - lf_resw=lf_var1w+1; - lflags.type=t_INCw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) { - return op+1; -} - -static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) { - LoadCF; - lf_var1w=op; - lf_resw=lf_var1w-1; - lflags.type=t_DECw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) { - return op-1; -} - -static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) { - return ~op; -} - -static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) { - lf_var1w=op; - lf_resw=0-lf_var1w; - lflags.type=t_NEGw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) { - return 0-op; -} - -static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) { - LoadCF; - lf_var1d=op; - lf_resd=lf_var1d+1; - lflags.type=t_INCd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) { - return op+1; -} - -static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) { - LoadCF; - lf_var1d=op; - lf_resd=lf_var1d-1; - lflags.type=t_DECd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) { - return op-1; -} - -static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) { - return ~op; -} - -static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) { - lf_var1d=op; - lf_resd=0-lf_var1d; - lflags.type=t_NEGd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) { - return 0-op; -} - - -static void dyn_sop_byte_gencall(SingleOps op) { - switch (op) { - case SOP_INC: - InvalidateFlagsPartially((void*)&dynrec_inc_byte_simple,t_INCb); - gen_call_function_raw((void*)&dynrec_inc_byte); - break; - case SOP_DEC: - InvalidateFlagsPartially((void*)&dynrec_dec_byte_simple,t_DECb); - gen_call_function_raw((void*)&dynrec_dec_byte); - break; - case SOP_NOT: - gen_call_function_raw((void*)&dynrec_not_byte); - break; - case SOP_NEG: - InvalidateFlags((void*)&dynrec_neg_byte_simple,t_NEGb); - gen_call_function_raw((void*)&dynrec_neg_byte); - break; - default: IllegalOptionDynrec("dyn_sop_byte_gencall"); - } -} - -static void dyn_sop_word_gencall(SingleOps op,bool dword) { - if (dword) { - switch (op) { - case SOP_INC: - InvalidateFlagsPartially((void*)&dynrec_inc_dword_simple,t_INCd); - gen_call_function_raw((void*)&dynrec_inc_dword); - break; - case SOP_DEC: - InvalidateFlagsPartially((void*)&dynrec_dec_dword_simple,t_DECd); - gen_call_function_raw((void*)&dynrec_dec_dword); - break; - case SOP_NOT: - gen_call_function_raw((void*)&dynrec_not_dword); - break; - case SOP_NEG: - InvalidateFlags((void*)&dynrec_neg_dword_simple,t_NEGd); - gen_call_function_raw((void*)&dynrec_neg_dword); - break; - default: IllegalOptionDynrec("dyn_sop_dword_gencall"); - } - } else { - switch (op) { - case SOP_INC: - InvalidateFlagsPartially((void*)&dynrec_inc_word_simple,t_INCw); - gen_call_function_raw((void*)&dynrec_inc_word); - break; - case SOP_DEC: - InvalidateFlagsPartially((void*)&dynrec_dec_word_simple,t_DECw); - gen_call_function_raw((void*)&dynrec_dec_word); - break; - case SOP_NOT: - gen_call_function_raw((void*)&dynrec_not_word); - break; - case SOP_NEG: - InvalidateFlags((void*)&dynrec_neg_word_simple,t_NEGw); - gen_call_function_raw((void*)&dynrec_neg_word); - break; - default: IllegalOptionDynrec("dyn_sop_word_gencall"); - } - } -} - - -static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) { - if (op2&0x18) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1 & 1); - SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1b=op1; - lf_var2b=op2&0x07; - lf_resb=(lf_var1b << lf_var2b) | (lf_var1b >> (8-lf_var2b)); - SETFLAGBIT(CF,lf_resb & 1); - SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7)); - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) return op1; - return (op1 << (op2&0x07)) | (op1 >> (8-(op2&0x07))); -} - -static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) { - if (op2&0x18) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1>>7); - SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1b=op1; - lf_var2b=op2&0x07; - lf_resb=(lf_var1b >> lf_var2b) | (lf_var1b << (8-lf_var2b)); - SETFLAGBIT(CF,lf_resb & 0x80); - SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) return op1; - return (op1 >> (op2&0x07)) | (op1 << (8-(op2&0x07))); -} - -static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) { - if (op2%9) { - Bit8u cf=(Bit8u)FillFlags()&0x1; - lf_var1b=op1; - lf_var2b=op2%9; - lf_resb=(lf_var1b << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1b >> (9-lf_var2b)); - SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7)); - return lf_resb; - } else return op1; -} - -static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) { - if (op2%9) { - Bit8u cf=(Bit8u)FillFlags()&0x1; - lf_var1b=op1; - lf_var2b=op2%9; - lf_resb=(lf_var1b >> lf_var2b) | (cf << (8-lf_var2b)) | (lf_var1b << (9-lf_var2b)); \ - SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); - return lf_resb; - } else return op1; -} - -static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b << lf_var2b; - lflags.type=t_SHLb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - return op1 << op2; -} - -static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b >> lf_var2b; - lflags.type=t_SHRb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - return op1 >> op2; -} - -static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1b=op1; - lf_var2b=op2; - if (lf_var2b>8) lf_var2b=8; - if (lf_var1b & 0x80) { - lf_resb=(lf_var1b >> lf_var2b)| (0xff << (8 - lf_var2b)); - } else { - lf_resb=lf_var1b >> lf_var2b; - } - lflags.type=t_SARb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - if (op2>8) op2=8; - if (op1 & 0x80) return (op1 >> op2) | (0xff << (8 - op2)); - else return op1 >> op2; -} - -static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) { - if (op2&0x10) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1 & 1); - SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1w=op1; - lf_var2b=op2&0xf; - lf_resw=(lf_var1w << lf_var2b) | (lf_var1w >> (16-lf_var2b)); - SETFLAGBIT(CF,lf_resw & 1); - SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15)); - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) return op1; - return (op1 << (op2&0xf)) | (op1 >> (16-(op2&0xf))); -} - -static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) { - if (op2&0x10) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1>>15); - SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1w=op1; - lf_var2b=op2&0xf; - lf_resw=(lf_var1w >> lf_var2b) | (lf_var1w << (16-lf_var2b)); - SETFLAGBIT(CF,lf_resw & 0x8000); - SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) return op1; - return (op1 >> (op2&0xf)) | (op1 << (16-(op2&0xf))); -} - -static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) { - if (op2%17) { - Bit16u cf=(Bit16u)FillFlags()&0x1; - lf_var1w=op1; - lf_var2b=op2%17; - lf_resw=(lf_var1w << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1w >> (17-lf_var2b)); - SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15)); - return lf_resw; - } else return op1; -} - -static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) { - if (op2%17) { - Bit16u cf=(Bit16u)FillFlags()&0x1; - lf_var1w=op1; - lf_var2b=op2%17; - lf_resw=(lf_var1w >> lf_var2b) | (cf << (16-lf_var2b)) | (lf_var1w << (17-lf_var2b)); - SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); - return lf_resw; - } else return op1; -} - -static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1w=op1; - lf_var2b=op2; - lf_resw=lf_var1w << lf_var2b; - lflags.type=t_SHLw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - return op1 << op2; -} - -static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1w=op1; - lf_var2b=op2; - lf_resw=lf_var1w >> lf_var2b; - lflags.type=t_SHRw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - return op1 >> op2; -} - -static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1w=op1; - lf_var2b=op2; - if (lf_var2b>16) lf_var2b=16; - if (lf_var1w & 0x8000) { - lf_resw=(lf_var1w >> lf_var2b) | (0xffff << (16 - lf_var2b)); - } else { - lf_resw=lf_var1w >> lf_var2b; - } - lflags.type=t_SARw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - if (op2>16) op2=16; - if (op1 & 0x8000) return (op1 >> op2) | (0xffff << (16 - op2)); - else return op1 >> op2; -} - -static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - FillFlagsNoCFOF(); - lf_var1d=op1; - lf_var2b=op2; - lf_resd=(lf_var1d << lf_var2b) | (lf_var1d >> (32-lf_var2b)); - SETFLAGBIT(CF,lf_resd & 1); - SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31)); - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return (op1 << op2) | (op1 >> (32-op2)); -} - -static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - FillFlagsNoCFOF(); - lf_var1d=op1; - lf_var2b=op2; - lf_resd=(lf_var1d >> lf_var2b) | (lf_var1d << (32-lf_var2b)); - SETFLAGBIT(CF,lf_resd & 0x80000000); - SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return (op1 >> op2) | (op1 << (32-op2)); -} - -static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - Bit32u cf=(Bit32u)FillFlags()&0x1; - lf_var1d=op1; - lf_var2b=op2; - if (lf_var2b==1) { - lf_resd=(lf_var1d << 1) | cf; - } else { - lf_resd=(lf_var1d << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1d >> (33-lf_var2b)); - } - SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1)); - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31)); - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) { - if (op2) { - Bit32u cf=(Bit32u)FillFlags()&0x1; - lf_var1d=op1; - lf_var2b=op2; - if (lf_var2b==1) { - lf_resd=lf_var1d >> 1 | cf << 31; - } else { - lf_resd=(lf_var1d >> lf_var2b) | (cf << (32-lf_var2b)) | (lf_var1d << (33-lf_var2b)); - } - SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); - return lf_resd; - } else return op1; -} - -static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1d=op1; - lf_var2b=op2; - lf_resd=lf_var1d << lf_var2b; - lflags.type=t_SHLd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return op1 << op2; -} - -static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1d=op1; - lf_var2b=op2; - lf_resd=lf_var1d >> lf_var2b; - lflags.type=t_SHRd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return op1 >> op2; -} - -static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - lf_var2b=op2; - lf_var1d=op1; - if (lf_var1d & 0x80000000) { - lf_resd=(lf_var1d >> lf_var2b) | (0xffffffff << (32 - lf_var2b)); - } else { - lf_resd=lf_var1d >> lf_var2b; - } - lflags.type=t_SARd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - if (op1 & 0x80000000) return (op1 >> op2) | (0xffffffff << (32 - op2)); - else return op1 >> op2; -} - -static void dyn_shift_byte_gencall(ShiftOps op) { - switch (op) { - case SHIFT_ROL: - InvalidateFlagsPartially((void*)&dynrec_rol_byte_simple,t_ROLb); - gen_call_function_raw((void*)&dynrec_rol_byte); - break; - case SHIFT_ROR: - InvalidateFlagsPartially((void*)&dynrec_ror_byte_simple,t_RORb); - gen_call_function_raw((void*)&dynrec_ror_byte); - break; - case SHIFT_RCL: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcl_byte); - break; - case SHIFT_RCR: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcr_byte); - break; - case SHIFT_SHL: - case SHIFT_SAL: - InvalidateFlagsPartially((void*)&dynrec_shl_byte_simple,t_SHLb); - gen_call_function_raw((void*)&dynrec_shl_byte); - break; - case SHIFT_SHR: - InvalidateFlagsPartially((void*)&dynrec_shr_byte_simple,t_SHRb); - gen_call_function_raw((void*)&dynrec_shr_byte); - break; - case SHIFT_SAR: - InvalidateFlagsPartially((void*)&dynrec_sar_byte_simple,t_SARb); - gen_call_function_raw((void*)&dynrec_sar_byte); - break; - default: IllegalOptionDynrec("dyn_shift_byte_gencall"); - } -} - -static void dyn_shift_word_gencall(ShiftOps op,bool dword) { - if (dword) { - switch (op) { - case SHIFT_ROL: - InvalidateFlagsPartially((void*)&dynrec_rol_dword_simple,t_ROLd); - gen_call_function_raw((void*)&dynrec_rol_dword); - break; - case SHIFT_ROR: - InvalidateFlagsPartially((void*)&dynrec_ror_dword_simple,t_RORd); - gen_call_function_raw((void*)&dynrec_ror_dword); - break; - case SHIFT_RCL: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcl_dword); - break; - case SHIFT_RCR: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcr_dword); - break; - case SHIFT_SHL: - case SHIFT_SAL: - InvalidateFlagsPartially((void*)&dynrec_shl_dword_simple,t_SHLd); - gen_call_function_raw((void*)&dynrec_shl_dword); - break; - case SHIFT_SHR: - InvalidateFlagsPartially((void*)&dynrec_shr_dword_simple,t_SHRd); - gen_call_function_raw((void*)&dynrec_shr_dword); - break; - case SHIFT_SAR: - InvalidateFlagsPartially((void*)&dynrec_sar_dword_simple,t_SARd); - gen_call_function_raw((void*)&dynrec_sar_dword); - break; - default: IllegalOptionDynrec("dyn_shift_dword_gencall"); - } - } else { - switch (op) { - case SHIFT_ROL: - InvalidateFlagsPartially((void*)&dynrec_rol_word_simple,t_ROLw); - gen_call_function_raw((void*)&dynrec_rol_word); - break; - case SHIFT_ROR: - InvalidateFlagsPartially((void*)&dynrec_ror_word_simple,t_RORw); - gen_call_function_raw((void*)&dynrec_ror_word); - break; - case SHIFT_RCL: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcl_word); - break; - case SHIFT_RCR: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcr_word); - break; - case SHIFT_SHL: - case SHIFT_SAL: - InvalidateFlagsPartially((void*)&dynrec_shl_word_simple,t_SHLw); - gen_call_function_raw((void*)&dynrec_shl_word); - break; - case SHIFT_SHR: - InvalidateFlagsPartially((void*)&dynrec_shr_word_simple,t_SHRw); - gen_call_function_raw((void*)&dynrec_shr_word); - break; - case SHIFT_SAR: - InvalidateFlagsPartially((void*)&dynrec_sar_word_simple,t_SARw); - gen_call_function_raw((void*)&dynrec_sar_word); - break; - default: IllegalOptionDynrec("dyn_shift_word_gencall"); - } - } -} - -static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=(op1<<16)|op2; - Bit32u tempd=lf_var1d << lf_var2b; - if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); - lf_resw=(Bit16u)(tempd >> 16); - lflags.type=t_DSHLw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - Bit32u tempd=(Bit32u)((((Bit32u)op1)<<16)|op2) << val; - if (val>16) tempd |= (op2 << (val - 16)); - return (Bit16u)(tempd >> 16); -} - -static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=op1; - lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); - lflags.type=t_DSHLd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - return (op1 << val) | (op2 >> (32-val)); -} - -static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=(op2<<16)|op1; - Bit32u tempd=lf_var1d >> lf_var2b; - if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); - lf_resw=(Bit16u)(tempd); - lflags.type=t_DSHRw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - Bit32u tempd=(Bit32u)((((Bit32u)op2)<<16)|op1) >> val; - if (val>16) tempd |= (op2 << (32-val)); - return (Bit16u)(tempd); -} - -static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=op1; - lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); - lflags.type=t_DSHRd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - return (op1 >> val) | (op2 << (32-val)); -} - -static void dyn_dpshift_word_gencall(bool left) { - if (left) { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_word,FC_OP3); - InvalidateFlagsPartially((void*)&dynrec_dshl_word_simple,proc_addr,t_DSHLw); - } else { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_word,FC_OP3); - InvalidateFlagsPartially((void*)&dynrec_dshr_word_simple,proc_addr,t_DSHRw); - } -} - -static void dyn_dpshift_dword_gencall(bool left) { - if (left) { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_dword,FC_OP3); - InvalidateFlagsPartially((void*)&dynrec_dshl_dword_simple,proc_addr,t_DSHLd); - } else { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_dword,FC_OP3); - InvalidateFlagsPartially((void*)&dynrec_dshr_dword_simple,proc_addr,t_DSHRd); - } -} - - - -static Bit32u DRC_CALL_CONV dynrec_get_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_of(void) { return TFLG_O; } -static Bit32u DRC_CALL_CONV dynrec_get_nof(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nof(void) { return TFLG_NO; } -static Bit32u DRC_CALL_CONV dynrec_get_cf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_cf(void) { return TFLG_B; } -static Bit32u DRC_CALL_CONV dynrec_get_ncf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_ncf(void) { return TFLG_NB; } -static Bit32u DRC_CALL_CONV dynrec_get_zf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_zf(void) { return TFLG_Z; } -static Bit32u DRC_CALL_CONV dynrec_get_nzf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nzf(void) { return TFLG_NZ; } -static Bit32u DRC_CALL_CONV dynrec_get_sf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_sf(void) { return TFLG_S; } -static Bit32u DRC_CALL_CONV dynrec_get_nsf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nsf(void) { return TFLG_NS; } -static Bit32u DRC_CALL_CONV dynrec_get_pf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_pf(void) { return TFLG_P; } -static Bit32u DRC_CALL_CONV dynrec_get_npf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_npf(void) { return TFLG_NP; } - -static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void) { return TFLG_BE; } -static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void) { return TFLG_NBE; } -static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void) { return TFLG_L; } -static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void) { return TFLG_NL; } -static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void) { return TFLG_LE; } -static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void) { return TFLG_NLE; } - - -static void dyn_branchflag_to_reg(BranchTypes btype) { - switch (btype) { - case BR_O:gen_call_function_raw((void*)&dynrec_get_of);break; - case BR_NO:gen_call_function_raw((void*)&dynrec_get_nof);break; - case BR_B:gen_call_function_raw((void*)&dynrec_get_cf);break; - case BR_NB:gen_call_function_raw((void*)&dynrec_get_ncf);break; - case BR_Z:gen_call_function_raw((void*)&dynrec_get_zf);break; - case BR_NZ:gen_call_function_raw((void*)&dynrec_get_nzf);break; - case BR_BE:gen_call_function_raw((void*)&dynrec_get_cf_or_zf);break; - case BR_NBE:gen_call_function_raw((void*)&dynrec_get_ncf_and_nzf);break; - - case BR_S:gen_call_function_raw((void*)&dynrec_get_sf);break; - case BR_NS:gen_call_function_raw((void*)&dynrec_get_nsf);break; - case BR_P:gen_call_function_raw((void*)&dynrec_get_pf);break; - case BR_NP:gen_call_function_raw((void*)&dynrec_get_npf);break; - case BR_L:gen_call_function_raw((void*)&dynrec_get_sf_neq_of);break; - case BR_NL:gen_call_function_raw((void*)&dynrec_get_sf_eq_of);break; - case BR_LE:gen_call_function_raw((void*)&dynrec_get_zf_or_sf_neq_of);break; - case BR_NLE:gen_call_function_raw((void*)&dynrec_get_nzf_and_sf_eq_of);break; - } -} - - -static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) DRC_FC; -static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) { - FillFlagsNoCFOF(); - reg_ax=reg_al*op; - SETFLAGBIT(ZF,reg_al == 0); - if (reg_ax & 0xff00) { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } else { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } -} - -static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) DRC_FC; -static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) { - FillFlagsNoCFOF(); - reg_ax=((Bit8s)reg_al) * ((Bit8s)op); - if ((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } -} - -static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) DRC_FC; -static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) { - FillFlagsNoCFOF(); - Bitu tempu=(Bitu)reg_ax*(Bitu)op; - reg_ax=(Bit16u)(tempu); - reg_dx=(Bit16u)(tempu >> 16); - SETFLAGBIT(ZF,reg_ax == 0); - if (reg_dx) { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } else { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } -} - -static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) DRC_FC; -static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) { - FillFlagsNoCFOF(); - Bits temps=((Bit16s)reg_ax)*((Bit16s)op); - reg_ax=(Bit16s)(temps); - reg_dx=(Bit16s)(temps >> 16); - if (((temps & 0xffff8000)==0xffff8000 || (temps & 0xffff8000)==0x0000)) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } -} - -static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) DRC_FC; -static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) { - FillFlagsNoCFOF(); - Bit64u tempu=(Bit64u)reg_eax*(Bit64u)op; - reg_eax=(Bit32u)(tempu); - reg_edx=(Bit32u)(tempu >> 32); - SETFLAGBIT(ZF,reg_eax == 0); - if (reg_edx) { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } else { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } -} - -static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) DRC_FC; -static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) { - FillFlagsNoCFOF(); - Bit64s temps=((Bit64s)((Bit32s)reg_eax))*((Bit64s)((Bit32s)op)); - reg_eax=(Bit32u)(temps); - reg_edx=(Bit32u)(temps >> 32); - if ((reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else if ( (reg_edx==0x00000000) && (reg_eax< 0x80000000) ) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } -} - - -static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) { - Bitu val=op; - if (val==0) return CPU_PrepareException(0,0); - Bitu quo=reg_ax / val; - Bit8u rem=(Bit8u)(reg_ax % val); - Bit8u quo8=(Bit8u)(quo&0xff); - if (quo>0xff) return CPU_PrepareException(0,0); - reg_ah=rem; - reg_al=quo8; - return false; -} - -static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) { - Bits val=(Bit8s)op; - if (val==0) return CPU_PrepareException(0,0); - Bits quo=((Bit16s)reg_ax) / val; - Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); - Bit8s quo8s=(Bit8s)(quo&0xff); - if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0); - reg_ah=rem; - reg_al=quo8s; - return false; -} - -static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) { - Bitu val=op; - if (val==0) return CPU_PrepareException(0,0); - Bitu num=((Bit32u)reg_dx<<16)|reg_ax; - Bitu quo=num/val; - Bit16u rem=(Bit16u)(num % val); - Bit16u quo16=(Bit16u)(quo&0xffff); - if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0); - reg_dx=rem; - reg_ax=quo16; - return false; -} - -static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) { - Bits val=(Bit16s)op; - if (val==0) return CPU_PrepareException(0,0); - Bits num=(Bit32s)((reg_dx<<16)|reg_ax); - Bits quo=num/val; - Bit16s rem=(Bit16s)(num % val); - Bit16s quo16s=(Bit16s)quo; - if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0); - reg_dx=rem; - reg_ax=quo16s; - return false; -} - -static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) { - Bitu val=op; - if (val==0) return CPU_PrepareException(0,0); - Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; - Bit64u quo=num/val; - Bit32u rem=(Bit32u)(num % val); - Bit32u quo32=(Bit32u)(quo&0xffffffff); - if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0); - reg_edx=rem; - reg_eax=quo32; - return false; -} - -static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) { - Bits val=(Bit32s)op; - if (val==0) return CPU_PrepareException(0,0); - Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; - Bit64s quo=num/val; - Bit32s rem=(Bit32s)(num % val); - Bit32s quo32s=(Bit32s)(quo&0xffffffff); - if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0); - reg_edx=rem; - reg_eax=quo32s; - return false; -} - - -static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) { - FillFlagsNoCFOF(); - Bits res=((Bit16s)op1) * ((Bit16s)op2); - if ((res>-32768) && (res<32767)) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } - return (Bit16u)(res & 0xffff); -} - -static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) { - FillFlagsNoCFOF(); - Bit64s res=((Bit64s)((Bit32s)op1))*((Bit64s)((Bit32s)op2)); - if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } - return (Bit32s)res; -} - - - -static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) { - return (Bit8s)op; -} - -static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) { - return (Bit16s)op; -} - -static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) { - if (op & 0x8000) return 0xffff; - else return 0; -} - -static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) { - if (op & 0x80000000) return 0xffffffff; - else return 0; -} - - -static void DRC_CALL_CONV dynrec_sahf(Bit16u op) DRC_FC; -static void DRC_CALL_CONV dynrec_sahf(Bit16u op) { - SETFLAGBIT(OF,get_OF()); - lflags.type=t_UNKNOWN; - CPU_SetFlags(op>>8,FMASK_NORMAL & 0xff); -} - - -static void DRC_CALL_CONV dynrec_cmc(void) DRC_FC; -static void DRC_CALL_CONV dynrec_cmc(void) { - FillFlags(); - SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); -} -static void DRC_CALL_CONV dynrec_clc(void) DRC_FC; -static void DRC_CALL_CONV dynrec_clc(void) { - FillFlags(); - SETFLAGBIT(CF,false); -} -static void DRC_CALL_CONV dynrec_stc(void) DRC_FC; -static void DRC_CALL_CONV dynrec_stc(void) { - FillFlags(); - SETFLAGBIT(CF,true); -} -static void DRC_CALL_CONV dynrec_cld(void) DRC_FC; -static void DRC_CALL_CONV dynrec_cld(void) { - SETFLAGBIT(DF,false); - cpu.direction=1; -} -static void DRC_CALL_CONV dynrec_std(void) DRC_FC; -static void DRC_CALL_CONV dynrec_std(void) { - SETFLAGBIT(DF,true); - cpu.direction=-1; -} - - -static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_di,mem_readb(si_base+reg_si)); - reg_si+=add_index; - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_edi,mem_readb(si_base+reg_esi)); - reg_esi+=add_index; - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_di,mem_readw(si_base+reg_si)); - reg_si+=add_index; - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_edi,mem_readw(si_base+reg_esi)); - reg_esi+=add_index; - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_di,mem_readd(si_base+reg_si)); - reg_si+=add_index; - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_edi,mem_readd(si_base+reg_esi)); - reg_esi+=add_index; - reg_edi+=add_index; - } - return count_left; -} - - -static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - reg_al=mem_readb(si_base+reg_si); - reg_si+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - reg_al=mem_readb(si_base+reg_esi); - reg_esi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - reg_ax=mem_readw(si_base+reg_si); - reg_si+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - reg_ax=mem_readw(si_base+reg_esi); - reg_esi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - reg_eax=mem_readd(si_base+reg_si); - reg_si+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - reg_eax=mem_readd(si_base+reg_esi); - reg_esi+=add_index; - } - return count_left; -} - - -static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_di,reg_al); - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_edi,reg_al); - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_di,reg_ax); - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_edi,reg_ax); - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_di,reg_eax); - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_edi,reg_eax); - reg_edi+=add_index; - } - return count_left; -} - - -static void DRC_CALL_CONV dynrec_push_word(Bit16u value) DRC_FC; -static void DRC_CALL_CONV dynrec_push_word(Bit16u value) { - Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask); - mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask),value); - reg_esp=new_esp; -} - -static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) DRC_FC; -static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) { - Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask); - mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); - reg_esp=new_esp; -} - -static Bit16u DRC_CALL_CONV dynrec_pop_word(void) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_pop_word(void) { - Bit16u val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); - return val; -} - -static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) { - Bit32u val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); - return val; -} diff --git a/src/cpu/core_dynrec/risc_armv4le-common.h b/src/cpu/core_dynrec/risc_armv4le-common.h deleted file mode 100644 index a8ad692d4..000000000 --- a/src/cpu/core_dynrec/risc_armv4le-common.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4 (little endian) backend by M-HT (common data/functions) */ - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit32u - -// calling convention modifier -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC /* nothing */ - -// use FC_REGS_ADDR to hold the address of "cpu_regs" and to access it using FC_REGS_ADDR -#define DRC_USE_REGS_ADDR -// use FC_SEGS_ADDR to hold the address of "Segs" and to access it using FC_SEGS_ADDR -#define DRC_USE_SEGS_ADDR - -// register mapping -typedef Bit8u HostReg; - -// "lo" registers -#define HOST_r0 0 -#define HOST_r1 1 -#define HOST_r2 2 -#define HOST_r3 3 -#define HOST_r4 4 -#define HOST_r5 5 -#define HOST_r6 6 -#define HOST_r7 7 -// "hi" registers -#define HOST_r8 8 -#define HOST_r9 9 -#define HOST_r10 10 -#define HOST_r11 11 -#define HOST_r12 12 -#define HOST_r13 13 -#define HOST_r14 14 -#define HOST_r15 15 - -// register aliases -// "lo" registers -#define HOST_a1 HOST_r0 -#define HOST_a2 HOST_r1 -#define HOST_a3 HOST_r2 -#define HOST_a4 HOST_r3 -#define HOST_v1 HOST_r4 -#define HOST_v2 HOST_r5 -#define HOST_v3 HOST_r6 -#define HOST_v4 HOST_r7 -// "hi" registers -#define HOST_v5 HOST_r8 -#define HOST_v6 HOST_r9 -#define HOST_v7 HOST_r10 -#define HOST_v8 HOST_r11 -#define HOST_ip HOST_r12 -#define HOST_sp HOST_r13 -#define HOST_lr HOST_r14 -#define HOST_pc HOST_r15 - - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { -#if (__ARM_EABI__) - //flush cache - eabi - register unsigned long _beg __asm ("a1") = (unsigned long)(block_start); // block start - register unsigned long _end __asm ("a2") = (unsigned long)(block_start+block_size); // block end - register unsigned long _flg __asm ("a3") = 0; - register unsigned long _par __asm ("r7") = 0xf0002; // sys_cacheflush - __asm __volatile ("swi 0x0" - : // no outputs - : "r" (_beg), "r" (_end), "r" (_flg), "r" (_par) - ); -#else -// GP2X BEGIN - //flush cache - old abi - register unsigned long _beg __asm ("a1") = (unsigned long)(block_start); // block start - register unsigned long _end __asm ("a2") = (unsigned long)(block_start+block_size); // block end - register unsigned long _flg __asm ("a3") = 0; - __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" - : // no outputs - : "r" (_beg), "r" (_end), "r" (_flg) - ); -// GP2X END -#endif -} diff --git a/src/cpu/core_dynrec/risc_armv4le-o3.h b/src/cpu/core_dynrec/risc_armv4le-o3.h deleted file mode 100644 index e95edee79..000000000 --- a/src/cpu/core_dynrec/risc_armv4le-o3.h +++ /dev/null @@ -1,1302 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4/ARMv7 (little endian) backend by M-HT (arm version) */ - - -// temporary registers -#define temp1 HOST_ip -#define temp2 HOST_v3 -#define temp3 HOST_v4 - -// register that holds function return values -#define FC_RETOP HOST_a1 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_v2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_v2 - -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 - -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 - -// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code -#define readdata_addr HOST_v5 - - -// helper macro -#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) ) - - -// instruction encodings - -// move -// mov dst, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define MOV_IMM(dst, imm, rimm) (0xe3a00000 + ((dst) << 12) + (imm) + ((rimm) << 7) ) -// mov dst, src, lsl #imm -#define MOV_REG_LSL_IMM(dst, src, imm) (0xe1a00000 + ((dst) << 12) + (src) + ((imm) << 7) ) -// movs dst, src, lsl #imm -#define MOVS_REG_LSL_IMM(dst, src, imm) (0xe1b00000 + ((dst) << 12) + (src) + ((imm) << 7) ) -// mov dst, src, lsr #imm -#define MOV_REG_LSR_IMM(dst, src, imm) (0xe1a00020 + ((dst) << 12) + (src) + ((imm) << 7) ) -// mov dst, src, asr #imm -#define MOV_REG_ASR_IMM(dst, src, imm) (0xe1a00040 + ((dst) << 12) + (src) + ((imm) << 7) ) -// mov dst, src, lsl rreg -#define MOV_REG_LSL_REG(dst, src, rreg) (0xe1a00010 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mov dst, src, lsr rreg -#define MOV_REG_LSR_REG(dst, src, rreg) (0xe1a00030 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mov dst, src, asr rreg -#define MOV_REG_ASR_REG(dst, src, rreg) (0xe1a00050 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mov dst, src, ror rreg -#define MOV_REG_ROR_REG(dst, src, rreg) (0xe1a00070 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mvn dst, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define MVN_IMM(dst, imm, rimm) (0xe3e00000 + ((dst) << 12) + (imm) + ((rimm) << 7) ) -#if C_TARGETCPU == ARMV7LE -// movw dst, #imm @ 0 <= imm <= 65535 -#define MOVW(dst, imm) (0xe3000000 + ((dst) << 12) + (((imm) & 0xf000) << 4) + ((imm) & 0x0fff) ) -// movt dst, #imm @ 0 <= imm <= 65535 -#define MOVT(dst, imm) (0xe3400000 + ((dst) << 12) + (((imm) & 0xf000) << 4) + ((imm) & 0x0fff) ) -#endif - -// arithmetic -// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// add dst, src1, src2, lsl #imm -#define ADD_REG_LSL_IMM(dst, src1, src2, imm) (0xe0800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// sub dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define SUB_IMM(dst, src, imm, rimm) (0xe2400000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// sub dst, src1, src2, lsl #imm -#define SUB_REG_LSL_IMM(dst, src1, src2, imm) (0xe0400000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// rsb dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define RSB_IMM(dst, src, imm, rimm) (0xe2600000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// cmp src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define CMP_IMM(src, imm, rimm) (0xe3500000 + ((src) << 16) + (imm) + ((rimm) << 7) ) -// nop -#if C_TARGETCPU == ARMV7LE -#define NOP (0xe320f000) -#else -#define NOP MOV_REG_LSL_IMM(HOST_r0, HOST_r0, 0) -#endif - -// logical -// tst src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define TST_IMM(src, imm, rimm) (0xe3100000 + ((src) << 16) + (imm) + ((rimm) << 7) ) -// and dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define AND_IMM(dst, src, imm, rimm) (0xe2000000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// and dst, src1, src2, lsl #imm -#define AND_REG_LSL_IMM(dst, src1, src2, imm) (0xe0000000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// orr dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ORR_IMM(dst, src, imm, rimm) (0xe3800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// orr dst, src1, src2, lsl #imm -#define ORR_REG_LSL_IMM(dst, src1, src2, imm) (0xe1800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// orr dst, src1, src2, lsr #imm -#define ORR_REG_LSR_IMM(dst, src1, src2, imm) (0xe1800020 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// eor dst, src1, src2, lsl #imm -#define EOR_REG_LSL_IMM(dst, src1, src2, imm) (0xe0200000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// bic dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define BIC_IMM(dst, src, imm, rimm) (0xe3c00000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// bic dst, src1, src2, lsl #imm @ 0 <= imm <= 31 -#define BIC_REG_LSL_IMM(dst, src1, src2, imm) (0xe1c00000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 4096 -#define LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// ldr reg, [addr, #-(imm)] @ 0 <= imm < 4096 -#define LDR_IMM_M(reg, addr, imm) (0xe5100000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// ldrh reg, [addr, #imm] @ 0 <= imm < 256 -#define LDRH_IMM(reg, addr, imm) (0xe1d000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) ) -// ldrh reg, [addr, #-(imm)] @ 0 <= imm < 256 -#define LDRH_IMM_M(reg, addr, imm) (0xe15000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) ) -// ldrb reg, [addr, #imm] @ 0 <= imm < 4096 -#define LDRB_IMM(reg, addr, imm) (0xe5d00000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// ldrb reg, [addr, #-(imm)] @ 0 <= imm < 4096 -#define LDRB_IMM_M(reg, addr, imm) (0xe5500000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// ldr reg, [addr1, addr2, lsl #imm] @ 0 <= imm < 31 -#define LDR_REG_LSL_IMM(reg, addr1, addr2, imm) (0xe7900000 + ((reg) << 12) + ((addr1) << 16) + (addr2) + ((imm) << 7) ) - -// store -// str reg, [addr, #imm] @ 0 <= imm < 4096 -#define STR_IMM(reg, addr, imm) (0xe5800000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// str reg, [addr, #-(imm)] @ 0 <= imm < 4096 -#define STR_IMM_M(reg, addr, imm) (0xe5000000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// strh reg, [addr, #imm] @ 0 <= imm < 256 -#define STRH_IMM(reg, addr, imm) (0xe1c000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) ) -// strh reg, [addr, #-(imm)] @ 0 <= imm < 256 -#define STRH_IMM_M(reg, addr, imm) (0xe14000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) ) -// strb reg, [addr, #imm] @ 0 <= imm < 4096 -#define STRB_IMM(reg, addr, imm) (0xe5c00000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// strb reg, [addr, #-(imm)] @ 0 <= imm < 4096 -#define STRB_IMM_M(reg, addr, imm) (0xe5400000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// branch -// beq pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define BEQ_FWD(imm) (0x0a000000 + ((imm) >> 2) ) -// bne pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define BNE_FWD(imm) (0x1a000000 + ((imm) >> 2) ) -// ble pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define BLE_FWD(imm) (0xda000000 + ((imm) >> 2) ) -// b pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define B_FWD(imm) (0xea000000 + ((imm) >> 2) ) -// bx reg -#define BX(reg) (0xe12fff10 + (reg) ) -#if C_TARGETCPU == ARMV7LE -// blx reg -#define BLX_REG(reg) (0xe12fff30 + (reg) ) - -// extend -// sxth dst, src, ror #rimm @ rimm = 0 | 8 | 16 | 24 -#define SXTH(dst, src, rimm) (0xe6bf0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) ) -// sxtb dst, src, ror #rimm @ rimm = 0 | 8 | 16 | 24 -#define SXTB(dst, src, rimm) (0xe6af0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) ) -// uxth dst, src, ror #rimm @ rimm = 0 | 8 | 16 | 24 -#define UXTH(dst, src, rimm) (0xe6ff0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) ) -// uxtb dst, src, ror #rimm @ rimm = 0 | 8 | 16 | 24 -#define UXTB(dst, src, rimm) (0xe6ef0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) ) - -// bit field -// bfi dst, src, #lsb, #width @ lsb >= 0, width >= 1, lsb+width <= 32 -#define BFI(dst, src, lsb, width) (0xe7c00010 + ((dst) << 12) + (src) + ((lsb) << 7) + (((lsb) + (width) - 1) << 16) ) -// bfc dst, #lsb, #width @ lsb >= 0, width >= 1, lsb+width <= 32 -#define BFC(dst, lsb, width) (0xe7c0001f + ((dst) << 12) + ((lsb) << 7) + (((lsb) + (width) - 1) << 16) ) -#endif - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addd( MOV_REG_LSL_IMM(reg_dst, reg_src, 0) ); // mov reg_dst, reg_src -} - -// helper function -static bool val_is_operand2(Bit32u value, Bit32u *val_shift) { - Bit32u shift; - - if (GCC_UNLIKELY(value == 0)) { - *val_shift = 0; - return true; - } - - shift = 0; - while ((value & 3) == 0) { - value>>=2; - shift+=2; - } - - if ((value >> 8) != 0) return false; - - *val_shift = shift; - return true; -} - -#if C_TARGETCPU != ARMV7LE -// helper function -static Bits get_imm_gen_len(Bit32u imm) { - Bits ret; - if (imm == 0) { - return 1; - } else { - ret = 0; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - } - ret++; - imm>>=8; - } - return ret; - } -} - -// helper function -static Bits get_min_imm_gen_len(Bit32u imm) { - Bits num1, num2; - - num1 = get_imm_gen_len(imm); - num2 = get_imm_gen_len(~imm); - - return (num1 <= num2)?num1:num2; -} -#endif - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { -#if C_TARGETCPU == ARMV7LE - Bit32u scale; - - if ( val_is_operand2(imm, &scale) ) { - cache_addd( MOV_IMM(dest_reg, imm >> scale, ROTATE_SCALE(scale)) ); // mov dest_reg, #imm - } else if ( val_is_operand2(~imm, &scale) ) { - cache_addd( MVN_IMM(dest_reg, (~imm) >> scale, ROTATE_SCALE(scale)) ); // mvn dest_reg, #~imm - } else { - cache_addd( MOVW(dest_reg, imm & 0xffff) ); // movw dest_reg, #(imm & 0xffff) - - if (imm >= 0x10000) - { - cache_addd( MOVT(dest_reg, imm >> 16) ); // movt dest_reg, #(imm >> 16) - } - } -#else - Bit32u imm2, first, scale; - - scale = 0; - first = 1; - imm2 = ~imm; - - if (get_imm_gen_len(imm) <= get_imm_gen_len(imm2)) { - if (imm == 0) { - cache_addd( MOV_IMM(dest_reg, 0, 0) ); // mov dest_reg, #0 - } else { - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - if (first) { - cache_addd( MOV_IMM(dest_reg, imm & 0xff, ROTATE_SCALE(scale)) ); // mov dest_reg, #((imm & 0xff) << scale) - first = 0; - } else { - cache_addd( ORR_IMM(dest_reg, dest_reg, imm & 0xff, ROTATE_SCALE(scale)) ); // orr dest_reg, dest_reg, #((imm & 0xff) << scale) - } - imm>>=8; - scale+=8; - } - } - } else { - if (imm2 == 0) { - cache_addd( MVN_IMM(dest_reg, 0, 0) ); // mvn dest_reg, #0 - } else { - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - if (first) { - cache_addd( MVN_IMM(dest_reg, imm2 & 0xff, ROTATE_SCALE(scale)) ); // mvn dest_reg, #((imm2 & 0xff) << scale) - first = 0; - } else { - cache_addd( BIC_IMM(dest_reg, dest_reg, imm2 & 0xff, ROTATE_SCALE(scale)) ); // bic dest_reg, dest_reg, #((imm2 & 0xff) << scale) - } - imm2>>=8; - scale+=8; - } - } - } -#endif -} - -// helper function -static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 4096)) { - cache_addd( LDR_IMM(dest_reg, addr_reg, data - addr_data) ); // ldr dest_reg, [addr_reg, #(data - addr_data)] - return true; - } else if ((data < addr_data) && (data > addr_data - 4096)) { - cache_addd( LDR_IMM_M(dest_reg, addr_reg, addr_data - data) ); // ldr dest_reg, [addr_reg, #-(addr_data - data)] - return true; - } - } - break; - case 2: -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 256)) { - cache_addd( LDRH_IMM(dest_reg, addr_reg, data - addr_data) ); // ldrh dest_reg, [addr_reg, #(data - addr_data)] - return true; - } else if ((data < addr_data) && (data > addr_data - 256)) { - cache_addd( LDRH_IMM_M(dest_reg, addr_reg, addr_data - data) ); // ldrh dest_reg, [addr_reg, #-(addr_data - data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 4096)) { - cache_addd( LDRB_IMM(dest_reg, addr_reg, data - addr_data) ); // ldrb dest_reg, [addr_reg, #(data - addr_data)] - return true; - } else if ((data < addr_data) && (data > addr_data - 4096)) { - cache_addd( LDRB_IMM_M(dest_reg, addr_reg, addr_data - data) ); // ldrb dest_reg, [addr_reg, #-(addr_data - data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) { - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_addd( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - cache_addd( LDRH_IMM(temp2, data_reg, 2) ); // ldrh temp2, [data_reg, #2] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 16) ); // orr dest_reg, dest_reg, temp2, lsl #16 - } else { - cache_addd( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addd( LDRH_IMM(temp2, data_reg, 1) ); // ldrh temp2, [data_reg, #1] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) ); // orr dest_reg, dest_reg, temp2, lsl #8 - cache_addd( LDRB_IMM(temp2, data_reg, 3) ); // ldrb temp2, [data_reg, #3] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 24) ); // orr dest_reg, dest_reg, temp2, lsl #24 - } - } else -#endif - { - cache_addd( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg] - } - } else { -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((Bit32u)data & 1) { - cache_addd( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addd( LDRB_IMM(temp2, data_reg, 1) ); // ldrb temp2, [data_reg, #1] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) ); // orr dest_reg, dest_reg, temp2, lsl #8 - } else -#endif - { - cache_addd( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1); - } -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function -static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 4096)) { - cache_addd( STR_IMM(src_reg, addr_reg, data - addr_data) ); // str src_reg, [addr_reg, #(data - addr_data)] - return true; - } else if ((data < addr_data) && (data > addr_data - 4096)) { - cache_addd( STR_IMM_M(src_reg, addr_reg, addr_data - data) ); // str src_reg, [addr_reg, #-(addr_data - data)] - return true; - } - } - break; - case 2: -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 256)) { - cache_addd( STRH_IMM(src_reg, addr_reg, data - addr_data) ); // strh src_reg, [addr_reg, #(data - addr_data)] - return true; - } else if ((data < addr_data) && (data > addr_data - 256)) { - cache_addd( STRH_IMM_M(src_reg, addr_reg, addr_data - data) ); // strh src_reg, [addr_reg, #-(addr_data - data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 4096)) { - cache_addd( STRB_IMM(src_reg, addr_reg, data - addr_data) ); // strb src_reg, [addr_reg, #(data - addr_data)] - return true; - } else if ((data < addr_data) && (data > addr_data - 4096)) { - cache_addd( STRB_IMM_M(src_reg, addr_reg, addr_data - data) ); // strb src_reg, [addr_reg, #-(addr_data - data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) { - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_addd( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 16) ); // mov temp2, src_reg, lsr #16 - cache_addd( STRH_IMM(temp2, data_reg, 2) ); // strh temp2, [data_reg, #2] - } else { - cache_addd( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) ); // mov temp2, src_reg, lsr #8 - cache_addd( STRH_IMM(temp2, data_reg, 1) ); // strh temp2, [data_reg, #1] - cache_addd( MOV_REG_LSR_IMM(temp2, temp2, 16) ); // mov temp2, temp2, lsr #16 - cache_addd( STRB_IMM(temp2, data_reg, 3) ); // strb temp2, [data_reg, #3] - } - } else -#endif - { - cache_addd( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg] - } - } else { -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - if ((Bit32u)dest & 1) { - cache_addd( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) ); // mov temp2, src_reg, lsr #8 - cache_addd( STRB_IMM(temp2, data_reg, 1) ); // strb temp2, [data_reg, #1] - } else -#endif - { - cache_addd( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1); - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - if (!gen_mov_memval_to_reg(dest_reg, data, 1)) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - cache_addd( LDRB_IMM(dest_reg, temp1, 0) ); // ldrb dest_reg, [temp1] - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addd( MOV_IMM(dest_reg, imm, 0) ); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - if (!gen_mov_memval_from_reg(src_reg, dest, 1)) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - cache_addd( STRB_IMM(src_reg, temp1, 0) ); // strb src_reg, [temp1] - } -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - if (sign) { -#if C_TARGETCPU == ARMV7LE - cache_addd( SXTB(reg, reg, 0) ); // sxtb reg, reg -#else - cache_addd( MOV_REG_LSL_IMM(reg, reg, 24) ); // mov reg, reg, lsl #24 - cache_addd( MOV_REG_ASR_IMM(reg, reg, 24) ); // mov reg, reg, asr #24 -#endif - } else { -#if C_TARGETCPU == ARMV7LE - cache_addd( UXTB(reg, reg, 0) ); // uxtb reg, reg -#else - cache_addd( AND_IMM(reg, reg, 0xff, 0) ); // and reg, reg, #0xff -#endif - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - if (sign) { -#if C_TARGETCPU == ARMV7LE - cache_addd( SXTH(reg, reg, 0) ); // sxth reg, reg -#else - cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) ); // mov reg, reg, lsl #16 - cache_addd( MOV_REG_ASR_IMM(reg, reg, 16) ); // mov reg, reg, asr #16 -#endif - } else { -#if C_TARGETCPU == ARMV7LE - cache_addd( UXTH(reg, reg, 0) ); // uxth reg, reg -#else - cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) ); // mov reg, reg, lsl #16 - cache_addd( MOV_REG_LSR_IMM(reg, reg, 16) ); // mov reg, reg, lsr #16 -#endif - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(temp3, op, 1); - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp3, 0) ); // add reg, reg, temp3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - if(!imm) return; - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if ( val_is_operand2(imm, &scale) ) { - cache_addd( ADD_IMM(reg, reg, imm >> scale, ROTATE_SCALE(scale)) ); // add reg, reg, #imm - } else if ( val_is_operand2(imm2, &scale) ) { - cache_addd( SUB_IMM(reg, reg, imm2 >> scale, ROTATE_SCALE(scale)) ); // sub reg, reg, #(-imm) -#if C_TARGETCPU == ARMV7LE - } else if (imm2 < 0x10000) { - cache_addd( MOVW(temp2, imm2) ); // movw temp2, #(-imm) - cache_addd( SUB_REG_LSL_IMM(reg, reg, temp2, 0) ); // sub reg, reg, temp2 -#endif - } else { -#if C_TARGETCPU != ARMV7LE - if (get_min_imm_gen_len(imm) <= get_min_imm_gen_len(imm2)) { -#endif - gen_mov_dword_to_reg_imm(temp2, imm); - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) ); // add reg, reg, temp2 -#if C_TARGETCPU != ARMV7LE - } else { - gen_mov_dword_to_reg_imm(temp2, imm2); - cache_addd( SUB_REG_LSL_IMM(reg, reg, temp2, 0) ); // sub reg, reg, temp2 - } -#endif - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - imm2 = ~imm; - if(!imm2) return; - - if (!imm) { - cache_addd( MOV_IMM(reg, 0, 0) ); // mov reg, #0 - } else if ( val_is_operand2(imm, &scale) ) { - cache_addd( AND_IMM(reg, reg, imm >> scale, ROTATE_SCALE(scale)) ); // and reg, reg, #imm - } else if ( val_is_operand2(imm2, &scale) ) { - cache_addd( BIC_IMM(reg, reg, imm2 >> scale, ROTATE_SCALE(scale)) ); // bic reg, reg, #(~imm) -#if C_TARGETCPU == ARMV7LE - } else if (imm2 < 0x10000) { - cache_addd( MOVW(temp2, imm2) ); // movw temp2, #(~imm) - cache_addd( BIC_REG_LSL_IMM(reg, reg, temp2, 0) ); // bic reg, reg, temp2 -#endif - } else { - gen_mov_dword_to_reg_imm(temp2, imm); - cache_addd( AND_REG_LSL_IMM(reg, reg, temp2, 0) ); // and reg, reg, temp2 - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(temp3, imm); - gen_mov_word_from_reg(temp3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(temp3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - } - gen_add_imm(temp3, imm); - if (!gen_mov_memval_from_reg(temp3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); - } -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, (Bit32s)imm, 1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - Bit32u imm2, scale; - - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(temp3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - } - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if ( val_is_operand2(imm, &scale) ) { - cache_addd( SUB_IMM(temp3, temp3, imm >> scale, ROTATE_SCALE(scale)) ); // sub temp3, temp3, #imm - } else if ( val_is_operand2(imm2, &scale) ) { - cache_addd( ADD_IMM(temp3, temp3, imm2 >> scale, ROTATE_SCALE(scale)) ); // add temp3, temp3, #(-imm) -#if C_TARGETCPU == ARMV7LE - } else if (imm2 < 0x10000) { - cache_addd( MOVW(temp2, imm2) ); // movw temp2, #(-imm) - cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // add temp3, temp3, temp2 -#endif - } else { -#if C_TARGETCPU != ARMV7LE - if (get_min_imm_gen_len(imm) <= get_min_imm_gen_len(imm2)) { -#endif - gen_mov_dword_to_reg_imm(temp2, imm); - cache_addd( SUB_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // sub temp3, temp3, temp2 -#if C_TARGETCPU != ARMV7LE - } else { - gen_mov_dword_to_reg_imm(temp2, imm2); - cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // add temp3, temp3, temp2 - } -#endif - } - - if (!gen_mov_memval_from_reg(temp3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); - } -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - gen_sub_direct_word(dest, (Bit32s)imm, 1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - cache_addd( ADD_REG_LSL_IMM(dest_reg, dest_reg, scale_reg, scale) ); // add dest_reg, dest_reg, scale_reg, lsl #(scale) - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addd( MOV_REG_LSL_IMM(dest_reg, dest_reg, scale) ); // mov dest_reg, dest_reg, lsl #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { -#if C_TARGETCPU == ARMV7LE - cache_addd( MOVW(temp1, ((Bit32u)func) & 0xffff) ); // movw temp1, #(func & 0xffff) - cache_addd( MOVT(temp1, ((Bit32u)func) >> 16) ); // movt temp1, #(func >> 16) - cache_addd( BLX_REG(temp1) ); // blx temp1 -#else - cache_addd( LDR_IMM(temp1, HOST_pc, 4) ); // ldr temp1, [pc, #4] - cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4 - cache_addd( BX(temp1) ); // bx temp1 - cache_addd((Bit32u)func); // .int func -#endif -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - Bit32u scale; - - gen_mov_word_to_reg(temp3, ptr, 1); - -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { -#endif - if ((imm >= 0) && (imm < 4096)) { - cache_addd( LDR_IMM(temp1, temp3, imm) ); // ldr temp1, [temp3, #imm] - } else { - gen_mov_dword_to_reg_imm(temp2, imm); - cache_addd( LDR_REG_LSL_IMM(temp1, temp3, temp2, 0) ); // ldr temp1, [temp3, temp2] - } -#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE)) - } else { - gen_add_imm(temp3, imm); - - cache_addd( LDRB_IMM(temp1, temp3, 0) ); // ldrb temp1, [temp3] - cache_addd( LDRB_IMM(temp2, temp3, 1) ); // ldrb temp2, [temp3, #1] - cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 8) ); // orr temp1, temp1, temp2, lsl #8 - cache_addd( LDRB_IMM(temp2, temp3, 2) ); // ldrb temp2, [temp3, #2] - cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 16) ); // orr temp1, temp1, temp2, lsl #16 - cache_addd( LDRB_IMM(temp2, temp3, 3) ); // ldrb temp2, [temp3, #3] - cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 24) ); // orr temp1, temp1, temp2, lsl #24 - } -#endif - - cache_addd( BX(temp1) ); // bx temp1 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (dword) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - } else { - cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) ); // movs temp1, reg, lsl #16 - } - cache_addd( BEQ_FWD(0) ); // beq j - return ((Bit32u)cache.pos-4); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (dword) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - } else { - cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) ); // movs temp1, reg, lsl #16 - } - cache_addd( BNE_FWD(0) ); // bne j - return ((Bit32u)cache.pos-4); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+8); - if (len<0) len=-len; - if (len>0x02000000) LOG_MSG("Big jump %d",len); -#endif - *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff ); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - if (isdword) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - } else { - cache_addd( TST_IMM(reg, 0xff, 0) ); // tst reg, #0xff - } - cache_addd( BNE_FWD(0) ); // bne j - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - cache_addd( BLE_FWD(0) ); // ble j - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff ); -} - -static void gen_run_code(void) { -#if C_TARGETCPU == ARMV7LE - cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr} - - cache_addd( MOVW(FC_SEGS_ADDR, ((Bit32u)&Segs) & 0xffff) ); // movw FC_SEGS_ADDR, #(&Segs & 0xffff) - cache_addd( MOVT(FC_SEGS_ADDR, ((Bit32u)&Segs) >> 16) ); // movt FC_SEGS_ADDR, #(&Segs >> 16) - - cache_addd( MOVW(FC_REGS_ADDR, ((Bit32u)&cpu_regs) & 0xffff) ); // movw FC_REGS_ADDR, #(&cpu_regs & 0xffff) - cache_addd( MOVT(FC_REGS_ADDR, ((Bit32u)&cpu_regs) >> 16) ); // movt FC_REGS_ADDR, #(&cpu_regs >> 16) - - cache_addd( MOVW(readdata_addr, ((Bitu)&core_dynrec.readdata) & 0xffff) ); // movw readdata_addr, #(&core_dynrec.readdata & 0xffff) - cache_addd( MOVT(readdata_addr, ((Bitu)&core_dynrec.readdata) >> 16) ); // movt readdata_addr, #(&core_dynrec.readdata >> 16) - - cache_addd( BX(HOST_r0) ); // bx r0 -#else - Bit8u *pos1, *pos2, *pos3; - - cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr} - - pos1 = cache.pos; - cache_addd( 0 ); - pos2 = cache.pos; - cache_addd( 0 ); - pos3 = cache.pos; - cache_addd( 0 ); - - cache_addd( BX(HOST_r0) ); // bx r0 - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } - - *(Bit32u*)pos1 = LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - cache_addd((Bit32u)&Segs); // address of "Segs" - - *(Bit32u*)pos2 = LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" - - *(Bit32u*)pos3 = LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)] - cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata" - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } -#endif -} - -// return from a function -static void gen_return_function(void) { - cache_addd(0xe8bd8df0); // ldmfd sp!, {v1-v5,v7,v8,pc} -} - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=ADD_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // add FC_RETOP, a1, a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=ORR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // orr FC_RETOP, a1, a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=AND_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // and FC_RETOP, a1, a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=SUB_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // sub FC_RETOP, a1, a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=EOR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // eor FC_RETOP, a1, a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=ADD_IMM(FC_RETOP, HOST_a1, 1, 0); // add FC_RETOP, a1, #1 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=SUB_IMM(FC_RETOP, HOST_a1, 1, 0); // sub FC_RETOP, a1, #1 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=MOV_REG_LSL_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsl a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_SHRb: - *(Bit32u*)pos=NOP; // nop -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)(pos+4)=BFC(HOST_a1, 8, 24); // bfc a1, 8, 24 - *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsr a2 -#else - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=AND_IMM(FC_RETOP, HOST_a1, 0xff, 0); // and FC_RETOP, a1, #0xff - *(Bit32u*)(pos+12)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2 -#endif - break; - case t_SHRw: - *(Bit32u*)pos=NOP; // nop -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)(pos+4)=BFC(HOST_a1, 16, 16); // bfc a1, 16, 16 - *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsr a2 -#else - *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+8)=MOV_REG_LSR_IMM(FC_RETOP, FC_RETOP, 16); // mov FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2 -#endif - break; - case t_SHRd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsr a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_SARb: - *(Bit32u*)pos=NOP; // nop -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)(pos+4)=SXTB(FC_RETOP, HOST_a1, 0); // sxtb FC_RETOP, a1 - *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2 -#else - *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+8)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 24); // mov FC_RETOP, FC_RETOP, asr #24 - *(Bit32u*)(pos+12)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2 -#endif - break; - case t_SARw: - *(Bit32u*)pos=NOP; // nop -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)(pos+4)=SXTH(FC_RETOP, HOST_a1, 0); // sxth FC_RETOP, a1 - *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2 -#else - *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+8)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 16); // mov FC_RETOP, FC_RETOP, asr #16 - *(Bit32u*)(pos+12)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2 -#endif - break; - case t_SARd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, asr a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_RORb: -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)pos=BFI(HOST_a1, HOST_a1, 8, 8); // bfi a1, a1, 8, 8 - *(Bit32u*)(pos+4)=BFI(HOST_a1, HOST_a1, 16, 16); // bfi a1, a1, 16, 16 - *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 -#else - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 8); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8 - *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2 -#endif - break; - case t_RORw: - *(Bit32u*)pos=NOP; // nop -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)(pos+4)=BFI(HOST_a1, HOST_a1, 16, 16); // bfi a1, a1, 16, 16 - *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 -#else - *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2 -#endif - break; - case t_RORd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - case t_ROLw: -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)pos=BFI(HOST_a1, HOST_a1, 16, 16); // bfi a1, a1, 16, 16 - *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 -#else - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2 -#endif - break; - case t_ROLd: - *(Bit32u*)pos=NOP; // nop -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 -#else - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32 - *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 -#endif - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=NOP; // nop - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=RSB_IMM(FC_RETOP, HOST_a1, 0, 0); // rsb FC_RETOP, a1, #0 -#if C_TARGETCPU != ARMV7LE - *(Bit32u*)(pos+12)=NOP; // nop -#endif - break; - default: -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)pos=MOVW(temp1, ((Bit32u)fct_ptr) & 0xffff); // movw temp1, #(fct_ptr & 0xffff) - *(Bit32u*)(pos+4)=MOVT(temp1, ((Bit32u)fct_ptr) >> 16); // movt temp1, #(fct_ptr >> 16) -#else - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func -#endif - break; - - } -#else -#if C_TARGETCPU == ARMV7LE - *(Bit32u*)pos=MOVW(temp1, ((Bit32u)fct_ptr) & 0xffff); // movw temp1, #(fct_ptr & 0xffff) - *(Bit32u*)(pos+4)=MOVT(temp1, ((Bit32u)fct_ptr) >> 16); // movt temp1, #(fct_ptr >> 16) -#else - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func -#endif -#endif -} -#endif - -static void cache_block_before_close(void) { } - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDRH_IMM(dest_reg, FC_SEGS_ADDR, index) ); // ldrh dest_reg, [FC_SEGS_ADDR, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDR_IMM(dest_reg, FC_SEGS_ADDR, index) ); // ldr dest_reg, [FC_SEGS_ADDR, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_addd( LDR_IMM(temp1, FC_SEGS_ADDR, index) ); // ldr temp1, [FC_SEGS_ADDR, #index] - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp1, 0) ); // add reg, reg, temp1 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrh dest_reg, [FC_REGS_ADDR, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldr dest_reg, [FC_REGS_ADDR, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - if (dword) { - cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldr dest_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrh dest_reg, [FC_REGS_ADDR, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_addd( LDR_IMM(temp2, FC_REGS_ADDR, index) ); // ldr temp2, [FC_REGS_ADDR, #index] - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) ); // add reg, reg, temp2 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) ); // strh src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) ); // str src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - if (dword) { - cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) ); // str src_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) ); // strh src_reg, [FC_REGS_ADDR, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_addd( STRB_IMM(src_reg, FC_REGS_ADDR, index) ); // strb src_reg, [FC_REGS_ADDR, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-s3.h b/src/cpu/core_dynrec/risc_armv4le-s3.h deleted file mode 100644 index c747f9735..000000000 --- a/src/cpu/core_dynrec/risc_armv4le-s3.h +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4 (little endian) backend by M-HT (speed-tweaked arm version) */ - - -// temporary registers -#define temp1 HOST_ip -#define temp2 HOST_v3 -#define temp3 HOST_v4 - -// register that holds function return values -#define FC_RETOP HOST_a1 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_v2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_v2 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 -#endif - - -// helper macro -#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) ) - - -// instruction encodings - -// move -// mov dst, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define MOV_IMM(dst, imm, rimm) (0xe3a00000 + ((dst) << 12) + (imm) + ((rimm) << 7) ) -// mov dst, src, lsl #imm -#define MOV_REG_LSL_IMM(dst, src, imm) (0xe1a00000 + ((dst) << 12) + (src) + ((imm) << 7) ) -// movs dst, src, lsl #imm -#define MOVS_REG_LSL_IMM(dst, src, imm) (0xe1b00000 + ((dst) << 12) + (src) + ((imm) << 7) ) -// mov dst, src, lsr #imm -#define MOV_REG_LSR_IMM(dst, src, imm) (0xe1a00020 + ((dst) << 12) + (src) + ((imm) << 7) ) -// mov dst, src, asr #imm -#define MOV_REG_ASR_IMM(dst, src, imm) (0xe1a00040 + ((dst) << 12) + (src) + ((imm) << 7) ) -// mov dst, src, lsl rreg -#define MOV_REG_LSL_REG(dst, src, rreg) (0xe1a00010 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mov dst, src, lsr rreg -#define MOV_REG_LSR_REG(dst, src, rreg) (0xe1a00030 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mov dst, src, asr rreg -#define MOV_REG_ASR_REG(dst, src, rreg) (0xe1a00050 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mov dst, src, ror rreg -#define MOV_REG_ROR_REG(dst, src, rreg) (0xe1a00070 + ((dst) << 12) + (src) + ((rreg) << 8) ) -// mvn dst, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define MVN_IMM(dst, imm, rimm) (0xe3e00000 + ((dst) << 12) + (imm) + ((rimm) << 7) ) - -// arithmetic -// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// add dst, src1, src2, lsl #imm -#define ADD_REG_LSL_IMM(dst, src1, src2, imm) (0xe0800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// sub dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define SUB_IMM(dst, src, imm, rimm) (0xe2400000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// sub dst, src1, src2, lsl #imm -#define SUB_REG_LSL_IMM(dst, src1, src2, imm) (0xe0400000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// rsb dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define RSB_IMM(dst, src, imm, rimm) (0xe2600000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// cmp src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define CMP_IMM(src, imm, rimm) (0xe3500000 + ((src) << 16) + (imm) + ((rimm) << 7) ) -// nop -#define NOP MOV_REG_LSL_IMM(HOST_r0, HOST_r0, 0) - -// logical -// tst src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define TST_IMM(src, imm, rimm) (0xe3100000 + ((src) << 16) + (imm) + ((rimm) << 7) ) -// and dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define AND_IMM(dst, src, imm, rimm) (0xe2000000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// and dst, src1, src2, lsl #imm -#define AND_REG_LSL_IMM(dst, src1, src2, imm) (0xe0000000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// orr dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ORR_IMM(dst, src, imm, rimm) (0xe3800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) -// orr dst, src1, src2, lsl #imm -#define ORR_REG_LSL_IMM(dst, src1, src2, imm) (0xe1800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// orr dst, src1, src2, lsr #imm -#define ORR_REG_LSR_IMM(dst, src1, src2, imm) (0xe1800020 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// eor dst, src1, src2, lsl #imm -#define EOR_REG_LSL_IMM(dst, src1, src2, imm) (0xe0200000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) ) -// bic dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define BIC_IMM(dst, src, imm, rimm) (0xe3c00000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 4096 -#define LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// ldrh reg, [addr, #imm] @ 0 <= imm < 256 -#define LDRH_IMM(reg, addr, imm) (0xe1d000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) ) -// ldrb reg, [addr, #imm] @ 0 <= imm < 4096 -#define LDRB_IMM(reg, addr, imm) (0xe5d00000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// store -// str reg, [addr, #imm] @ 0 <= imm < 4096 -#define STR_IMM(reg, addr, imm) (0xe5800000 + ((reg) << 12) + ((addr) << 16) + (imm) ) -// strh reg, [addr, #imm] @ 0 <= imm < 256 -#define STRH_IMM(reg, addr, imm) (0xe1c000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) ) -// strb reg, [addr, #imm] @ 0 <= imm < 4096 -#define STRB_IMM(reg, addr, imm) (0xe5c00000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// branch -// beq pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define BEQ_FWD(imm) (0x0a000000 + ((imm) >> 2) ) -// bne pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define BNE_FWD(imm) (0x1a000000 + ((imm) >> 2) ) -// bgt pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define BGT_FWD(imm) (0xca000000 + ((imm) >> 2) ) -// b pc+imm @ 0 <= imm < 32M & imm mod 4 = 0 -#define B_FWD(imm) (0xea000000 + ((imm) >> 2) ) -// bx reg -#define BX(reg) (0xe12fff10 + (reg) ) - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addd( MOV_REG_LSL_IMM(reg_dst, reg_src, 0) ); // mov reg_dst, reg_src -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - Bits first, scale; - if (imm == 0) { - cache_addd( MOV_IMM(dest_reg, 0, 0) ); // mov dest_reg, #0 - } else { - scale = 0; - first = 1; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - if (first) { - cache_addd( MOV_IMM(dest_reg, imm & 0xff, ROTATE_SCALE(scale)) ); // mov dest_reg, #((imm & 0xff) << scale) - first = 0; - } else { - cache_addd( ORR_IMM(dest_reg, dest_reg, imm & 0xff, ROTATE_SCALE(scale)) ); // orr dest_reg, dest_reg, #((imm & 0xff) << scale) - } - imm>>=8; - scale+=8; - } - } -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_addd( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - cache_addd( LDRH_IMM(temp2, data_reg, 2) ); // ldrh temp2, [data_reg, #2] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 16) ); // orr dest_reg, dest_reg, temp2, lsl #16 - } else { - cache_addd( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addd( LDRH_IMM(temp2, data_reg, 1) ); // ldrh temp2, [data_reg, #1] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) ); // orr dest_reg, dest_reg, temp2, lsl #8 - cache_addd( LDRB_IMM(temp2, data_reg, 3) ); // ldrb temp2, [data_reg, #3] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 24) ); // orr dest_reg, dest_reg, temp2, lsl #24 - } - } else { - cache_addd( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg] - } - } else { - if ((Bit32u)data & 1) { - cache_addd( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addd( LDRB_IMM(temp2, data_reg, 1) ); // ldrb temp2, [data_reg, #1] - cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) ); // orr dest_reg, dest_reg, temp2, lsl #8 - } else { - cache_addd( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_addd( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 16) ); // mov temp2, src_reg, lsr #16 - cache_addd( STRH_IMM(temp2, data_reg, 2) ); // strh temp2, [data_reg, #2] - } else { - cache_addd( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) ); // mov temp2, src_reg, lsr #8 - cache_addd( STRH_IMM(temp2, data_reg, 1) ); // strh temp2, [data_reg, #1] - cache_addd( MOV_REG_LSR_IMM(temp2, temp2, 16) ); // mov temp2, temp2, lsr #16 - cache_addd( STRB_IMM(temp2, data_reg, 3) ); // strb temp2, [data_reg, #3] - } - } else { - cache_addd( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg] - } - } else { - if ((Bit32u)dest & 1) { - cache_addd( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) ); // mov temp2, src_reg, lsr #8 - cache_addd( STRB_IMM(temp2, data_reg, 1) ); // strb temp2, [data_reg, #1] - } else { - cache_addd( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - cache_addd( LDRB_IMM(dest_reg, temp1, 0) ); // ldrb dest_reg, [temp1] -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addd( MOV_IMM(dest_reg, imm, 0) ); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - cache_addd( STRB_IMM(src_reg, temp1, 0) ); // strb src_reg, [temp1] -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - if (sign) { - cache_addd( MOV_REG_LSL_IMM(reg, reg, 24) ); // mov reg, reg, lsl #24 - cache_addd( MOV_REG_ASR_IMM(reg, reg, 24) ); // mov reg, reg, asr #24 - } else { - cache_addd( AND_IMM(reg, reg, 0xff, 0) ); // and reg, reg, #0xff - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - if (sign) { - cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) ); // mov reg, reg, lsl #16 - cache_addd( MOV_REG_ASR_IMM(reg, reg, 16) ); // mov reg, reg, asr #16 - } else { - cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) ); // mov reg, reg, lsl #16 - cache_addd( MOV_REG_LSR_IMM(reg, reg, 16) ); // mov reg, reg, lsr #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(temp3, op, 1); - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp3, 0) ); // add reg, reg, temp3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bits scale; - if(!imm) return; - if (imm == 0xffffffff) { - cache_addd( SUB_IMM(reg, reg, 1, 0) ); // sub reg, reg, #1 - } else { - scale = 0; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - cache_addd( ADD_IMM(reg, reg, imm & 0xff, ROTATE_SCALE(scale)) ); // add reg, reg, #((imm & 0xff) << scale) - imm>>=8; - scale+=8; - } - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bits scale; - Bit32u imm2; - imm2 = ~imm; - if(!imm2) return; - if (!imm) { - cache_addd( MOV_IMM(reg, 0, 0) ); // mov reg, #0 - } else { - scale = 0; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - cache_addd( BIC_IMM(reg, reg, imm2 & 0xff, ROTATE_SCALE(scale)) ); // bic reg, reg, #((imm2 & 0xff) << scale) - imm2>>=8; - scale+=8; - } - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(temp3, imm); - gen_mov_word_from_reg(temp3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, 1, temp1); - if (imm >= 0) { - cache_addd( ADD_IMM(temp3, temp3, (Bit32s)imm, 0) ); // add temp3, temp3, #(imm) - } else { - cache_addd( SUB_IMM(temp3, temp3, -((Bit32s)imm), 0) ); // sub temp3, temp3, #(-imm) - } - gen_mov_word_from_reg_helper(temp3, dest, 1, temp1); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - // maybe use function gen_add_imm - if (dword) { - gen_mov_dword_to_reg_imm(temp2, imm); - } else { - gen_mov_word_to_reg_imm(temp2, (Bit16u)imm); - } - cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // add temp3, temp3, temp2 - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, 1, temp1); - if (imm >= 0) { - cache_addd( SUB_IMM(temp3, temp3, (Bit32s)imm, 0) ); // sub temp3, temp3, #(imm) - } else { - cache_addd( ADD_IMM(temp3, temp3, -((Bit32s)imm), 0) ); // add temp3, temp3, #(-imm) - } - gen_mov_word_from_reg_helper(temp3, dest, 1, temp1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - // maybe use function gen_add_imm/gen_sub_imm - if (dword) { - gen_mov_dword_to_reg_imm(temp2, imm); - } else { - gen_mov_word_to_reg_imm(temp2, (Bit16u)imm); - } - cache_addd( SUB_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // sub temp3, temp3, temp2 - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - cache_addd( ADD_REG_LSL_IMM(dest_reg, dest_reg, scale_reg, scale) ); // add dest_reg, dest_reg, scale_reg, lsl #(scale) - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addd( MOV_REG_LSL_IMM(dest_reg, dest_reg, scale) ); // mov dest_reg, dest_reg, lsl #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addd( LDR_IMM(temp1, HOST_pc, 4) ); // ldr temp1, [pc, #4] - cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4 - cache_addd( BX(temp1) ); // bx temp1 - cache_addd((Bit32u)func); // .int func -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - Bits scale; - Bitu imm2; - gen_mov_word_to_reg(temp3, ptr, 1); - - if (imm) { - scale = 0; - imm2 = (Bitu)imm; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - cache_addd( ADD_IMM(temp3, temp3, imm2 & 0xff, ROTATE_SCALE(scale)) ); // add temp3, temp3, #((imm2 & 0xff) << scale) - imm2>>=8; - scale+=8; - } - } - -#if (1) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { - cache_addd( LDR_IMM(temp1, temp3, 0) ); // ldr temp1, [temp3] - } else -#endif - { - cache_addd( LDRB_IMM(temp1, temp3, 0) ); // ldrb temp1, [temp3] - cache_addd( LDRB_IMM(temp2, temp3, 1) ); // ldrb temp2, [temp3, #1] - cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 8) ); // orr temp1, temp1, temp2, lsl #8 - cache_addd( LDRB_IMM(temp2, temp3, 2) ); // ldrb temp2, [temp3, #2] - cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 16) ); // orr temp1, temp1, temp2, lsl #16 - cache_addd( LDRB_IMM(temp2, temp3, 3) ); // ldrb temp2, [temp3, #3] - cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 24) ); // orr temp1, temp1, temp2, lsl #24 - } - - cache_addd( BX(temp1) ); // bx temp1 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (dword) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - } else { - cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) ); // movs temp1, reg, lsl #16 - } - cache_addd( BEQ_FWD(0) ); // beq j - return ((Bit32u)cache.pos-4); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (dword) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - } else { - cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) ); // movs temp1, reg, lsl #16 - } - cache_addd( BNE_FWD(0) ); // bne j - return ((Bit32u)cache.pos-4); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+8); - if (len<0) len=-len; - if (len>0x02000000) LOG_MSG("Big jump %d",len); -#endif - *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff ); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - if (isdword) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - } else { - cache_addd( TST_IMM(reg, 0xff, 0) ); // tst reg, #0xff - } - cache_addd( BEQ_FWD(8) ); // beq nobranch (pc +8) - cache_addd( LDR_IMM(temp1, HOST_pc, 0) ); // ldr temp1, [pc, #0] - cache_addd( BX(temp1) ); // bx temp1 - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0 - cache_addd( BGT_FWD(8) ); // bgt nobranch (pc+8) - cache_addd( LDR_IMM(temp1, HOST_pc, 0) ); // ldr temp1, [pc, #0] - cache_addd( BX(temp1) ); // bx temp1 - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=(Bit32u)cache.pos; -} - -static void gen_run_code(void) { - cache_addd(0xe92d4000); // stmfd sp!, {lr} - cache_addd(0xe92d0cf0); // stmfd sp!, {v1-v4,v7,v8} - - // adr: 8 - cache_addd( LDR_IMM(FC_SEGS_ADDR, HOST_pc, 64 - (8 + 8)) ); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - // adr: 12 - cache_addd( LDR_IMM(FC_REGS_ADDR, HOST_pc, 68 - (12 + 8)) ); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - - cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4 - cache_addd(0xe92d4000); // stmfd sp!, {lr} - cache_addd( BX(HOST_r0) ); // bx r0 - - cache_addd(0xe8bd0cf0); // ldmfd sp!, {v1-v4,v7,v8} - - cache_addd(0xe8bd4000); // ldmfd sp!, {lr} - cache_addd( BX(HOST_lr) ); // bx lr - - // fill up to 64 bytes - cache_addd( NOP ); // nop - cache_addd( NOP ); // nop - cache_addd( NOP ); // nop - cache_addd( NOP ); // nop - cache_addd( NOP ); // nop - cache_addd( NOP ); // nop - - // adr: 64 - cache_addd((Bit32u)&Segs); // address of "Segs" - // adr: 68 - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" -} - -// return from a function -static void gen_return_function(void) { - cache_addd(0xe8bd4000); // ldmfd sp!, {lr} - cache_addd( BX(HOST_lr) ); // bx lr -} - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=ADD_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // add FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=ORR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // orr FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=AND_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // and FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=SUB_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // sub FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=EOR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // eor FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=B_FWD(8); // b (pc+2*4) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=ADD_IMM(FC_RETOP, HOST_a1, 1, 0); // add FC_RETOP, a1, #1 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=SUB_IMM(FC_RETOP, HOST_a1, 1, 0); // sub FC_RETOP, a1, #1 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit32u*)pos=MOV_REG_LSL_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsl a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SHRb: - *(Bit32u*)pos=AND_IMM(FC_RETOP, HOST_a1, 0xff, 0); // and FC_RETOP, a1, #0xff - *(Bit32u*)(pos+4)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2 - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SHRw: - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=MOV_REG_LSR_IMM(FC_RETOP, FC_RETOP, 16); // mov FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2 - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SHRd: - *(Bit32u*)pos=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsr a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SARb: - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 24); // mov FC_RETOP, FC_RETOP, asr #24 - *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2 - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SARw: - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 16); // mov FC_RETOP, FC_RETOP, asr #16 - *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2 - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_SARd: - *(Bit32u*)pos=MOV_REG_ASR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, asr a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_RORb: - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 8); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8 - *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2 - break; - case t_RORw: - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_RORd: - *(Bit32u*)pos=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_ROLw: - *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2 - break; - case t_ROLd: - *(Bit32u*)pos=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32 - *(Bit32u*)(pos+4)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2 - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=RSB_IMM(FC_RETOP, HOST_a1, 0, 0); // rsb FC_RETOP, a1, #0 - *(Bit32u*)(pos+4)=NOP; // nop - *(Bit32u*)(pos+8)=NOP; // nop - *(Bit32u*)(pos+12)=NOP; // nop - break; - default: - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func - break; - - } -#else - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func -#endif -} -#endif - -static void cache_block_before_close(void) { } - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDRH_IMM(dest_reg, FC_SEGS_ADDR, index) ); // ldrh dest_reg, [FC_SEGS_ADDR, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDR_IMM(dest_reg, FC_SEGS_ADDR, index) ); // ldr dest_reg, [FC_SEGS_ADDR, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_addd( LDR_IMM(temp1, FC_SEGS_ADDR, index) ); // ldr temp1, [FC_SEGS_ADDR, #index] - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp1, 0) ); // add reg, reg, temp1 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrh dest_reg, [FC_REGS_ADDR, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldr dest_reg, [FC_REGS_ADDR, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - if (dword) { - cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldr dest_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrh dest_reg, [FC_REGS_ADDR, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_addd( LDR_IMM(temp2, FC_REGS_ADDR, index) ); // ldr temp2, [FC_REGS_ADDR, #index] - cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) ); // add reg, reg, temp2 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) ); // strh src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) ); // str src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - if (dword) { - cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) ); // str src_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) ); // strh src_reg, [FC_REGS_ADDR, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_addd( STRB_IMM(src_reg, FC_REGS_ADDR, index) ); // strb src_reg, [FC_REGS_ADDR, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-thumb-iw.h b/src/cpu/core_dynrec/risc_armv4le-thumb-iw.h deleted file mode 100644 index f962c5bf4..000000000 --- a/src/cpu/core_dynrec/risc_armv4le-thumb-iw.h +++ /dev/null @@ -1,1505 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4 (little endian) backend by M-HT (thumb version with data pool, requires -mthumb-interwork switch when compiling dosbox) */ - - -// temporary "lo" registers -#define templo1 HOST_v3 -#define templo2 HOST_v4 -#define templo3 HOST_v2 - -// register that holds function return values -#define FC_RETOP HOST_a1 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_a4 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_a4 - -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 - -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 - -// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code -#define readdata_addr HOST_v5 - - -// instruction encodings - -// move -// mov dst, #imm @ 0 <= imm <= 255 -#define MOV_IMM(dst, imm) (0x2000 + ((dst) << 8) + (imm) ) -// mov dst, src -#define MOV_REG(dst, src) ADD_IMM3(dst, src, 0) -// mov dst, src -#define MOV_LO_HI(dst, src) (0x4640 + (dst) + (((src) - HOST_r8) << 3) ) -// mov dst, src -#define MOV_HI_LO(dst, src) (0x4680 + ((dst) - HOST_r8) + ((src) << 3) ) - -// arithmetic -// add dst, src, #imm @ 0 <= imm <= 7 -#define ADD_IMM3(dst, src, imm) (0x1c00 + (dst) + ((src) << 3) + ((imm) << 6) ) -// add dst, #imm @ 0 <= imm <= 255 -#define ADD_IMM8(dst, imm) (0x3000 + ((dst) << 8) + (imm) ) -// add dst, src1, src2 -#define ADD_REG(dst, src1, src2) (0x1800 + (dst) + ((src1) << 3) + ((src2) << 6) ) -// add dst, pc, #imm @ 0 <= imm < 1024 & imm mod 4 = 0 -#define ADD_LO_PC_IMM(dst, imm) (0xa000 + ((dst) << 8) + ((imm) >> 2) ) -// sub dst, src1, src2 -#define SUB_REG(dst, src1, src2) (0x1a00 + (dst) + ((src1) << 3) + ((src2) << 6) ) -// sub dst, src, #imm @ 0 <= imm <= 7 -#define SUB_IMM3(dst, src, imm) (0x1e00 + (dst) + ((src) << 3) + ((imm) << 6) ) -// sub dst, #imm @ 0 <= imm <= 255 -#define SUB_IMM8(dst, imm) (0x3800 + ((dst) << 8) + (imm) ) -// neg dst, src -#define NEG(dst, src) (0x4240 + (dst) + ((src) << 3) ) -// cmp dst, #imm @ 0 <= imm <= 255 -#define CMP_IMM(dst, imm) (0x2800 + ((dst) << 8) + (imm) ) -// nop -#define NOP (0x46c0) - -// logical -// and dst, src -#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) ) -// bic dst, src -#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) ) -// eor dst, src -#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) ) -// orr dst, src -#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) ) -// mvn dst, src -#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) ) - -// shift/rotate -// lsl dst, src, #imm -#define LSL_IMM(dst, src, imm) (0x0000 + (dst) + ((src) << 3) + ((imm) << 6) ) -// lsl dst, reg -#define LSL_REG(dst, reg) (0x4080 + (dst) + ((reg) << 3) ) -// lsr dst, src, #imm -#define LSR_IMM(dst, src, imm) (0x0800 + (dst) + ((src) << 3) + ((imm) << 6) ) -// lsr dst, reg -#define LSR_REG(dst, reg) (0x40c0 + (dst) + ((reg) << 3) ) -// asr dst, src, #imm -#define ASR_IMM(dst, src, imm) (0x1000 + (dst) + ((src) << 3) + ((imm) << 6) ) -// asr dst, reg -#define ASR_REG(dst, reg) (0x4100 + (dst) + ((reg) << 3) ) -// ror dst, reg -#define ROR_REG(dst, reg) (0x41c0 + (dst) + ((reg) << 3) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0 -#define LDR_IMM(reg, addr, imm) (0x6800 + (reg) + ((addr) << 3) + ((imm) << 4) ) -// ldrh reg, [addr, #imm] @ 0 <= imm < 64 & imm mod 2 = 0 -#define LDRH_IMM(reg, addr, imm) (0x8800 + (reg) + ((addr) << 3) + ((imm) << 5) ) -// ldrb reg, [addr, #imm] @ 0 <= imm < 32 -#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) ) -// ldr reg, [pc, #imm] @ 0 <= imm < 1024 & imm mod 4 = 0 -#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) ) -// ldr reg, [addr1, addr2] -#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) ) - -// store -// str reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0 -#define STR_IMM(reg, addr, imm) (0x6000 + (reg) + ((addr) << 3) + ((imm) << 4) ) -// strh reg, [addr, #imm] @ 0 <= imm < 64 & imm mod 2 = 0 -#define STRH_IMM(reg, addr, imm) (0x8000 + (reg) + ((addr) << 3) + ((imm) << 5) ) -// strb reg, [addr, #imm] @ 0 <= imm < 32 -#define STRB_IMM(reg, addr, imm) (0x7000 + (reg) + ((addr) << 3) + ((imm) << 6) ) - -// branch -// beq pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BEQ_FWD(imm) (0xd000 + ((imm) >> 1) ) -// bne pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BNE_FWD(imm) (0xd100 + ((imm) >> 1) ) -// bgt pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BGT_FWD(imm) (0xdc00 + ((imm) >> 1) ) -// b pc+imm @ 0 <= imm < 2048 & imm mod 2 = 0 -#define B_FWD(imm) (0xe000 + ((imm) >> 1) ) -// bx reg -#define BX(reg) (0x4700 + ((reg) << 3) ) - - -// arm instructions - -// arithmetic -// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 4096 -#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// store -// str reg, [addr, #-(imm)]! @ 0 <= imm < 4096 -#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// branch -// bx reg -#define ARM_BX(reg) (0xe12fff10 + (reg) ) - - -// data pool defines -#define CACHE_DATA_JUMP (2) -#define CACHE_DATA_ALIGN (32) -#define CACHE_DATA_MIN (32) -#define CACHE_DATA_MAX (288) - -// data pool variables -static Bit8u * cache_datapos = NULL; // position of data pool in the cache block -static Bit32u cache_datasize = 0; // total size of data pool -static Bit32u cache_dataindex = 0; // used size of data pool = index of free data item (in bytes) in data pool - - -// forwarded function -static void INLINE gen_create_branch_short(void * func); - -// function to check distance to data pool -// if too close, then generate jump after data pool -static void cache_checkinstr(Bit32u size) { - if (cache_datasize == 0) { - if (cache_datapos != NULL) { - if (cache.pos + size + CACHE_DATA_JUMP >= cache_datapos) { - cache_datapos = NULL; - } - } - return; - } - - if (cache.pos + size + CACHE_DATA_JUMP <= cache_datapos) return; - - { - register Bit8u * newcachepos; - - newcachepos = cache_datapos + cache_datasize; - gen_create_branch_short(newcachepos); - cache.pos = newcachepos; - } - - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - cache_datasize = 0; - cache_dataindex = 0; -} - -// function to reserve item in data pool -// returns address of item -static Bit8u * cache_reservedata(void) { - // if data pool not yet initialized, then initialize data pool - if (GCC_UNLIKELY(cache_datapos == NULL)) { - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN < cache.block.active->cache.start + CACHE_DATA_MAX) { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - // if data pool not yet used, then set data pool - if (cache_datasize == 0) { - // set data pool address is too close (or behind) cache.pos then set new data pool size - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_JUMP /*+ CACHE_DATA_ALIGN*/ > cache_datapos) { - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - } - // set initial data pool size - cache_datasize = CACHE_DATA_ALIGN; - } - - // if data pool is full, then enlarge data pool - if (cache_dataindex == cache_datasize) { - cache_datasize += CACHE_DATA_ALIGN; - } - - cache_dataindex += 4; - return (cache_datapos + (cache_dataindex - 4)); -} - -static void cache_block_before_close(void) { - // if data pool in use, then resize cache block to include the data pool - if (cache_datasize != 0) - { - cache.pos = cache_datapos + cache_dataindex; - } - - // clear the values before next use - cache_datapos = NULL; - cache_datasize = 0; - cache_dataindex = 0; -} - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_checkinstr(2); - cache_addw( MOV_REG(reg_dst, reg_src) ); // mov reg_dst, reg_src -} - -// helper function -static bool val_single_shift(Bit32u value, Bit32u *val_shift) { - Bit32u shift; - - if (GCC_UNLIKELY(value == 0)) { - *val_shift = 0; - return true; - } - - shift = 0; - while ((value & 1) == 0) { - value>>=1; - shift+=1; - } - - if ((value >> 8) != 0) return false; - - *val_shift = shift; - return true; -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - Bit32u scale; - - if (imm < 256) { - cache_checkinstr(2); - cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm) - } else if ((~imm) < 256) { - cache_checkinstr(4); - cache_addw( MOV_IMM(dest_reg, ~imm) ); // mov dest_reg, #(~imm) - cache_addw( MVN(dest_reg, dest_reg) ); // mvn dest_reg, dest_reg - } else if (val_single_shift(imm, &scale)) { - cache_checkinstr(4); - cache_addw( MOV_IMM(dest_reg, imm >> scale) ); // mov dest_reg, #(imm >> scale) - cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #scale - } else { - Bit32u diff; - - cache_checkinstr(4); - - diff = imm - ((Bit32u)cache.pos+4); - - if ((diff < 1024) && ((imm & 0x03) == 0)) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( ADD_LO_PC_IMM(dest_reg, diff >> 2) ); // add dest_reg, pc, #(diff >> 2) - } else { - cache_addw( NOP ); // nop - cache_addw( ADD_LO_PC_IMM(dest_reg, (diff - 2) >> 2) ); // add dest_reg, pc, #((diff - 2) >> 2) - } - } else { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=imm; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 4)) ); // ldr dest_reg, [pc, datapos] - } else { - cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 2)) ); // ldr dest_reg, [pc, datapos] - } - } - } -} - -// helper function -static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) ); // ldr dest_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 2: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) ); // ldrh dest_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 32)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) ); // ldrb dest_reg, [templo2, #(data - addr_data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) { - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_checkinstr(8); - cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - cache_addw( LDRH_IMM(templo1, data_reg, 2) ); // ldrh templo1, [data_reg, #2] - cache_addw( LSL_IMM(templo1, templo1, 16) ); // lsl templo1, templo1, #16 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } else { - cache_checkinstr(16); - cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addw( ADD_IMM3(templo1, data_reg, 1) ); // add templo1, data_reg, #1 - cache_addw( LDRH_IMM(templo1, templo1, 0) ); // ldrh templo1, [templo1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - cache_addw( LDRB_IMM(templo1, data_reg, 3) ); // ldrb templo1, [data_reg, #3] - cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } - } else -#endif - { - cache_checkinstr(2); - cache_addw( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg] - } - } else { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)data & 1) { - cache_checkinstr(8); - cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addw( LDRB_IMM(templo1, data_reg, 1) ); // ldrb templo1, [data_reg, #1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } else -#endif - { - cache_checkinstr(2); - cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2); - } -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function -static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STR_IMM(src_reg, templo2, data - addr_data) ); // str src_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 2: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) ); // strh src_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 32)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) ); // strb src_reg, [templo2, #(data - addr_data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) { - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_checkinstr(8); - cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 16) ); // lsr templo1, templo1, #16 - cache_addw( STRH_IMM(templo1, data_reg, 2) ); // strh templo1, [data_reg, #2] - } else { - cache_checkinstr(20); - cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8 - cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 16) ); // lsr templo1, templo1, #16 - cache_addw( STRB_IMM(templo1, data_reg, 2) ); // strb templo1, [data_reg, #2] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 24) ); // lsr templo1, templo1, #24 - cache_addw( STRB_IMM(templo1, data_reg, 3) ); // strb templo1, [data_reg, #3] - } - } else -#endif - { - cache_checkinstr(2); - cache_addw( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg] - } - } else { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)dest & 1) { - cache_checkinstr(8); - cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8 - cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1] - } else -#endif - { - cache_checkinstr(2); - cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2); - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - if (!gen_mov_memval_to_reg(dest_reg, data, 1)) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)data); - cache_checkinstr(2); - cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1] - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_checkinstr(2); - cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - if (!gen_mov_memval_from_reg(src_reg, dest, 1)) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest); - cache_checkinstr(2); - cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1] - } -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw( LSL_IMM(reg, reg, 24) ); // lsl reg, reg, #24 - - if (sign) { - cache_addw( ASR_IMM(reg, reg, 24) ); // asr reg, reg, #24 - } else { - cache_addw( LSR_IMM(reg, reg, 24) ); // lsr reg, reg, #24 - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw( LSL_IMM(reg, reg, 16) ); // lsl reg, reg, #16 - - if (sign) { - cache_addw( ASR_IMM(reg, reg, 16) ); // asr reg, reg, #16 - } else { - cache_addw( LSR_IMM(reg, reg, 16) ); // lsr reg, reg, #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(templo3, op, 1); - cache_checkinstr(2); - cache_addw( ADD_REG(reg, reg, templo3) ); // add reg, reg, templo3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - if(!imm) return; - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if (imm <= 255) { - cache_checkinstr(2); - cache_addw( ADD_IMM8(reg, imm) ); // add reg, #imm - } else if (imm2 <= 255) { - cache_checkinstr(2); - cache_addw( SUB_IMM8(reg, imm2) ); // sub reg, #(-imm) - } else { - if (val_single_shift(imm2, &scale)) { - cache_checkinstr((scale)?6:4); - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( SUB_REG(reg, reg, templo1) ); // sub reg, reg, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1 - } - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - imm2 = ~imm; - if(!imm2) return; - - if (!imm) { - cache_checkinstr(2); - cache_addw( MOV_IMM(reg, 0) ); // mov reg, #0 - } else { - if (val_single_shift(imm2, &scale)) { - cache_checkinstr((scale)?6:4); - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( BIC(reg, templo1) ); // bic reg, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw( AND(reg, templo1) ); // and reg, templo1 - } - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(templo3, imm); - gen_mov_word_from_reg(templo3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templo3, dest, dword, templo2); - } - gen_add_imm(templo3, imm); - if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(templo3, dest, dword, templo2); - } -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, (Bit32s)imm, 1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - Bit32u imm2, scale; - - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templo3, dest, dword, templo2); - } - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if (imm <= 255) { - cache_checkinstr(2); - cache_addw( SUB_IMM8(templo3, imm) ); // sub templo3, #imm - } else if (imm2 <= 255) { - cache_checkinstr(2); - cache_addw( ADD_IMM8(templo3, imm2) ); // add templo3, #(-imm) - } else { - if (val_single_shift(imm2, &scale)) { - cache_checkinstr((scale)?6:4); - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1 - } - } - - if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(templo3, dest, dword, templo2); - } -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - gen_sub_direct_word(dest, (Bit32s)imm, 1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(4); - cache_addw( LSL_IMM(templo1, scale_reg, scale) ); // lsl templo1, scale_reg, #(scale) - cache_addw( ADD_REG(dest_reg, dest_reg, templo1) ); // add dest_reg, dest_reg, templo1 - } else { - cache_checkinstr(2); - cache_addw( ADD_REG(dest_reg, dest_reg, scale_reg) ); // add dest_reg, dest_reg, scale_reg - } - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(2); - cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// helper function for gen_call_function_raw and gen_call_function_setup -static void gen_call_function_helper(void * func) { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=(Bit32u)func; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) ); // ldr templo1, [pc, datapos] - cache_addw( ADD_LO_PC_IMM(templo2, 8) ); // adr templo2, after_call (add templo2, pc, #8) - cache_addw( ADD_IMM8(templo2, 1) ); // add templo2, #1 - cache_addw( MOV_HI_LO(HOST_lr, templo2) ); // mov lr, templo2 - cache_addw( BX(templo1) ); // bx templo1 --- switch to arm state - cache_addw( NOP ); // nop - } else { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) ); // ldr templo1, [pc, datapos] - cache_addw( ADD_LO_PC_IMM(templo2, 4) ); // adr templo2, after_call (add templo2, pc, #4) - cache_addw( ADD_IMM8(templo2, 1) ); // add templo2, #1 - cache_addw( MOV_HI_LO(HOST_lr, templo2) ); // mov lr, templo2 - cache_addw( BX(templo1) ); // bx templo1 --- switch to arm state - } - // after_call: - - // thumb state from now on -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_checkinstr(12); - gen_call_function_helper(func); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - cache_checkinstr(12); - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_helper(func); - return proc_addr; - // if proc_addr is on word boundary ((proc_addr & 0x03) == 0) - // then length of generated code is 12 bytes - // otherwise length of generated code is 10 bytes -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(templo3, ptr, 1); - -#if !defined(C_UNALIGNED_MEMORY) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { -#endif - if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) { - cache_checkinstr(6); - cache_addw( LDR_IMM(templo2, templo3, imm) ); // ldr templo2, [templo3, #imm] - } else { - gen_mov_dword_to_reg_imm(templo2, imm); - cache_checkinstr(6); - cache_addw( LDR_REG(templo2, templo3, templo2) ); // ldr templo2, [templo3, templo2] - } -#if !defined(C_UNALIGNED_MEMORY) - } else { - gen_add_imm(templo3, imm); - - cache_checkinstr(24); - cache_addw( LDRB_IMM(templo2, templo3, 0) ); // ldrb templo2, [templo3] - cache_addw( LDRB_IMM(templo1, templo3, 1) ); // ldrb templo1, [templo3, #1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - cache_addw( LDRB_IMM(templo1, templo3, 2) ); // ldrb templo1, [templo3, #2] - cache_addw( LSL_IMM(templo1, templo1, 16) ); // lsl templo1, templo1, #16 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - cache_addw( LDRB_IMM(templo1, templo3, 3) ); // ldrb templo1, [templo3, #3] - cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - } -#endif - - // increase jmp address to keep thumb state - cache_addw( ADD_IMM3(templo2, templo2, 1) ); // add templo2, templo2, #1 - - cache_addw( BX(templo2) ); // bx templo2 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo1, reg, 16) ); // lsl templo1, reg, #16 - } - cache_addw( BEQ_FWD(0) ); // beq j - return ((Bit32u)cache.pos-2); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo1, reg, 16) ); // lsl templo1, reg, #16 - } - cache_addw( BNE_FWD(0) ); // bne j - return ((Bit32u)cache.pos-2); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+4); - if (len<0) len=-len; - if (len>252) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 ); -} - - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - if (isdword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo2, reg, 24) ); // lsl templo2, reg, #24 - } - cache_addw( BEQ_FWD(2) ); // beq nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) ); // ldr templo1, [pc, datapos] - } else { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) ); // ldr templo1, [pc, datapos] - } - cache_addw( BX(templo1) ); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - cache_addw( BGT_FWD(2) ); // bgt nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) ); // ldr templo1, [pc, datapos] - } else { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) ); // ldr templo1, [pc, datapos] - } - cache_addw( BX(templo1) ); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state -} - -static void gen_run_code(void) { - Bit8u *pos1, *pos2, *pos3; - -#if (__ARM_EABI__) - // 8-byte stack alignment - cache_addd(0xe92d4ff0); // stmfd sp!, {v1-v8,lr} -#else - cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr} -#endif - - cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) ); // add r0, r0, #1 - - pos1 = cache.pos; - cache_addd( 0 ); - pos2 = cache.pos; - cache_addd( 0 ); - pos3 = cache.pos; - cache_addd( 0 ); - - cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4 - cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) ); // str lr, [sp, #-4]! - cache_addd( ARM_BX(HOST_r0) ); // bx r0 - -#if (__ARM_EABI__) - cache_addd(0xe8bd4ff0); // ldmfd sp!, {v1-v8,lr} -#else - cache_addd(0xe8bd4df0); // ldmfd sp!, {v1-v5,v7,v8,lr} -#endif - cache_addd( ARM_BX(HOST_lr) ); // bx lr - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } - - *(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - cache_addd((Bit32u)&Segs); // address of "Segs" - - *(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" - - *(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)] - cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata" - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } -} - -// return from a function -static void gen_return_function(void) { - cache_checkinstr(4); - cache_addw(0xbc08); // pop {r3} - cache_addw( BX(HOST_r3) ); // bx r3 -} - - -// short unconditional jump (over data pool) -// must emit at most CACHE_DATA_JUMP bytes -static void INLINE gen_create_branch_short(void * func) { - cache_addw( B_FWD((Bit32u)func - ((Bit32u)cache.pos + 4)) ); // b func -} - - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { - if ((*(Bit16u*)pos & 0xf000) == 0xe000) { - if ((*(Bit16u*)pos & 0x0fff) >= ((CACHE_DATA_ALIGN / 2) - 1) && - (*(Bit16u*)pos & 0x0fff) < 0x0800) - { - pos = (Bit8u *) ( ( ( (Bit32u)(*(Bit16u*)pos & 0x0fff) ) << 1 ) + ((Bit32u)pos + 4) ); - } - } - -#ifdef DRC_FLAGS_INVALIDATION_DCODE - if (((Bit32u)pos & 0x03) == 0) - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2); // add a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=ORR(HOST_a1, HOST_a2); // orr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=AND(HOST_a1, HOST_a2); // and a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2); // sub a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=EOR(HOST_a1, HOST_a2); // eor a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=B_FWD(8); // b after_call (pc+8) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1); // add a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1); // sub a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2); // lsl a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_SHRb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 24); // lsr a1, a1, #24 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+10)=NOP; // nop - break; - case t_SHRw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 16); // lsr a1, a1, #16 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+10)=NOP; // nop - break; - case t_SHRd: - *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_SARb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 24); // asr a1, a1, #24 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+10)=NOP; // nop - break; - case t_SARw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 16); // asr a1, a1, #16 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+10)=NOP; // nop - break; - case t_SARd: - *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_RORb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_RORw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+4)=NOP; // nop - *(Bit16u*)(pos+6)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+8)=NOP; // nop - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_RORd: - *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - case t_ROLw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_ROLd: - *(Bit16u*)pos=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+10)=NOP; // nop - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=NEG(HOST_a1, HOST_a1); // neg a1, a1 - *(Bit16u*)(pos+2)=B_FWD(6); // b after_call (pc+6) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - break; - } - } - else - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2); // add a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=ORR(HOST_a1, HOST_a2); // orr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=AND(HOST_a1, HOST_a2); // and a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2); // sub a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=EOR(HOST_a1, HOST_a2); // eor a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=B_FWD(6); // b after_call (pc+6) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1); // add a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1); // sub a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2); // lsl a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_SHRb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 24); // lsr a1, a1, #24 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - break; - case t_SHRw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 16); // lsr a1, a1, #16 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - break; - case t_SHRd: - *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_SARb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 24); // asr a1, a1, #24 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - break; - case t_SARw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 16); // asr a1, a1, #16 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - break; - case t_SARd: - *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_RORw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+4)=NOP; // nop - *(Bit16u*)(pos+6)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+8)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_RORd: - *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - case t_ROLd: - *(Bit16u*)pos=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+2)=NOP; // nop - *(Bit16u*)(pos+4)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=NEG(HOST_a1, HOST_a1); // neg a1, a1 - *(Bit16u*)(pos+2)=B_FWD(4); // b after_call (pc+4) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - break; - } - - } -#else - if (((Bit32u)pos & 0x03) == 0) - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - } - else - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - } -#endif -} -#endif - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDRH_IMM(dest_reg, templo1, index) ); // ldrh dest_reg, [templo1, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDR_IMM(dest_reg, templo1, index) ); // ldr dest_reg, [templo1, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDR_IMM(templo2, templo1, index) ); // ldr templo2, [templo1, #index] - cache_addw( ADD_REG(reg, reg, templo2) ); // add reg, reg, templo2 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRH_IMM(dest_reg, templo2, index) ); // ldrh dest_reg, [templo2, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDR_IMM(dest_reg, templo2, index) ); // ldr dest_reg, [templo2, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - if (dword) { - cache_addw( LDR_IMM(dest_reg, templo2, index) ); // ldr dest_reg, [templo2, #index] - } else { - cache_addw( LDRH_IMM(dest_reg, templo2, index) ); // ldrh dest_reg, [templo2, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRB_IMM(dest_reg, templo2, index) ); // ldrb dest_reg, [templo2, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRB_IMM(dest_reg, templo2, index) ); // ldrb dest_reg, [templo2, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDR_IMM(templo1, templo2, index) ); // ldr templo1, [templo2, #index] - cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STRH_IMM(src_reg, templo1, index) ); // strh src_reg, [templo1, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STR_IMM(src_reg, templo1, index) ); // str src_reg, [templo1, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - if (dword) { - cache_addw( STR_IMM(src_reg, templo1, index) ); // str src_reg, [templo1, #index] - } else { - cache_addw( STRH_IMM(src_reg, templo1, index) ); // strh src_reg, [templo1, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STRB_IMM(src_reg, templo1, index) ); // strb src_reg, [templo1, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-thumb-niw.h b/src/cpu/core_dynrec/risc_armv4le-thumb-niw.h deleted file mode 100644 index 2a6b24bea..000000000 --- a/src/cpu/core_dynrec/risc_armv4le-thumb-niw.h +++ /dev/null @@ -1,1538 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4 (little endian) backend by M-HT (thumb version with data pool) */ - - -// temporary "lo" registers -#define templo1 HOST_v3 -#define templo2 HOST_v4 -#define templo3 HOST_v2 - -// register that holds function return values -#define FC_RETOP HOST_a1 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_a4 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_a4 - -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 - -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 - -// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code -#define readdata_addr HOST_v5 - - -// instruction encodings - -// move -// mov dst, #imm @ 0 <= imm <= 255 -#define MOV_IMM(dst, imm) (0x2000 + ((dst) << 8) + (imm) ) -// mov dst, src -#define MOV_REG(dst, src) ADD_IMM3(dst, src, 0) -// mov dst, src -#define MOV_LO_HI(dst, src) (0x4640 + (dst) + (((src) - HOST_r8) << 3) ) -// mov dst, src -#define MOV_HI_LO(dst, src) (0x4680 + ((dst) - HOST_r8) + ((src) << 3) ) - -// arithmetic -// add dst, src, #imm @ 0 <= imm <= 7 -#define ADD_IMM3(dst, src, imm) (0x1c00 + (dst) + ((src) << 3) + ((imm) << 6) ) -// add dst, #imm @ 0 <= imm <= 255 -#define ADD_IMM8(dst, imm) (0x3000 + ((dst) << 8) + (imm) ) -// add dst, src1, src2 -#define ADD_REG(dst, src1, src2) (0x1800 + (dst) + ((src1) << 3) + ((src2) << 6) ) -// add dst, pc, #imm @ 0 <= imm < 1024 & imm mod 4 = 0 -#define ADD_LO_PC_IMM(dst, imm) (0xa000 + ((dst) << 8) + ((imm) >> 2) ) -// sub dst, src1, src2 -#define SUB_REG(dst, src1, src2) (0x1a00 + (dst) + ((src1) << 3) + ((src2) << 6) ) -// sub dst, src, #imm @ 0 <= imm <= 7 -#define SUB_IMM3(dst, src, imm) (0x1e00 + (dst) + ((src) << 3) + ((imm) << 6) ) -// sub dst, #imm @ 0 <= imm <= 255 -#define SUB_IMM8(dst, imm) (0x3800 + ((dst) << 8) + (imm) ) -// neg dst, src -#define NEG(dst, src) (0x4240 + (dst) + ((src) << 3) ) -// cmp dst, #imm @ 0 <= imm <= 255 -#define CMP_IMM(dst, imm) (0x2800 + ((dst) << 8) + (imm) ) -// nop -#define NOP (0x46c0) - -// logical -// and dst, src -#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) ) -// bic dst, src -#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) ) -// eor dst, src -#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) ) -// orr dst, src -#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) ) -// mvn dst, src -#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) ) - -// shift/rotate -// lsl dst, src, #imm -#define LSL_IMM(dst, src, imm) (0x0000 + (dst) + ((src) << 3) + ((imm) << 6) ) -// lsl dst, reg -#define LSL_REG(dst, reg) (0x4080 + (dst) + ((reg) << 3) ) -// lsr dst, src, #imm -#define LSR_IMM(dst, src, imm) (0x0800 + (dst) + ((src) << 3) + ((imm) << 6) ) -// lsr dst, reg -#define LSR_REG(dst, reg) (0x40c0 + (dst) + ((reg) << 3) ) -// asr dst, src, #imm -#define ASR_IMM(dst, src, imm) (0x1000 + (dst) + ((src) << 3) + ((imm) << 6) ) -// asr dst, reg -#define ASR_REG(dst, reg) (0x4100 + (dst) + ((reg) << 3) ) -// ror dst, reg -#define ROR_REG(dst, reg) (0x41c0 + (dst) + ((reg) << 3) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0 -#define LDR_IMM(reg, addr, imm) (0x6800 + (reg) + ((addr) << 3) + ((imm) << 4) ) -// ldrh reg, [addr, #imm] @ 0 <= imm < 64 & imm mod 2 = 0 -#define LDRH_IMM(reg, addr, imm) (0x8800 + (reg) + ((addr) << 3) + ((imm) << 5) ) -// ldrb reg, [addr, #imm] @ 0 <= imm < 32 -#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) ) -// ldr reg, [pc, #imm] @ 0 <= imm < 1024 & imm mod 4 = 0 -#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) ) -// ldr reg, [addr1, addr2] -#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) ) - -// store -// str reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0 -#define STR_IMM(reg, addr, imm) (0x6000 + (reg) + ((addr) << 3) + ((imm) << 4) ) -// strh reg, [addr, #imm] @ 0 <= imm < 64 & imm mod 2 = 0 -#define STRH_IMM(reg, addr, imm) (0x8000 + (reg) + ((addr) << 3) + ((imm) << 5) ) -// strb reg, [addr, #imm] @ 0 <= imm < 32 -#define STRB_IMM(reg, addr, imm) (0x7000 + (reg) + ((addr) << 3) + ((imm) << 6) ) - -// branch -// beq pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BEQ_FWD(imm) (0xd000 + ((imm) >> 1) ) -// bne pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BNE_FWD(imm) (0xd100 + ((imm) >> 1) ) -// bgt pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BGT_FWD(imm) (0xdc00 + ((imm) >> 1) ) -// b pc+imm @ 0 <= imm < 2048 & imm mod 2 = 0 -#define B_FWD(imm) (0xe000 + ((imm) >> 1) ) -// bx reg -#define BX(reg) (0x4700 + ((reg) << 3) ) - - -// arm instructions - -// arithmetic -// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 4096 -#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// store -// str reg, [addr, #-(imm)]! @ 0 <= imm < 4096 -#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// branch -// bx reg -#define ARM_BX(reg) (0xe12fff10 + (reg) ) - - -// data pool defines -#define CACHE_DATA_JUMP (2) -#define CACHE_DATA_ALIGN (32) -#define CACHE_DATA_MIN (32) -#define CACHE_DATA_MAX (288) - -// data pool variables -static Bit8u * cache_datapos = NULL; // position of data pool in the cache block -static Bit32u cache_datasize = 0; // total size of data pool -static Bit32u cache_dataindex = 0; // used size of data pool = index of free data item (in bytes) in data pool - - -// forwarded function -static void INLINE gen_create_branch_short(void * func); - -// function to check distance to data pool -// if too close, then generate jump after data pool -static void cache_checkinstr(Bit32u size) { - if (cache_datasize == 0) { - if (cache_datapos != NULL) { - if (cache.pos + size + CACHE_DATA_JUMP >= cache_datapos) { - cache_datapos = NULL; - } - } - return; - } - - if (cache.pos + size + CACHE_DATA_JUMP <= cache_datapos) return; - - { - register Bit8u * newcachepos; - - newcachepos = cache_datapos + cache_datasize; - gen_create_branch_short(newcachepos); - cache.pos = newcachepos; - } - - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - cache_datasize = 0; - cache_dataindex = 0; -} - -// function to reserve item in data pool -// returns address of item -static Bit8u * cache_reservedata(void) { - // if data pool not yet initialized, then initialize data pool - if (GCC_UNLIKELY(cache_datapos == NULL)) { - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN < cache.block.active->cache.start + CACHE_DATA_MAX) { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - // if data pool not yet used, then set data pool - if (cache_datasize == 0) { - // set data pool address is too close (or behind) cache.pos then set new data pool size - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_JUMP /*+ CACHE_DATA_ALIGN*/ > cache_datapos) { - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - } - // set initial data pool size - cache_datasize = CACHE_DATA_ALIGN; - } - - // if data pool is full, then enlarge data pool - if (cache_dataindex == cache_datasize) { - cache_datasize += CACHE_DATA_ALIGN; - } - - cache_dataindex += 4; - return (cache_datapos + (cache_dataindex - 4)); -} - -static void cache_block_before_close(void) { - // if data pool in use, then resize cache block to include the data pool - if (cache_datasize != 0) - { - cache.pos = cache_datapos + cache_dataindex; - } - - // clear the values before next use - cache_datapos = NULL; - cache_datasize = 0; - cache_dataindex = 0; -} - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_checkinstr(2); - cache_addw( MOV_REG(reg_dst, reg_src) ); // mov reg_dst, reg_src -} - -// helper function -static bool val_single_shift(Bit32u value, Bit32u *val_shift) { - Bit32u shift; - - if (GCC_UNLIKELY(value == 0)) { - *val_shift = 0; - return true; - } - - shift = 0; - while ((value & 1) == 0) { - value>>=1; - shift+=1; - } - - if ((value >> 8) != 0) return false; - - *val_shift = shift; - return true; -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - Bit32u scale; - - if (imm < 256) { - cache_checkinstr(2); - cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm) - } else if ((~imm) < 256) { - cache_checkinstr(4); - cache_addw( MOV_IMM(dest_reg, ~imm) ); // mov dest_reg, #(~imm) - cache_addw( MVN(dest_reg, dest_reg) ); // mvn dest_reg, dest_reg - } else if (val_single_shift(imm, &scale)) { - cache_checkinstr(4); - cache_addw( MOV_IMM(dest_reg, imm >> scale) ); // mov dest_reg, #(imm >> scale) - cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #scale - } else { - Bit32u diff; - - cache_checkinstr(4); - - diff = imm - ((Bit32u)cache.pos+4); - - if ((diff < 1024) && ((imm & 0x03) == 0)) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( ADD_LO_PC_IMM(dest_reg, diff >> 2) ); // add dest_reg, pc, #(diff >> 2) - } else { - cache_addw( NOP ); // nop - cache_addw( ADD_LO_PC_IMM(dest_reg, (diff - 2) >> 2) ); // add dest_reg, pc, #((diff - 2) >> 2) - } - } else { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=imm; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 4)) ); // ldr dest_reg, [pc, datapos] - } else { - cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 2)) ); // ldr dest_reg, [pc, datapos] - } - } - } -} - -// helper function -static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) ); // ldr dest_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 2: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) ); // ldrh dest_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 32)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) ); // ldrb dest_reg, [templo2, #(data - addr_data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) { - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_checkinstr(8); - cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - cache_addw( LDRH_IMM(templo1, data_reg, 2) ); // ldrh templo1, [data_reg, #2] - cache_addw( LSL_IMM(templo1, templo1, 16) ); // lsl templo1, templo1, #16 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } else { - cache_checkinstr(16); - cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addw( ADD_IMM3(templo1, data_reg, 1) ); // add templo1, data_reg, #1 - cache_addw( LDRH_IMM(templo1, templo1, 0) ); // ldrh templo1, [templo1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - cache_addw( LDRB_IMM(templo1, data_reg, 3) ); // ldrb templo1, [data_reg, #3] - cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } - } else -#endif - { - cache_checkinstr(2); - cache_addw( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg] - } - } else { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)data & 1) { - cache_checkinstr(8); - cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addw( LDRB_IMM(templo1, data_reg, 1) ); // ldrb templo1, [data_reg, #1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } else -#endif - { - cache_checkinstr(2); - cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2); - } -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function -static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STR_IMM(src_reg, templo2, data - addr_data) ); // str src_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 2: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) ); // strh src_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 32)) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) ); // strb src_reg, [templo2, #(data - addr_data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) { - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_checkinstr(8); - cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 16) ); // lsr templo1, templo1, #16 - cache_addw( STRH_IMM(templo1, data_reg, 2) ); // strh templo1, [data_reg, #2] - } else { - cache_checkinstr(20); - cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8 - cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 16) ); // lsr templo1, templo1, #16 - cache_addw( STRB_IMM(templo1, data_reg, 2) ); // strb templo1, [data_reg, #2] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 24) ); // lsr templo1, templo1, #24 - cache_addw( STRB_IMM(templo1, data_reg, 3) ); // strb templo1, [data_reg, #3] - } - } else -#endif - { - cache_checkinstr(2); - cache_addw( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg] - } - } else { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)dest & 1) { - cache_checkinstr(8); - cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8 - cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1] - } else -#endif - { - cache_checkinstr(2); - cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2); - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - if (!gen_mov_memval_to_reg(dest_reg, data, 1)) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)data); - cache_checkinstr(2); - cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1] - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_checkinstr(2); - cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - if (!gen_mov_memval_from_reg(src_reg, dest, 1)) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest); - cache_checkinstr(2); - cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1] - } -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw( LSL_IMM(reg, reg, 24) ); // lsl reg, reg, #24 - - if (sign) { - cache_addw( ASR_IMM(reg, reg, 24) ); // asr reg, reg, #24 - } else { - cache_addw( LSR_IMM(reg, reg, 24) ); // lsr reg, reg, #24 - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw( LSL_IMM(reg, reg, 16) ); // lsl reg, reg, #16 - - if (sign) { - cache_addw( ASR_IMM(reg, reg, 16) ); // asr reg, reg, #16 - } else { - cache_addw( LSR_IMM(reg, reg, 16) ); // lsr reg, reg, #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(templo3, op, 1); - cache_checkinstr(2); - cache_addw( ADD_REG(reg, reg, templo3) ); // add reg, reg, templo3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - if(!imm) return; - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if (imm <= 255) { - cache_checkinstr(2); - cache_addw( ADD_IMM8(reg, imm) ); // add reg, #imm - } else if (imm2 <= 255) { - cache_checkinstr(2); - cache_addw( SUB_IMM8(reg, imm2) ); // sub reg, #(-imm) - } else { - if (val_single_shift(imm2, &scale)) { - cache_checkinstr((scale)?6:4); - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( SUB_REG(reg, reg, templo1) ); // sub reg, reg, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1 - } - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - imm2 = ~imm; - if(!imm2) return; - - if (!imm) { - cache_checkinstr(2); - cache_addw( MOV_IMM(reg, 0) ); // mov reg, #0 - } else { - if (val_single_shift(imm2, &scale)) { - cache_checkinstr((scale)?6:4); - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( BIC(reg, templo1) ); // bic reg, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw( AND(reg, templo1) ); // and reg, templo1 - } - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(templo3, imm); - gen_mov_word_from_reg(templo3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templo3, dest, dword, templo2); - } - gen_add_imm(templo3, imm); - if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(templo3, dest, dword, templo2); - } -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, (Bit32s)imm, 1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - Bit32u imm2, scale; - - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templo3, dest, dword, templo2); - } - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if (imm <= 255) { - cache_checkinstr(2); - cache_addw( SUB_IMM8(templo3, imm) ); // sub templo3, #imm - } else if (imm2 <= 255) { - cache_checkinstr(2); - cache_addw( ADD_IMM8(templo3, imm2) ); // add templo3, #(-imm) - } else { - if (val_single_shift(imm2, &scale)) { - cache_checkinstr((scale)?6:4); - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1 - } - } - - if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(templo3, dest, dword, templo2); - } -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - gen_sub_direct_word(dest, (Bit32s)imm, 1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(4); - cache_addw( LSL_IMM(templo1, scale_reg, scale) ); // lsl templo1, scale_reg, #(scale) - cache_addw( ADD_REG(dest_reg, dest_reg, templo1) ); // add dest_reg, dest_reg, templo1 - } else { - cache_checkinstr(2); - cache_addw( ADD_REG(dest_reg, dest_reg, scale_reg) ); // add dest_reg, dest_reg, scale_reg - } - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(2); - cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// helper function for gen_call_function_raw and gen_call_function_setup -static void gen_call_function_helper(void * func) { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=(Bit32u)func; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) ); // ldr templo1, [pc, datapos] - cache_addw( ADD_LO_PC_IMM(templo2, 4) ); // adr templo2, after_call (add templo2, pc, #4) - cache_addw( MOV_HI_LO(HOST_lr, templo2) ); // mov lr, templo2 - cache_addw( BX(templo1) ); // bx templo1 --- switch to arm state - } else { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) ); // ldr templo1, [pc, datapos] - cache_addw( ADD_LO_PC_IMM(templo2, 4) ); // adr templo2, after_call (add templo2, pc, #4) - cache_addw( MOV_HI_LO(HOST_lr, templo2) ); // mov lr, templo2 - cache_addw( BX(templo1) ); // bx templo1 --- switch to arm state - cache_addw( NOP ); // nop - } - // after_call: - - // switch from arm to thumb state - cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1)); // add templo1, pc, #1 - cache_addd(0xe12fff10 + (templo1)); // bx templo1 - - // thumb state from now on -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_checkinstr(18); - gen_call_function_helper(func); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - cache_checkinstr(18); - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_helper(func); - return proc_addr; - // if proc_addr is on word boundary ((proc_addr & 0x03) == 0) - // then length of generated code is 16 bytes - // otherwise length of generated code is 18 bytes -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(templo3, ptr, 1); - -#if !defined(C_UNALIGNED_MEMORY) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { -#endif - if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) { - cache_checkinstr(6); - cache_addw( LDR_IMM(templo2, templo3, imm) ); // ldr templo2, [templo3, #imm] - } else { - gen_mov_dword_to_reg_imm(templo2, imm); - cache_checkinstr(6); - cache_addw( LDR_REG(templo2, templo3, templo2) ); // ldr templo2, [templo3, templo2] - } -#if !defined(C_UNALIGNED_MEMORY) - } else { - gen_add_imm(templo3, imm); - - cache_checkinstr(24); - cache_addw( LDRB_IMM(templo2, templo3, 0) ); // ldrb templo2, [templo3] - cache_addw( LDRB_IMM(templo1, templo3, 1) ); // ldrb templo1, [templo3, #1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - cache_addw( LDRB_IMM(templo1, templo3, 2) ); // ldrb templo1, [templo3, #2] - cache_addw( LSL_IMM(templo1, templo1, 16) ); // lsl templo1, templo1, #16 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - cache_addw( LDRB_IMM(templo1, templo3, 3) ); // ldrb templo1, [templo3, #3] - cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - } -#endif - - // increase jmp address to keep thumb state - cache_addw( ADD_IMM3(templo2, templo2, 1) ); // add templo2, templo2, #1 - - cache_addw( BX(templo2) ); // bx templo2 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo1, reg, 16) ); // lsl templo1, reg, #16 - } - cache_addw( BEQ_FWD(0) ); // beq j - return ((Bit32u)cache.pos-2); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo1, reg, 16) ); // lsl templo1, reg, #16 - } - cache_addw( BNE_FWD(0) ); // bne j - return ((Bit32u)cache.pos-2); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+4); - if (len<0) len=-len; - if (len>252) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 ); -} - - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - if (isdword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo2, reg, 24) ); // lsl templo2, reg, #24 - } - cache_addw( BEQ_FWD(2) ); // beq nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) ); // ldr templo1, [pc, datapos] - } else { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) ); // ldr templo1, [pc, datapos] - } - cache_addw( BX(templo1) ); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - cache_addw( BGT_FWD(2) ); // bgt nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) ); // ldr templo1, [pc, datapos] - } else { - cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) ); // ldr templo1, [pc, datapos] - } - cache_addw( BX(templo1) ); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state -} - -static void gen_run_code(void) { - Bit8u *pos1, *pos2, *pos3; - -#if (__ARM_EABI__) - // 8-byte stack alignment - cache_addd(0xe92d4ff0); // stmfd sp!, {v1-v8,lr} -#else - cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr} -#endif - - cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) ); // add r0, r0, #1 - - pos1 = cache.pos; - cache_addd( 0 ); - pos2 = cache.pos; - cache_addd( 0 ); - pos3 = cache.pos; - cache_addd( 0 ); - - cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4 - cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) ); // str lr, [sp, #-4]! - cache_addd( ARM_BX(HOST_r0) ); // bx r0 - -#if (__ARM_EABI__) - cache_addd(0xe8bd4ff0); // ldmfd sp!, {v1-v8,lr} -#else - cache_addd(0xe8bd4df0); // ldmfd sp!, {v1-v5,v7,v8,lr} -#endif - cache_addd( ARM_BX(HOST_lr) ); // bx lr - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } - - *(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - cache_addd((Bit32u)&Segs); // address of "Segs" - - *(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" - - *(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)] - cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata" - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } -} - -// return from a function -static void gen_return_function(void) { - cache_checkinstr(4); - cache_addw(0xbc08); // pop {r3} - cache_addw( BX(HOST_r3) ); // bx r3 -} - - -// short unconditional jump (over data pool) -// must emit at most CACHE_DATA_JUMP bytes -static void INLINE gen_create_branch_short(void * func) { - cache_addw( B_FWD((Bit32u)func - ((Bit32u)cache.pos + 4)) ); // b func -} - - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { - if ((*(Bit16u*)pos & 0xf000) == 0xe000) { - if ((*(Bit16u*)pos & 0x0fff) >= ((CACHE_DATA_ALIGN / 2) - 1) && - (*(Bit16u*)pos & 0x0fff) < 0x0800) - { - pos = (Bit8u *) ( ( ( (Bit32u)(*(Bit16u*)pos & 0x0fff) ) << 1 ) + ((Bit32u)pos + 4) ); - } - } - -#ifdef DRC_FLAGS_INVALIDATION_DCODE - if (((Bit32u)pos & 0x03) == 0) - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2); // add a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=ORR(HOST_a1, HOST_a2); // orr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=AND(HOST_a1, HOST_a2); // and a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2); // sub a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=EOR(HOST_a1, HOST_a2); // eor a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=B_FWD(12); // b after_call (pc+12) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1); // add a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1); // sub a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2); // lsl a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_SHRb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24); // lsr a1, a1, #24 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(6); // b after_call (pc+6) - break; - case t_SHRw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16); // lsr a1, a1, #16 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(6); // b after_call (pc+6) - break; - case t_SHRd: - *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_SARb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24); // asr a1, a1, #24 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(6); // b after_call (pc+6) - break; - case t_SARw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16); // asr a1, a1, #16 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(6); // b after_call (pc+6) - break; - case t_SARd: - *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_RORb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+10)=NOP; // nop - *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+14)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_RORw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+8)=B_FWD(4); // b after_call (pc+4) - break; - case t_RORd: - *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - case t_ROLb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+14)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_ROLw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=NOP; // nop - *(Bit16u*)(pos+12)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+14)=NOP; // nop - break; - case t_ROLd: - *(Bit16u*)pos=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+6)=B_FWD(6); // b after_call (pc+6) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=NEG(HOST_a1, HOST_a1); // neg a1, a1 - *(Bit16u*)(pos+2)=B_FWD(10); // b after_call (pc+10) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - break; - } - } - else - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2); // add a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=ORR(HOST_a1, HOST_a2); // orr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=AND(HOST_a1, HOST_a2); // and a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2); // sub a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=EOR(HOST_a1, HOST_a2); // eor a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=B_FWD(14); // b after_call (pc+14) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1); // add a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1); // sub a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2); // lsl a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_SHRb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24); // lsr a1, a1, #24 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(8); // b after_call (pc+8) - break; - case t_SHRw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16); // lsr a1, a1, #16 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(8); // b after_call (pc+8) - break; - case t_SHRd: - *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_SARb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24); // asr a1, a1, #24 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(8); // b after_call (pc+8) - break; - case t_SARw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16); // asr a1, a1, #16 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(8); // b after_call (pc+8) - break; - case t_SARd: - *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_RORb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=NOP; // nop - *(Bit16u*)(pos+8)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+10)=NOP; // nop - *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+14)=NOP; // nop - *(Bit16u*)(pos+16)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_RORw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+8)=B_FWD(6); // b after_call (pc+6) - break; - case t_RORd: - *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - case t_ROLb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+14)=NOP; // nop - *(Bit16u*)(pos+16)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_ROLw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=NOP; // nop - *(Bit16u*)(pos+12)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+14)=NOP; // nop - *(Bit16u*)(pos+16)=NOP; // nop - break; - case t_ROLd: - *(Bit16u*)pos=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+6)=B_FWD(8); // b after_call (pc+8) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=NEG(HOST_a1, HOST_a1); // neg a1, a1 - *(Bit16u*)(pos+2)=B_FWD(12); // b after_call (pc+12) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - break; - } - - } -#else - if (((Bit32u)pos & 0x03) == 0) - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - } - else - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - } -#endif -} -#endif - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDRH_IMM(dest_reg, templo1, index) ); // ldrh dest_reg, [templo1, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDR_IMM(dest_reg, templo1, index) ); // ldr dest_reg, [templo1, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDR_IMM(templo2, templo1, index) ); // ldr templo2, [templo1, #index] - cache_addw( ADD_REG(reg, reg, templo2) ); // add reg, reg, templo2 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRH_IMM(dest_reg, templo2, index) ); // ldrh dest_reg, [templo2, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDR_IMM(dest_reg, templo2, index) ); // ldr dest_reg, [templo2, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - if (dword) { - cache_addw( LDR_IMM(dest_reg, templo2, index) ); // ldr dest_reg, [templo2, #index] - } else { - cache_addw( LDRH_IMM(dest_reg, templo2, index) ); // ldrh dest_reg, [templo2, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRB_IMM(dest_reg, templo2, index) ); // ldrb dest_reg, [templo2, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRB_IMM(dest_reg, templo2, index) ); // ldrb dest_reg, [templo2, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDR_IMM(templo1, templo2, index) ); // ldr templo1, [templo2, #index] - cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STRH_IMM(src_reg, templo1, index) ); // strh src_reg, [templo1, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STR_IMM(src_reg, templo1, index) ); // str src_reg, [templo1, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - if (dword) { - cache_addw( STR_IMM(src_reg, templo1, index) ); // str src_reg, [templo1, #index] - } else { - cache_addw( STRH_IMM(src_reg, templo1, index) ); // strh src_reg, [templo1, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STRB_IMM(src_reg, templo1, index) ); // strb src_reg, [templo1, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-thumb.h b/src/cpu/core_dynrec/risc_armv4le-thumb.h deleted file mode 100644 index 829cb554b..000000000 --- a/src/cpu/core_dynrec/risc_armv4le-thumb.h +++ /dev/null @@ -1,1335 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4 (little endian) backend by M-HT (thumb version) */ - - -// temporary "lo" registers -#define templo1 HOST_v3 -#define templo2 HOST_v4 -#define templo3 HOST_v2 - -// register that holds function return values -#define FC_RETOP HOST_a1 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_a4 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_a4 - -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 - -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 - -// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code -#define readdata_addr HOST_v5 - - -// instruction encodings - -// move -// mov dst, #imm @ 0 <= imm <= 255 -#define MOV_IMM(dst, imm) (0x2000 + ((dst) << 8) + (imm) ) -// mov dst, src -#define MOV_REG(dst, src) ADD_IMM3(dst, src, 0) -// mov dst, src -#define MOV_LO_HI(dst, src) (0x4640 + (dst) + (((src) - HOST_r8) << 3) ) -// mov dst, src -#define MOV_HI_LO(dst, src) (0x4680 + ((dst) - HOST_r8) + ((src) << 3) ) - -// arithmetic -// add dst, src, #imm @ 0 <= imm <= 7 -#define ADD_IMM3(dst, src, imm) (0x1c00 + (dst) + ((src) << 3) + ((imm) << 6) ) -// add dst, #imm @ 0 <= imm <= 255 -#define ADD_IMM8(dst, imm) (0x3000 + ((dst) << 8) + (imm) ) -// add dst, src1, src2 -#define ADD_REG(dst, src1, src2) (0x1800 + (dst) + ((src1) << 3) + ((src2) << 6) ) -// add dst, pc, #imm @ 0 <= imm < 1024 & imm mod 4 = 0 -#define ADD_LO_PC_IMM(dst, imm) (0xa000 + ((dst) << 8) + ((imm) >> 2) ) -// sub dst, src1, src2 -#define SUB_REG(dst, src1, src2) (0x1a00 + (dst) + ((src1) << 3) + ((src2) << 6) ) -// sub dst, src, #imm @ 0 <= imm <= 7 -#define SUB_IMM3(dst, src, imm) (0x1e00 + (dst) + ((src) << 3) + ((imm) << 6) ) -// sub dst, #imm @ 0 <= imm <= 255 -#define SUB_IMM8(dst, imm) (0x3800 + ((dst) << 8) + (imm) ) -// neg dst, src -#define NEG(dst, src) (0x4240 + (dst) + ((src) << 3) ) -// cmp dst, #imm @ 0 <= imm <= 255 -#define CMP_IMM(dst, imm) (0x2800 + ((dst) << 8) + (imm) ) -// nop -#define NOP (0x46c0) - -// logical -// and dst, src -#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) ) -// bic dst, src -#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) ) -// eor dst, src -#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) ) -// orr dst, src -#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) ) -// mvn dst, src -#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) ) - -// shift/rotate -// lsl dst, src, #imm -#define LSL_IMM(dst, src, imm) (0x0000 + (dst) + ((src) << 3) + ((imm) << 6) ) -// lsl dst, reg -#define LSL_REG(dst, reg) (0x4080 + (dst) + ((reg) << 3) ) -// lsr dst, src, #imm -#define LSR_IMM(dst, src, imm) (0x0800 + (dst) + ((src) << 3) + ((imm) << 6) ) -// lsr dst, reg -#define LSR_REG(dst, reg) (0x40c0 + (dst) + ((reg) << 3) ) -// asr dst, src, #imm -#define ASR_IMM(dst, src, imm) (0x1000 + (dst) + ((src) << 3) + ((imm) << 6) ) -// asr dst, reg -#define ASR_REG(dst, reg) (0x4100 + (dst) + ((reg) << 3) ) -// ror dst, reg -#define ROR_REG(dst, reg) (0x41c0 + (dst) + ((reg) << 3) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0 -#define LDR_IMM(reg, addr, imm) (0x6800 + (reg) + ((addr) << 3) + ((imm) << 4) ) -// ldrh reg, [addr, #imm] @ 0 <= imm < 64 & imm mod 2 = 0 -#define LDRH_IMM(reg, addr, imm) (0x8800 + (reg) + ((addr) << 3) + ((imm) << 5) ) -// ldrb reg, [addr, #imm] @ 0 <= imm < 32 -#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) ) -// ldr reg, [pc, #imm] @ 0 <= imm < 1024 & imm mod 4 = 0 -#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) ) -// ldr reg, [addr1, addr2] -#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) ) - -// store -// str reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0 -#define STR_IMM(reg, addr, imm) (0x6000 + (reg) + ((addr) << 3) + ((imm) << 4) ) -// strh reg, [addr, #imm] @ 0 <= imm < 64 & imm mod 2 = 0 -#define STRH_IMM(reg, addr, imm) (0x8000 + (reg) + ((addr) << 3) + ((imm) << 5) ) -// strb reg, [addr, #imm] @ 0 <= imm < 32 -#define STRB_IMM(reg, addr, imm) (0x7000 + (reg) + ((addr) << 3) + ((imm) << 6) ) - -// branch -// beq pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BEQ_FWD(imm) (0xd000 + ((imm) >> 1) ) -// bne pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BNE_FWD(imm) (0xd100 + ((imm) >> 1) ) -// bgt pc+imm @ 0 <= imm < 256 & imm mod 2 = 0 -#define BGT_FWD(imm) (0xdc00 + ((imm) >> 1) ) -// b pc+imm @ 0 <= imm < 2048 & imm mod 2 = 0 -#define B_FWD(imm) (0xe000 + ((imm) >> 1) ) -// bx reg -#define BX(reg) (0x4700 + ((reg) << 3) ) - - -// arm instructions - -// arithmetic -// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0 -#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) ) - -// load -// ldr reg, [addr, #imm] @ 0 <= imm < 4096 -#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// store -// str reg, [addr, #-(imm)]! @ 0 <= imm < 4096 -#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) ) - -// branch -// bx reg -#define ARM_BX(reg) (0xe12fff10 + (reg) ) - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addw( MOV_REG(reg_dst, reg_src) ); // mov reg_dst, reg_src -} - -// helper function -static bool val_single_shift(Bit32u value, Bit32u *val_shift) { - Bit32u shift; - - if (GCC_UNLIKELY(value == 0)) { - *val_shift = 0; - return true; - } - - shift = 0; - while ((value & 1) == 0) { - value>>=1; - shift+=1; - } - - if ((value >> 8) != 0) return false; - - *val_shift = shift; - return true; -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - Bit32u scale; - - if (imm < 256) { - cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #imm - } else if ((~imm) < 256) { - cache_addw( MOV_IMM(dest_reg, ~imm) ); // mov dest_reg, #(~imm) - cache_addw( MVN(dest_reg, dest_reg) ); // mvn dest_reg, dest_reg - } else if (val_single_shift(imm, &scale)) { - cache_addw( MOV_IMM(dest_reg, imm >> scale) ); // mov dest_reg, #(imm >> scale) - cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #scale - } else { - Bit32u diff; - - diff = imm - ((Bit32u)cache.pos+4); - - if ((diff < 1024) && ((imm & 0x03) == 0)) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( ADD_LO_PC_IMM(dest_reg, diff) ); // add dest_reg, pc, #(diff >> 2) - } else { - cache_addw( NOP ); // nop - cache_addw( ADD_LO_PC_IMM(dest_reg, diff - 2) ); // add dest_reg, pc, #((diff - 2) >> 2) - } - } else { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(dest_reg, 0) ); // ldr dest_reg, [pc, #0] - cache_addw( B_FWD(2) ); // b next_code (pc+2) - cache_addd(imm); // .int imm - // next_code: - } else { - cache_addw( LDR_PC_IMM(dest_reg, 4) ); // ldr dest_reg, [pc, #4] - cache_addw( B_FWD(4) ); // b next_code (pc+4) - cache_addw( NOP ); // nop - cache_addd(imm); // .int imm - // next_code: - } - } - } -} - -// helper function -static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) { - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) ); // ldr dest_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 2: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) { - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) ); // ldrh dest_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 32)) { - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) ); // ldrb dest_reg, [templo2, #(data - addr_data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) { - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - cache_addw( LDRH_IMM(templo1, data_reg, 2) ); // ldrh templo1, [data_reg, #2] - cache_addw( LSL_IMM(templo1, templo1, 16) ); // lsl templo1, templo1, #16 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } else { - cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addw( ADD_IMM3(templo1, data_reg, 1) ); // add templo1, data_reg, #1 - cache_addw( LDRH_IMM(templo1, templo1, 0) ); // ldrh templo1, [templo1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - cache_addw( LDRB_IMM(templo1, data_reg, 3) ); // ldrb templo1, [data_reg, #3] - cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } - } else -#endif - { - cache_addw( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg] - } - } else { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)data & 1) { - cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg] - cache_addw( LDRB_IMM(templo1, data_reg, 1) ); // ldrb templo1, [data_reg, #1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1 - } else -#endif - { - cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2); - } -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function -static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) { - switch (size) { - case 4: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 3) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) { - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STR_IMM(src_reg, templo2, data - addr_data) ); // str src_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 2: -#if !defined(C_UNALIGNED_MEMORY) - if ((data & 1) == 0) -#endif - { - if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) { - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) ); // strh src_reg, [templo2, #(data - addr_data)] - return true; - } - } - break; - case 1: - if ((data >= addr_data) && (data < addr_data + 32)) { - cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg - cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) ); // strb src_reg, [templo2, #(data - addr_data)] - return true; - } - default: - break; - } - return false; -} - -// helper function -static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) { - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true; - if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true; - return false; -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 16) ); // lsr templo1, templo1, #16 - cache_addw( STRH_IMM(templo1, data_reg, 2) ); // strh templo1, [data_reg, #2] - } else { - cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8 - cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 16) ); // lsr templo1, templo1, #16 - cache_addw( STRB_IMM(templo1, data_reg, 2) ); // strb templo1, [data_reg, #2] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 24) ); // lsr templo1, templo1, #24 - cache_addw( STRB_IMM(templo1, data_reg, 3) ); // strb templo1, [data_reg, #3] - } - } else -#endif - { - cache_addw( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg] - } - } else { -#if !defined(C_UNALIGNED_MEMORY) - if ((Bit32u)dest & 1) { - cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg] - cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg - cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8 - cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1] - } else -#endif - { - cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2); - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - if (!gen_mov_memval_to_reg(dest_reg, data, 1)) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)data); - cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1] - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - if (!gen_mov_memval_from_reg(src_reg, dest, 1)) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest); - cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1] - } -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_addw( LSL_IMM(reg, reg, 24) ); // lsl reg, reg, #24 - - if (sign) { - cache_addw( ASR_IMM(reg, reg, 24) ); // asr reg, reg, #24 - } else { - cache_addw( LSR_IMM(reg, reg, 24) ); // lsr reg, reg, #24 - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_addw( LSL_IMM(reg, reg, 16) ); // lsl reg, reg, #16 - - if (sign) { - cache_addw( ASR_IMM(reg, reg, 16) ); // asr reg, reg, #16 - } else { - cache_addw( LSR_IMM(reg, reg, 16) ); // lsr reg, reg, #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(templo3, op, 1); - cache_addw( ADD_REG(reg, reg, templo3) ); // add reg, reg, templo3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - if(!imm) return; - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if (imm <= 255) { - cache_addw( ADD_IMM8(reg, imm) ); // add reg, #imm - } else if (imm2 <= 255) { - cache_addw( SUB_IMM8(reg, imm2) ); // sub reg, #(-imm) - } else { - if (val_single_shift(imm2, &scale)) { - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( SUB_REG(reg, reg, templo1) ); // sub reg, reg, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1 - } - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bit32u imm2, scale; - - imm2 = ~imm; - if(!imm2) return; - - if (!imm) { - cache_addw( MOV_IMM(reg, 0) ); // mov reg, #0 - } else { - if (val_single_shift(imm2, &scale)) { - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( BIC(reg, templo1) ); // bic reg, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_addw( AND(reg, templo1) ); // and reg, templo1 - } - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(templo3, imm); - gen_mov_word_from_reg(templo3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templo3, dest, dword, templo2); - } - gen_add_imm(templo3, imm); - if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(templo3, dest, dword, templo2); - } -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, (Bit32s)imm, 1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - Bit32u imm2, scale; - - if (!dword) imm &= 0xffff; - if(!imm) return; - - if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templo3, dest, dword, templo2); - } - - imm2 = (Bit32u) (-((Bit32s)imm)); - - if (imm <= 255) { - cache_addw( SUB_IMM8(templo3, imm) ); // sub templo3, #imm - } else if (imm2 <= 255) { - cache_addw( ADD_IMM8(templo3, imm2) ); // add templo3, #(-imm) - } else { - if (val_single_shift(imm2, &scale)) { - cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale) - if (scale) { - cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale - } - cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1 - } else { - gen_mov_dword_to_reg_imm(templo1, imm); - cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1 - } - } - - if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) { - gen_mov_word_from_reg_helper(templo3, dest, dword, templo2); - } -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - gen_sub_direct_word(dest, (Bit32s)imm, 1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw( LSL_IMM(templo1, scale_reg, scale) ); // lsl templo1, scale_reg, #(scale) - cache_addw( ADD_REG(dest_reg, dest_reg, templo1) ); // add dest_reg, dest_reg, templo1 - } else { - cache_addw( ADD_REG(dest_reg, dest_reg, scale_reg) ); // add dest_reg, dest_reg, scale_reg - } - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( LDR_PC_IMM(templo1, 4) ); // ldr templo1, [pc, #4] - cache_addw( ADD_LO_PC_IMM(templo2, 8) ); // adr templo2, after_call (add templo2, pc, #8) - cache_addw( MOV_HI_LO(HOST_lr, templo2) ); // mov lr, templo2 - cache_addw( BX(templo1) ); // bx templo1 --- switch to arm state - } else { - cache_addw( LDR_PC_IMM(templo1, 8) ); // ldr templo1, [pc, #8] - cache_addw( ADD_LO_PC_IMM(templo2, 8) ); // adr templo2, after_call (add templo2, pc, #8) - cache_addw( MOV_HI_LO(HOST_lr, templo2) ); // mov lr, templo2 - cache_addw( BX(templo1) ); // bx templo1 --- switch to arm state - cache_addw( NOP ); // nop - } - cache_addd((Bit32u)func); // .int func - // after_call: - - // switch from arm to thumb state - cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1)); // add templo1, pc, #1 - cache_addd(0xe12fff10 + (templo1)); // bx templo1 - - // thumb state from now on -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; - // if proc_addr is on word boundary ((proc_addr & 0x03) == 0) - // then length of generated code is 20 bytes - // otherwise length of generated code is 22 bytes -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(templo3, ptr, 1); - -#if !defined(C_UNALIGNED_MEMORY) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { -#endif - if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) { - cache_addw( LDR_IMM(templo2, templo3, imm) ); // ldr templo2, [templo3, #imm] - } else { - gen_mov_dword_to_reg_imm(templo2, imm); - cache_addw( LDR_REG(templo2, templo3, templo2) ); // ldr templo2, [templo3, templo2] - } -#if !defined(C_UNALIGNED_MEMORY) - } else { - gen_add_imm(templo3, imm); - - cache_addw( LDRB_IMM(templo2, templo3, 0) ); // ldrb templo2, [templo3] - cache_addw( LDRB_IMM(templo1, templo3, 1) ); // ldrb templo1, [templo3, #1] - cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - cache_addw( LDRB_IMM(templo1, templo3, 2) ); // ldrb templo1, [templo3, #2] - cache_addw( LSL_IMM(templo1, templo1, 16) ); // lsl templo1, templo1, #16 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - cache_addw( LDRB_IMM(templo1, templo3, 3) ); // ldrb templo1, [templo3, #3] - cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24 - cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1 - } -#endif - - // increase jmp address to keep thumb state - cache_addw( ADD_IMM3(templo2, templo2, 1) ); // add templo2, templo2, #1 - - cache_addw( BX(templo2) ); // bx templo2 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (dword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo1, reg, 16) ); // lsl templo1, reg, #16 - } - cache_addw( BEQ_FWD(0) ); // beq j - return ((Bit32u)cache.pos-2); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (dword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo1, reg, 16) ); // lsl templo1, reg, #16 - } - cache_addw( BNE_FWD(0) ); // bne j - return ((Bit32u)cache.pos-2); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+4); - if (len<0) len=-len; - if (len>252) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 ); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - if (isdword) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - } else { - cache_addw( LSL_IMM(templo2, reg, 24) ); // lsl templo2, reg, #24 - } - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( BEQ_FWD(8) ); // beq nobranch (pc+8) - cache_addw( LDR_PC_IMM(templo1, 4) ); // ldr templo1, [pc, #4] - cache_addw( BX(templo1) ); // bx templo1 - cache_addw( NOP ); // nop - } else { - cache_addw( BEQ_FWD(6) ); // beq nobranch (pc+6) - cache_addw( LDR_PC_IMM(templo1, 0) ); // ldr templo1, [pc, #0] - cache_addw( BX(templo1) ); // bx templo1 - } - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addw( CMP_IMM(reg, 0) ); // cmp reg, #0 - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw( BGT_FWD(8) ); // bgt nobranch (pc+8) - cache_addw( LDR_PC_IMM(templo1, 4) ); // ldr templo1, [pc, #4] - cache_addw( BX(templo1) ); // bx templo1 - cache_addw( NOP ); // nop - } else { - cache_addw( BGT_FWD(6) ); // bgt nobranch (pc+6) - cache_addw( LDR_PC_IMM(templo1, 0) ); // ldr templo1, [pc, #0] - cache_addw( BX(templo1) ); // bx templo1 - } - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state -} - -static void gen_run_code(void) { - Bit8u *pos1, *pos2, *pos3; - -#if (__ARM_EABI__) - // 8-byte stack alignment - cache_addd(0xe92d4ff0); // stmfd sp!, {v1-v8,lr} -#else - cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr} -#endif - - cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) ); // add r0, r0, #1 - - pos1 = cache.pos; - cache_addd( 0 ); - pos2 = cache.pos; - cache_addd( 0 ); - pos3 = cache.pos; - cache_addd( 0 ); - - cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4 - cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) ); // str lr, [sp, #-4]! - cache_addd( ARM_BX(HOST_r0) ); // bx r0 - -#if (__ARM_EABI__) - cache_addd(0xe8bd4ff0); // ldmfd sp!, {v1-v8,lr} -#else - cache_addd(0xe8bd4df0); // ldmfd sp!, {v1-v5,v7,v8,lr} -#endif - cache_addd( ARM_BX(HOST_lr) ); // bx lr - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } - - *(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - cache_addd((Bit32u)&Segs); // address of "Segs" - - *(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" - - *(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)] - cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata" - - // align cache.pos to 32 bytes - if ((((Bitu)cache.pos) & 0x1f) != 0) { - cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f)); - } -} - -// return from a function -static void gen_return_function(void) { - cache_addw(0xbc08); // pop {r3} - cache_addw( BX(HOST_r3) ); // bx r3 -} - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - if (((Bit32u)pos & 0x03) == 0) - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2); // add a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=ORR(HOST_a1, HOST_a2); // orr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=AND(HOST_a1, HOST_a2); // and a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2); // sub a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=EOR(HOST_a1, HOST_a2); // eor a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=B_FWD(16); // b after_call (pc+16) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1); // add a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1); // sub a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2); // lsl a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_SHRb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24); // lsr a1, a1, #24 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(10); // b after_call (pc+10) - break; - case t_SHRw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16); // lsr a1, a1, #16 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(10); // b after_call (pc+10) - break; - case t_SHRd: - *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_SARb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24); // asr a1, a1, #24 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(10); // b after_call (pc+10) - break; - case t_SARw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16); // asr a1, a1, #16 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(10); // b after_call (pc+10) - break; - case t_SARd: - *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_RORb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+12)=B_FWD(4); // b after_call (pc+4) - break; - case t_RORw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+8)=B_FWD(8); // b after_call (pc+8) - break; - case t_RORd: - *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - case t_ROLb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=NOP; // nop - *(Bit16u*)(pos+12)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+14)=NOP; // nop - *(Bit16u*)(pos+16)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+18)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_ROLw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+12)=B_FWD(4); // b after_call (pc+4) - break; - case t_ROLd: - *(Bit16u*)pos=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+6)=B_FWD(10); // b after_call (pc+10) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=NEG(HOST_a1, HOST_a1); // neg a1, a1 - *(Bit16u*)(pos+2)=B_FWD(14); // b after_call (pc+14) - break; - default: - *(Bit32u*)(pos+8)=(Bit32u)fct_ptr; // simple_func - break; - } - } - else - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2); // add a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=ORR(HOST_a1, HOST_a2); // orr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=AND(HOST_a1, HOST_a2); // and a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2); // sub a1, a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=EOR(HOST_a1, HOST_a2); // eor a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=B_FWD(18); // b after_call (pc+18) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1); // add a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1); // sub a1, a1, #1 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2); // lsl a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_SHRb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24); // lsr a1, a1, #24 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(12); // b after_call (pc+12) - break; - case t_SHRw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16); // lsr a1, a1, #16 - *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(12); // b after_call (pc+12) - break; - case t_SHRd: - *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2); // lsr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_SARb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24); // asr a1, a1, #24 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(12); // b after_call (pc+12) - break; - case t_SARw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16); // asr a1, a1, #16 - *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+6)=B_FWD(12); // b after_call (pc+12) - break; - case t_SARd: - *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2); // asr a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_RORb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+12)=B_FWD(6); // b after_call (pc+6) - break; - case t_RORw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+8)=B_FWD(10); // b after_call (pc+10) - break; - case t_RORd: - *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - case t_ROLb: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8); // lsr templo1, a1, #8 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=NOP; // nop - *(Bit16u*)(pos+12)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+14)=NOP; // nop - *(Bit16u*)(pos+16)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+18)=NOP; // nop - *(Bit16u*)(pos+20)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - break; - case t_ROLw: - *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16); // lsr templo1, a1, #16 - *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1); // orr a1, templo1 - *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+12)=B_FWD(6); // b after_call (pc+6) - break; - case t_ROLd: - *(Bit16u*)pos=NEG(HOST_a2, HOST_a2); // neg a2, a2 - *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32); // add a2, #32 - *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2); // ror a1, a2 - *(Bit16u*)(pos+6)=B_FWD(12); // b after_call (pc+12) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=NEG(HOST_a1, HOST_a1); // neg a1, a1 - *(Bit16u*)(pos+2)=B_FWD(16); // b after_call (pc+16) - break; - default: - *(Bit32u*)(pos+10)=(Bit32u)fct_ptr; // simple_func - break; - } - - } -#else - if (((Bit32u)pos & 0x03) == 0) - { - *(Bit32u*)(pos+8)=(Bit32u)fct_ptr; // simple_func - } - else - { - *(Bit32u*)(pos+10)=(Bit32u)fct_ptr; // simple_func - } -#endif -} -#endif - -static void cache_block_before_close(void) { - if ((((Bit32u)cache.pos) & 3) != 0) { - cache_addw( NOP ); // nop - } -} - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDRH_IMM(dest_reg, templo1, index) ); // ldrh dest_reg, [templo1, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDR_IMM(dest_reg, templo1, index) ); // ldr dest_reg, [templo1, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) ); // mov templo1, FC_SEGS_ADDR - cache_addw( LDR_IMM(templo2, templo1, index) ); // ldr templo2, [templo1, #index] - cache_addw( ADD_REG(reg, reg, templo2) ); // add reg, reg, templo2 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRH_IMM(dest_reg, templo2, index) ); // ldrh dest_reg, [templo2, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDR_IMM(dest_reg, templo2, index) ); // ldr dest_reg, [templo2, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - if (dword) { - cache_addw( LDR_IMM(dest_reg, templo2, index) ); // ldr dest_reg, [templo2, #index] - } else { - cache_addw( LDRH_IMM(dest_reg, templo2, index) ); // ldrh dest_reg, [templo2, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRB_IMM(dest_reg, templo2, index) ); // ldrb dest_reg, [templo2, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDRB_IMM(dest_reg, templo2, index) ); // ldrb dest_reg, [templo2, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) ); // mov templo2, FC_REGS_ADDR - cache_addw( LDR_IMM(templo1, templo2, index) ); // ldr templo1, [templo2, #index] - cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STRH_IMM(src_reg, templo1, index) ); // strh src_reg, [templo1, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STR_IMM(src_reg, templo1, index) ); // str src_reg, [templo1, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - if (dword) { - cache_addw( STR_IMM(src_reg, templo1, index) ); // str src_reg, [templo1, #index] - } else { - cache_addw( STRH_IMM(src_reg, templo1, index) ); // strh src_reg, [templo1, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) ); // mov templo1, FC_REGS_ADDR - cache_addw( STRB_IMM(src_reg, templo1, index) ); // strb src_reg, [templo1, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le.h b/src/cpu/core_dynrec/risc_armv4le.h deleted file mode 100644 index 7a38d8f27..000000000 --- a/src/cpu/core_dynrec/risc_armv4le.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* ARMv4/ARMv7 (little endian) backend (switcher) by M-HT */ - -#include "risc_armv4le-common.h" - -// choose your destiny: -#if C_TARGETCPU == ARMV7LE - #include "risc_armv4le-o3.h" -#else - #if defined(__THUMB_INTERWORK__) - #include "risc_armv4le-thumb-iw.h" - #else - #include "risc_armv4le-o3.h" -// #include "risc_armv4le-thumb-niw.h" -// #include "risc_armv4le-thumb.h" - #endif -#endif diff --git a/src/cpu/core_dynrec/risc_mipsel32.h b/src/cpu/core_dynrec/risc_mipsel32.h deleted file mode 100644 index 96dd1852f..000000000 --- a/src/cpu/core_dynrec/risc_mipsel32.h +++ /dev/null @@ -1,750 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -/* MIPS32 (little endian) backend by crazyc */ - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit32u - -// calling convention modifier -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC /* nothing */ - -// use FC_REGS_ADDR to hold the address of "cpu_regs" and to access it using FC_REGS_ADDR -//#define DRC_USE_REGS_ADDR -// use FC_SEGS_ADDR to hold the address of "Segs" and to access it using FC_SEGS_ADDR -//#define DRC_USE_SEGS_ADDR - -// register mapping -typedef Bit8u HostReg; - -#define HOST_v0 2 -#define HOST_v1 3 -#define HOST_a0 4 -#define HOST_a1 5 -#define HOST_t4 12 -#define HOST_t5 13 -#define HOST_t6 14 -#define HOST_t7 15 -#define HOST_s0 16 -#define HOST_t8 24 -#define HOST_t9 25 -#define temp1 HOST_v1 -#define temp2 HOST_t9 - -// register that holds function return values -#define FC_RETOP HOST_v0 - -// register used for address calculations, -#define FC_ADDR HOST_s0 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a0 - -// register that holds the second parameter -#define FC_OP2 HOST_a1 - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_??? - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_t5 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_t6 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_t7 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_??? -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_??? -#endif - -// save some state to improve code gen -static bool temp1_valid = false; -static Bit32u temp1_value; - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addw((reg_dst<<11)+0x21); // addu reg_dst, $0, reg_src - cache_addw(reg_src); -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - if(imm < 65536) { - cache_addw((Bit16u)imm); // ori dest_reg, $0, imm - cache_addw(0x3400+dest_reg); - } else if(((Bit32s)imm < 0) && ((Bit32s)imm >= -32768)) { - cache_addw((Bit16u)imm); // addiu dest_reg, $0, imm - cache_addw(0x2400+dest_reg); - } else if(!(imm & 0xffff)) { - cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm) - cache_addw(0x3c00+dest_reg); - } else { - cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm) - cache_addw(0x3c00+dest_reg); - cache_addw((Bit16u)imm); // ori dest_reg, dest_reg, %lo(imm) - cache_addw(0x3400+(dest_reg<<5)+dest_reg); - } -} - -// this is the only place temp1 should be modified -static void INLINE mov_imm_to_temp1(Bit32u imm) { - if (temp1_valid && (temp1_value == imm)) return; - gen_mov_dword_to_reg_imm(temp1, imm); - temp1_valid = true; - temp1_value = imm; -} - -static Bit16s gen_addr_temp1(Bit32u addr) { - Bit32u hihalf = addr & 0xffff0000; - Bit16s lohalf = addr & 0xffff; - if (lohalf > 32764) { // [l,s]wl will overflow - hihalf = addr; - lohalf = 0; - } else if(lohalf < 0) hihalf += 0x10000; - mov_imm_to_temp1(hihalf); - return lohalf; -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - Bit16s lohalf = gen_addr_temp1((Bit32u)data); - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - cache_addw(lohalf+3); // lwl dest_reg, 3(temp1) - cache_addw(0x8800+(temp1<<5)+dest_reg); - cache_addw(lohalf); // lwr dest_reg, 0(temp1) - cache_addw(0x9800+(temp1<<5)+dest_reg); - } else { - cache_addw(lohalf); // lw dest_reg, 0(temp1) - cache_addw(0x8C00+(temp1<<5)+dest_reg); - } - } else { - if ((Bit32u)data & 1) { - cache_addw(lohalf); // lbu dest_reg, 0(temp1) - cache_addw(0x9000+(temp1<<5)+dest_reg); - cache_addw(lohalf+1); // lbu temp2, 1(temp1) - cache_addw(0x9000+(temp1<<5)+temp2); -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - cache_addw(0x7a04); // ins dest_reg, temp2, 8, 8 - cache_addw(0x7c00+(temp2<<5)+dest_reg); -#else - cache_addw((temp2<<11)+0x200); // sll temp2, temp2, 8 - cache_addw(temp2); - cache_addw((dest_reg<<11)+0x25); // or dest_reg, temp2, dest_reg - cache_addw((temp2<<5)+dest_reg); -#endif - } else { - cache_addw(lohalf); // lhu dest_reg, 0(temp1); - cache_addw(0x9400+(temp1<<5)+dest_reg); - } - } -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - cache_addw(imm); // ori dest_reg, $0, imm - cache_addw(0x3400+dest_reg); -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - Bit16s lohalf = gen_addr_temp1((Bit32u)dest); - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - cache_addw(lohalf+3); // swl src_reg, 3(temp1) - cache_addw(0xA800+(temp1<<5)+src_reg); - cache_addw(lohalf); // swr src_reg, 0(temp1) - cache_addw(0xB800+(temp1<<5)+src_reg); - } else { - cache_addw(lohalf); // sw src_reg, 0(temp1) - cache_addw(0xAC00+(temp1<<5)+src_reg); - } - } else { - if((Bit32u)dest & 1) { - cache_addw(lohalf); // sb src_reg, 0(temp1) - cache_addw(0xA000+(temp1<<5)+src_reg); - cache_addw((temp2<<11)+0x202); // srl temp2, src_reg, 8 - cache_addw(src_reg); - cache_addw(lohalf+1); // sb temp2, 1(temp1) - cache_addw(0xA000+(temp1<<5)+temp2); - } else { - cache_addw(lohalf); // sh src_reg, 0(temp1); - cache_addw(0xA400+(temp1<<5)+src_reg); - } - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - Bit16s lohalf = gen_addr_temp1((Bit32u)data); - cache_addw(lohalf); // lbu dest_reg, 0(temp1) - cache_addw(0x9000+(temp1<<5)+dest_reg); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - gen_mov_word_to_reg_imm(dest_reg, imm); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - Bit16s lohalf = gen_addr_temp1((Bit32u)dest); - cache_addw(lohalf); // sb src_reg, 0(temp1) - cache_addw(0xA000+(temp1<<5)+src_reg); -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - if (sign) { -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - cache_addw((reg<<11)+0x420); // seb reg, reg - cache_addw(0x7c00+reg); -#else - arch that lacks seb -#endif - } else { - cache_addw(0xff); // andi reg, reg, 0xff - cache_addw(0x3000+(reg<<5)+reg); - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - if (sign) { -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - cache_addw((reg<<11)+0x620); // seh reg, reg - cache_addw(0x7c00+reg); -#else - arch that lacks seh -#endif - } else { - cache_addw(0xffff); // andi reg, reg, 0xffff - cache_addw(0x3000+(reg<<5)+reg); - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(temp2, op, 1); - cache_addw((reg<<11)+0x21); // addu reg, reg, temp2 - cache_addw((reg<<5)+temp2); -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - if(!imm) return; - if(((Bit32s)imm >= -32768) && ((Bit32s)imm < 32768)) { - cache_addw((Bit16u)imm); // addiu reg, reg, imm - cache_addw(0x2400+(reg<<5)+reg); - } else { - mov_imm_to_temp1(imm); - cache_addw((reg<<11)+0x21); // addu reg, reg, temp1 - cache_addw((reg<<5)+temp1); - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - if(imm < 65536) { - cache_addw((Bit16u)imm); // andi reg, reg, imm - cache_addw(0x3000+(reg<<5)+reg); - } else { - mov_imm_to_temp1((Bit32u)imm); - cache_addw((reg<<11)+0x24); // and reg, temp1, reg - cache_addw((temp1<<5)+reg); - } -} - - -// move a 32bit constant value into memory -static void INLINE gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(temp2, imm); - gen_mov_word_from_reg(temp2, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void INLINE gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - gen_mov_word_to_reg(temp2, dest, dword); - gen_add_imm(temp2, imm); - gen_mov_word_from_reg(temp2, dest, dword); -} - -// add an 8bit constant value to a dword memory value -static void INLINE gen_add_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, (Bit32s)imm, 1); -} - -// subtract an 8bit constant value from a dword memory value -static void INLINE gen_sub_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, -((Bit32s)imm), 1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void INLINE gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - gen_add_direct_word(dest, -(Bit32s)imm, dword); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw((scale_reg<<11)+(scale<<6)); // sll scale_reg, scale_reg, scale - cache_addw(scale_reg); - } - cache_addw((dest_reg<<11)+0x21); // addu dest_reg, dest_reg, scale_reg - cache_addw((dest_reg<<5)+scale_reg); - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw((dest_reg<<11)+(scale<<6)); // sll dest_reg, dest_reg, scale - cache_addw(dest_reg); - } - gen_add_imm(dest_reg, imm); -} - -#define DELAY cache_addd(0) // nop - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { -#if C_DEBUG - if ((cache.pos ^ func) & 0xf0000000) LOG_MSG("jump overflow\n"); -#endif - temp1_valid = false; - cache_addd(0x0c000000+(((Bit32u)func>>2)&0x3ffffff)); // jal func - DELAY; -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; -} - -#ifdef __mips_eabi -// max of 8 parameters in $a0-$a3 and $t0-$t3 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param+4, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param+4, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param+4, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param+4, (void *)mem, 1); -} -#else - other mips abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void INLINE gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(temp2, ptr, 1); - if((imm < -32768) || (imm >= 32768)) { - gen_add_imm(temp2, imm); - imm = 0; - } - temp1_valid = false; - cache_addw((Bit16u)imm); // lw temp2, imm(temp2) - cache_addw(0x8C00+(temp2<<5)+temp2); - cache_addd((temp2<<21)+8); // jr temp2 - DELAY; -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u INLINE gen_create_branch_on_zero(HostReg reg,bool dword) { - temp1_valid = false; - if(!dword) { - cache_addw(0xffff); // andi temp1, reg, 0xffff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(0); // beq $0, reg, 0 - cache_addw(0x1000+(dword?reg:temp1)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u INLINE gen_create_branch_on_nonzero(HostReg reg,bool dword) { - temp1_valid = false; - if(!dword) { - cache_addw(0xffff); // andi temp1, reg, 0xffff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(0); // bne $0, reg, 0 - cache_addw(0x1400+(dword?reg:temp1)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - temp1_valid = false; // this is a branch target - *(Bit16u*)data=((Bit16u)((Bit32u)cache.pos-data-4)>>2); -} - -#if 0 // assume for the moment no branch will go farther then +/- 128KB - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - temp1_valid = false; - if (!isdword) { - cache_addw(0xff); // andi temp1, reg, 0xff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(3); // beq $0, reg, +12 - cache_addw(0x1000+(isdword?reg:temp1)); - DELAY; - cache_addd(0x00000000); // fill j - DELAY; - return ((Bit32u)cache.pos-8); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) { - temp1_valid = false; - cache_addw(3); // bgtz reg, +12 - cache_addw(0x1c00+(reg<<5)); - DELAY; - cache_addd(0x00000000); // fill j - DELAY; - return ((Bit32u)cache.pos-8); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - temp1_valid = false; - // this is an absolute branch - *(Bit32u*)data=0x08000000+(((Bit32u)cache.pos>>2)&0x3ffffff); -} -#else -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - temp1_valid = false; - if (!isdword) { - cache_addw(0xff); // andi temp1, reg, 0xff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(0); // bne $0, reg, 0 - cache_addw(0x1400+(isdword?reg:temp1)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) { - temp1_valid = false; - cache_addw(0); // blez reg, 0 - cache_addw(0x1800+(reg<<5)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - gen_fill_branch(data); -} -#endif - -static void gen_run_code(void) { - temp1_valid = false; - cache_addd(0x27bdfff0); // addiu $sp, $sp, -16 - cache_addd(0xafb00004); // sw $s0, 4($sp) - cache_addd(0x00800008); // jr $a0 - cache_addd(0xafbf0000); // sw $ra, 0($sp) -} - -// return from a function -static void gen_return_function(void) { - temp1_valid = false; - cache_addd(0x8fbf0000); // lw $ra, 0($sp) - cache_addd(0x8fb00004); // lw $s0, 4($sp) - cache_addd(0x03e00008); // jr $ra - cache_addd(0x27bd0010); // addiu $sp, $sp, 16 -} - -#ifdef DRC_FLAGS_INVALIDATION -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=0x00851021; // addu $v0, $a0, $a1 - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=0x00851025; // or $v0, $a0, $a1 - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=0x00851024; // and $v0, $a0, $a1 - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=0x00851023; // subu $v0, $a0, $a1 - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=0x00851026; // xor $v0, $a0, $a1 - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=0; // nop - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=0x24820001; // addiu $v0, $a0, 1 - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=0x2482ffff; // addiu $v0, $a0, -1 - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit32u*)pos=0x00a41004; // sllv $v0, $a0, $a1 - break; - case t_SHRb: - case t_SHRw: - case t_SHRd: - *(Bit32u*)pos=0x00a41006; // srlv $v0, $a0, $a1 - break; - case t_SARd: - *(Bit32u*)pos=0x00a41007; // srav $v0, $a0, $a1 - break; -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - case t_RORd: - *(Bit32u*)pos=0x00a41046; // rotr $v0, $a0, $a1 - break; -#endif - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=0x00041023; // subu $v0, $0, $a0 - break; - default: - *(Bit32u*)pos=0x0c000000+((((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func - break; - } -#else - *(Bit32u*)pos=0x0c000000+(((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func -#endif -} -#endif - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { -#ifdef PSP -// writeback dcache and invalidate icache - Bit32u inval_start = ((Bit32u)block_start) & ~63; - Bit32u inval_end = (((Bit32u)block_start) + block_size + 64) & ~63; - for (;inval_start < inval_end; inval_start+=64) { - __builtin_allegrex_cache(0x1a, inval_start); - __builtin_allegrex_cache(0x08, inval_start); - } -#endif -} - -static void cache_block_before_close(void) { } - - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { -// stub -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { -// stub -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { -// stub -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { -// stub -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { -// stub -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { -// stub -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { -// stub -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { -// stub -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { -// stub -} - -#endif diff --git a/src/cpu/core_dynrec/risc_x64.h b/src/cpu/core_dynrec/risc_x64.h deleted file mode 100644 index a2c5b30cf..000000000 --- a/src/cpu/core_dynrec/risc_x64.h +++ /dev/null @@ -1,730 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit64u - -// calling convention modifier -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC /* nothing */ - - -// register mapping -typedef Bit8u HostReg; - -#define HOST_EAX 0 -#define HOST_ECX 1 -#define HOST_EDX 2 -#define HOST_EBX 3 -#define HOST_ESI 6 -#define HOST_EDI 7 - - -// register that holds function return values -#define FC_RETOP HOST_EAX - -// register used for address calculations, if the ABI does not -// state that this register is preserved across function calls -// then define DRC_PROTECT_ADDR_REG above -#define FC_ADDR HOST_EBX - -// register that holds the first parameter -#define FC_OP1 HOST_EDI - -// register that holds the second parameter -#define FC_OP2 HOST_ESI - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_EAX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_ECX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_EDX - - -// temporary register for LEA -#define TEMP_REG_DRC HOST_ESI - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - cache_addb(0x8b); // mov reg_dst,reg_src - cache_addb(0xc0+(reg_dst<<3)+reg_src); -} - - -static INLINE void gen_reg_memaddr(HostReg reg,void* data) { - Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+5); - if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { - cache_addb(0x05+(reg<<3)); - // RIP-relative addressing is offset after the instruction - cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); - } else if ((Bit64u)data<0x100000000LL) { - cache_addw(0x2504+(reg<<3)); - cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL)); - } else { - E_Exit("DRC64:Unhandled memory reference"); - } -} - -static INLINE void gen_memaddr(Bitu op,void* data,Bitu off) { - Bit64s diff; - diff = (Bit64s)data-((Bit64s)cache.pos+off+5); - if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { - // RIP-relative addressing is offset after the instruction - cache_addb(op+1); - cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); - } else if ((Bit64u)data<0x100000000LL) { - cache_addb(op); - cache_addb(0x25); - cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL)); - } else { - E_Exit("DRC64:Unhandled memory reference"); - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x8b); // mov reg,[data] - gen_reg_memaddr(dest_reg,data); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addd(imm); -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x89); // mov [data],reg - gen_reg_memaddr(src_reg,dest); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - cache_addb(0x8a); // mov reg,[data] - gen_reg_memaddr(dest_reg,data); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - cache_addb(0x66); - cache_addb(0x8b); // mov reg,[data] - gen_reg_memaddr(dest_reg,data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addb(0xb0+dest_reg); // mov reg,imm - cache_addb(imm); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - cache_addb(0x88); // mov [data],reg - gen_reg_memaddr(src_reg,dest); -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - - - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_addb(0x03); // add reg,[data] - gen_reg_memaddr(reg,op); -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - cache_addw(0xc081+(reg<<8)); // add reg,imm - cache_addd(imm); -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - cache_addw(0xe081+(reg<<8)); // and reg,imm - cache_addd(imm); -} - - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_addb(0xc7); // mov [data],imm - gen_memaddr(0x04,dest,4); - cache_addd(imm); -} - -// move a 64bit constant value into a full register -static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) { - cache_addb(0x48); - cache_addb(0xb8+dest_reg); // mov dest_reg,imm - cache_addq(imm); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_reg_qword(HOST_EAX,imm); - cache_addb(0x48); - gen_mov_word_from_reg(HOST_EAX,dest,true); -} - - -// add an 8bit constant value to a memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - cache_addb(0x83); // add [data],imm - gen_memaddr(0x4,dest,1); - cache_addb(imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addb(0x81); // add [data],imm - if (dword) { - gen_memaddr(0x4,dest,4); // size of following immediate value - cache_addd((Bit32u)imm); - } else { - gen_memaddr(0x4,dest,2); // size of following immediate value - cache_addw((Bit16u)imm); - } -} - -// subtract an 8bit constant value from a memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - cache_addb(0x83); // sub [data],imm - gen_memaddr(0x2c,dest,1); - cache_addb(imm); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x81); // sub [data],imm - if (dword) { - gen_memaddr(0x2c,dest,4); // size of following immediate value - cache_addd((Bit32u)imm); - } else { - gen_memaddr(0x2c,dest,2); // size of following immediate value - cache_addw((Bit16u)imm); - } -} - - - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - Bit8u rm_base; - Bitu imm_size; - if (!imm) { - imm_size=0; rm_base=0x0; //no imm - } else if ((imm>=-128 && imm<=127)) { - imm_size=1; rm_base=0x40; //Signed byte imm - } else { - imm_size=4; rm_base=0x80; //Signed dword imm - } - - // ea_reg := ea_reg+scale_reg*(2^scale)+imm - cache_addb(0x48); - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator - cache_addb(dest_reg+(scale_reg<<3)+(scale<<6)); - - switch (imm_size) { - case 0: break; - case 1:cache_addb(imm);break; - case 4:cache_addd(imm);break; - } -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - // ea_reg := ea_reg*(2^scale)+imm - // ea_reg := op2 *(2^scale)+imm - cache_addb(0x48); - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg<<3)); - cache_addb(0x05+(dest_reg<<3)+(scale<<6)); - - cache_addd(imm); // always add dword immediate -} - - - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addb(0x48); - cache_addw(0xec83); - cache_addb(0x08); // sub rsp,0x08 (align stack to 16 byte boundary) - - cache_addb(0x48); - cache_addb(0xb8); // mov reg,imm64 - cache_addq((Bit64u)func); - cache_addw(0xd0ff); - - cache_addb(0x48); - cache_addw(0xc483); - cache_addb(0x08); // add rsp,0x08 (reset alignment) -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit64u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - // align the stack - cache_addb(0x48); - cache_addw(0xc48b); // mov rax,rsp - - cache_addb(0x48); - cache_addw(0xec83); // sub rsp,0x08 - cache_addb(0x08); // 0x08==return address pushed onto stack by call - - cache_addb(0x48); - cache_addw(0xe483); // and esp,0xfffffffffffffff0 - cache_addb(0xf0); - - cache_addb(0x48); - cache_addw(0xc483); // add rsp,0x08 - cache_addb(0x08); - - // stack is 16 byte aligned now - - - cache_addb(0x50); // push rax (==old rsp) - - // returned address relates to where the address is stored in gen_call_function_raw - Bit64u proc_addr=(Bit64u)cache.pos-4; - - // Do the actual call to the procedure - cache_addb(0x48); - cache_addb(0xb8); // mov reg,imm64 - cache_addq((Bit64u)func); - - cache_addw(0xd0ff); - - // restore stack - cache_addb(0x5c); // pop rsp - - return proc_addr; -} - - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - // move an immediate 32bit value into a 64bit param reg - switch (param) { - case 0: // mov param1,imm32 - gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); - break; - case 1: // mov param2,imm32 - gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); - break; -#if defined (_MSC_VER) - case 2: // mov r8,imm32 - cache_addw(0xb849); - cache_addq((Bit32u)imm); - break; - case 3: // mov r9,imm32 - cache_addw(0xb949); - cache_addq((Bit32u)imm); - break; -#else - case 2: // mov rdx,imm32 - gen_mov_dword_to_reg_imm(HOST_EDX,(Bit32u)imm); - break; - case 3: // mov rcx,imm32 - gen_mov_dword_to_reg_imm(HOST_ECX,(Bit32u)imm); - break; -#endif - default: - E_Exit("I(mm) >4 params unsupported"); - break; - } -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(DRC_PTR_SIZE_IM addr,Bitu param) { - // move an immediate 64bit value into a 64bit param reg - switch (param) { - case 0: // mov param1,addr64 - gen_mov_reg_qword(FC_OP1,addr); - break; - case 1: // mov param2,addr64 - gen_mov_reg_qword(FC_OP2,addr); - break; -#if defined (_MSC_VER) - case 2: // mov r8,addr64 - cache_addw(0xb849); - cache_addq(addr); - break; - case 3: // mov r9,addr64 - cache_addw(0xb949); - cache_addq(addr); - break; -#else - case 2: // mov rdx,addr64 - gen_mov_reg_qword(HOST_EDX,addr); - break; - case 3: // mov rcx,addr64 - gen_mov_reg_qword(HOST_ECX,addr); - break; -#endif - default: - E_Exit("A(ddr) >4 params unsupported"); - break; - } -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - // move a register into a 64bit param reg, {inputregs}!={outputregs} - switch (param) { - case 0: // mov param1,reg&7 - gen_mov_regs(FC_OP1,reg&7); - break; - case 1: // mov param2,reg&7 - gen_mov_regs(FC_OP2,reg&7); - break; -#if defined (_MSC_VER) - case 2: // mov r8,reg&7 - cache_addb(0x49); - gen_mov_regs(0,reg&7); - break; - case 3: // mov r9,reg&7 - cache_addb(0x49); - gen_mov_regs(1,reg&7); - break; -#else - case 2: // mov rdx,reg&7 - gen_mov_regs(HOST_EDX,reg&7); - break; - case 3: // mov rcx,reg&7 - gen_mov_regs(HOST_ECX,reg&7); - break; -#endif - default: - E_Exit("R(eg) >4 params unsupported"); - break; - } -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - // move memory content into a 64bit param reg - switch (param) { - case 0: // mov param1,[mem] - gen_mov_word_to_reg(FC_OP1,(void*)mem,true); - break; - case 1: // mov param2,[mem] - gen_mov_word_to_reg(FC_OP2,(void*)mem,true); - break; -#if defined (_MSC_VER) - case 2: // mov r8,[mem] - cache_addb(0x49); - gen_mov_word_to_reg(0,(void*)mem,true); - break; - case 3: // mov r9,[mem] - cache_addb(0x49); - gen_mov_word_to_reg(1,(void*)mem,true); - break; -#else - case 2: // mov rdx,[mem] - gen_mov_word_to_reg(HOST_EDX,(void*)mem,true); - break; - case 3: // mov rcx,[mem] - gen_mov_word_to_reg(HOST_ECX,(void*)mem,true); - break; -#endif - default: - E_Exit("R(eg) >4 params unsupported"); - break; - } -} - - - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - cache_addw(0xa148); // mov rax,[data] - cache_addq((Bit64u)ptr); - - cache_addb(0xff); // jmp [rax+imm] - if (!imm) { - cache_addb(0x20); - } else if ((imm>=-128 && imm<=127)) { - cache_addb(0x60); - cache_addb(imm); - } else { - cache_addb(0xa0); - cache_addd(imm); - } -} - - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit64u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0074); // jz addr - return ((Bit64u)cache.pos-1); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit64u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0075); // jnz addr - return ((Bit64u)cache.pos-1); -} - -// calculate relative offset and fill it into the location pointed to by data -static void gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bit64s len=(Bit64u)cache.pos-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)((Bit64u)cache.pos-data-1); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit64u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - // isdword: cmp reg32,0 - // not isdword: cmp reg8,0 - cache_addb(0x0a+(isdword?1:0)); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x850f); // jnz - cache_addd(0); - return ((Bit64u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit64u gen_create_branch_long_leqzero(HostReg reg) { - cache_addw(0xf883+(reg<<8)); - cache_addb(0x00); // cmp reg,0 - - cache_addw(0x8e0f); // jle - cache_addd(0); - return ((Bit64u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void gen_fill_branch_long(Bit64u data) { - *(Bit32u*)data=(Bit32u)((Bit64u)cache.pos-data-4); -} - - -static void gen_run_code(void) { - cache_addb(0x53); // push rbx - cache_addw(0xd0ff+(FC_OP1<<8)); // call rdi - cache_addb(0x5b); // pop rbx -} - -// return from a function -static void gen_return_function(void) { - cache_addb(0xc3); // ret -} - -#ifdef DRC_FLAGS_INVALIDATION -// called when a call to a function can be replaced by a -// call to a simpler function -// check gen_call_function_raw and gen_call_function_setup -// for the targeted code -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)(pos+0)=0xf001f889; // mov eax,edi; add eax,esi - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)(pos+0)=0xf009f889; // mov eax,edi; or eax,esi - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)(pos+0)=0xf021f889; // mov eax,edi; and eax,esi - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)(pos+0)=0xf029f889; // mov eax,edi; sub eax,esi - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)(pos+0)=0xf031f889; // mov eax,edi; xor eax,esi - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)(pos+0)=0x909012eb; // skip - *(Bit32u*)(pos+4)=0x90909090; - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)(pos+0)=0xc0fff889; // mov eax,edi; inc eax - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)(pos+0)=0xc8fff889; // mov eax,edi; dec eax - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)(pos+0)=0xd8f7f889; // mov eax,edi; neg eax - *(Bit32u*)(pos+4)=0x90900eeb; // skip - *(Bit32u*)(pos+8)=0x90909090; - *(Bit32u*)(pos+12)=0x90909090; - *(Bit32u*)(pos+16)=0x90909090; - break; - default: - *(Bit64u*)(pos+6)=(Bit64u)fct_ptr; // fill function pointer - break; - } -#else - *(Bit64u*)(pos+6)=(Bit64u)fct_ptr; // fill function pointer -#endif -} -#endif - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { } - -static void cache_block_before_close(void) { } diff --git a/src/cpu/core_dynrec/risc_x86.h b/src/cpu/core_dynrec/risc_x86.h deleted file mode 100644 index 0ee4e6374..000000000 --- a/src/cpu/core_dynrec/risc_x86.h +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (C) 2002-2013 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit32u - -// calling convention modifier -#if defined (WIN32) -#define DRC_CALL_CONV _fastcall -#define DRC_FC /* nothing */ -#else -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC GCC_ATTRIBUTE(fastcall) -#endif - - -// register mapping -enum HostReg { - HOST_EAX=0, - HOST_ECX, - HOST_EDX, - HOST_EBX, - HOST_ESP, - HOST_EBP, - HOST_ESI, - HOST_EDI -}; - - -// register that holds function return values -#define FC_RETOP HOST_EAX - -// register used for address calculations, if the ABI does not -// state that this register is preserved across function calls -// then define DRC_PROTECT_ADDR_REG above -#define FC_ADDR HOST_EBX - -// register that holds the first parameter -#define FC_OP1 HOST_ECX - -// register that holds the second parameter -#define FC_OP2 HOST_EDX - -// special register that holds the third parameter for _R3 calls (byte accessible) -#define FC_OP3 HOST_EAX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_ECX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_EDX - - -// temporary register for LEA -#define TEMP_REG_DRC HOST_ESI - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - cache_addb(0x8b); // mov reg_dst,reg_src - cache_addb(0xc0+(reg_dst<<3)+reg_src); -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!dword) cache_addb(0x66); - cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data] - cache_addd((Bit32u)data); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addd(imm); -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!dword) cache_addb(0x66); - cache_addw(0x0589+(src_reg<<11)); // mov [data],reg - cache_addd((Bit32u)dest); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - cache_addw(0x058a+(dest_reg<<11)); // mov reg,[data] - cache_addd((Bit32u)data); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - cache_addb(0x66); - cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data] - cache_addd((Bit32u)data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addb(0xb0+dest_reg); // mov reg,imm - cache_addb(imm); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - cache_addw(0x0588+(src_reg<<11)); // mov [data],reg - cache_addd((Bit32u)dest); -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - - - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_addw(0x0503+(reg<<11)); // add reg,[data] - cache_addd((Bit32u)op); -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - cache_addw(0xc081+(reg<<8)); // add reg,imm - cache_addd(imm); -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - cache_addw(0xe081+(reg<<8)); // and reg,imm - cache_addd(imm); -} - - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_addw(0x05c7); // mov [data],imm - cache_addd((Bit32u)dest); - cache_addd(imm); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - - -// add an 8bit constant value to a memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - cache_addw(0x0583); // add [data],imm - cache_addd((Bit32u)dest); - cache_addb(imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x0581); // add [data],imm - cache_addd((Bit32u)dest); - if (dword) cache_addd((Bit32u)imm); - else cache_addw((Bit16u)imm); -} - -// subtract an 8bit constant value from a memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - cache_addw(0x2d83); // sub [data],imm - cache_addd((Bit32u)dest); - cache_addb(imm); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x2d81); // sub [data],imm - cache_addd((Bit32u)dest); - if (dword) cache_addd((Bit32u)imm); - else cache_addw((Bit16u)imm); -} - - - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - Bit8u rm_base; - Bitu imm_size; - if (!imm) { - imm_size=0; rm_base=0x0; //no imm - } else if ((imm>=-128 && imm<=127)) { - imm_size=1; rm_base=0x40; //Signed byte imm - } else { - imm_size=4; rm_base=0x80; //Signed dword imm - } - - // ea_reg := ea_reg+scale_reg*(2^scale)+imm - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator - cache_addb(dest_reg+(scale_reg<<3)+(scale<<6)); - - switch (imm_size) { - case 0: break; - case 1:cache_addb(imm);break; - case 4:cache_addd(imm);break; - } -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - // ea_reg := ea_reg*(2^scale)+imm - // ea_reg := op2 *(2^scale)+imm - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg<<3)); - cache_addb(0x05+(dest_reg<<3)+(scale<<6)); - - cache_addd(imm); // always add dword immediate -} - - - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addb(0xe8); - cache_addd((Bit32u)func - (Bit32u)cache.pos-4); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr=(Bit32u)cache.pos; - // Do the actual call to the procedure - cache_addb(0xe8); - cache_addd((Bit32u)func - (Bit32u)cache.pos-4); - - // Restore the params of the stack - if (paramcount) { - cache_addw(0xc483); //add ESP,imm byte - cache_addb((!fastcall)?paramcount*4:0); - } - return proc_addr; -} - - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - cache_addb(0x68); // push immediate - cache_addd(imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - cache_addb(0x68); // push immediate (address) - cache_addd(addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - cache_addb(0x50+(reg&7)); // push reg -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - cache_addw(0x35ff); // push [] - cache_addd(mem); -} - - - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(HOST_EAX,ptr,true); - cache_addb(0xff); // jmp [eax+imm] - if (!imm) { - cache_addb(0x20); - } else if ((imm>=-128 && imm<=127)) { - cache_addb(0x60); - cache_addb(imm); - } else { - cache_addb(0xa0); - cache_addd(imm); - } -} - - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0074); // jz addr - return ((Bit32u)cache.pos-1); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0075); // jnz addr - return ((Bit32u)cache.pos-1); -} - -// calculate relative offset and fill it into the location pointed to by data -static void gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)((Bit32u)cache.pos-data-1); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - // isdword: cmp reg32,0 - // not isdword: cmp reg8,0 - cache_addb(0x0a+(isdword?1:0)); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x850f); // jnz - cache_addd(0); - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addw(0xf883+(reg<<8)); - cache_addb(0x00); // cmp reg,0 - - cache_addw(0x8e0f); // jle - cache_addd(0); - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void gen_fill_branch_long(Bit32u data) { - *(Bit32u*)data=((Bit32u)cache.pos-data-4); -} - - -static void gen_run_code(void) { - cache_addd(0x0424448b); // mov eax,[esp+4] - cache_addb(0x53); // push ebx - cache_addb(0x56); // push esi - cache_addw(0xd0ff); // call eax - cache_addb(0x5e); // pop esi - cache_addb(0x5b); // pop ebx -} - -// return from a function -static void gen_return_function(void) { - cache_addb(0xc3); // ret -} - -#ifdef DRC_FLAGS_INVALIDATION -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=0xc203c18b; // mov eax,ecx; add eax,edx - *(pos+4)=0x90; - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=0xc20bc18b; // mov eax,ecx; or eax,edx - *(pos+4)=0x90; - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=0xc223c18b; // mov eax,ecx; and eax,edx - *(pos+4)=0x90; - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=0xc22bc18b; // mov eax,ecx; sub eax,edx - *(pos+4)=0x90; - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=0xc233c18b; // mov eax,ecx; xor eax,edx - *(pos+4)=0x90; - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=0x909003eb; // skip - *(pos+4)=0x90; - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=0x9040c18b; // mov eax,ecx; inc eax - *(pos+4)=0x90; - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=0x9048c18b; // mov eax,ecx; dec eax - *(pos+4)=0x90; - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=0xd8f7c18b; // mov eax,ecx; neg eax - *(pos+4)=0x90; - break; - default: - *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4)); // fill function pointer - break; - } -#else - *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4)); // fill function pointer -#endif -} -#endif - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { } - -static void cache_block_before_close(void) { } diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 2c8dd0bc9..d3927241e 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -81,10 +81,6 @@ void CPU_Core_Dyn_X86_Init(void); void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache); void CPU_Core_Dyn_X86_Cache_Close(void); void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu); -#elif (C_DYNREC) -void CPU_Core_Dynrec_Init(void); -void CPU_Core_Dynrec_Cache_Init(bool enable_cache); -void CPU_Core_Dynrec_Cache_Close(void); #endif /* In debug mode exceptions are tested and dosbox exits when @@ -1602,11 +1598,6 @@ void CPU_SET_CRX(Bitu cr,Bitu value) { cpudecoder=&CPU_Core_Dyn_X86_Run; strcpy(core_mode, "dynamic"); } -#elif (C_DYNREC) - if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) { - CPU_Core_Dynrec_Cache_Init(true); - cpudecoder=&CPU_Core_Dynrec_Run; - } #endif CPU_AutoDetermineMode<<=CPU_AUTODETERMINE_SHIFT; } else { @@ -2231,7 +2222,7 @@ static void CPU_ToggleNormalCore(bool pressed) { } } -#if ((C_DYNAMIC_X86) || (C_DYNREC)) +#if (C_DYNAMIC_X86) static void CPU_ToggleDynamicCore(bool pressed) { if (!pressed) return; @@ -2335,15 +2326,13 @@ public: CPU_Core_Full_Init(); #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Init(); -#elif (C_DYNREC) - CPU_Core_Dynrec_Init(); #endif MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles"); MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles"); MAPPER_AddHandler(CPU_ToggleAutoCycles,MK_equals,MMOD1,"cycauto","Tog. Cycles Auto"); MAPPER_AddHandler(CPU_ToggleNormalCore,MK_1,MMOD1,"normal" ,"Tog. Normal Core"); MAPPER_AddHandler(CPU_ToggleFullCore,MK_2,MMOD1,"full","Tog. Full Core"); -#if ((C_DYNAMIC_X86) || (C_DYNREC)) +#if (C_DYNAMIC_X86) MAPPER_AddHandler(CPU_ToggleDynamicCore,MK_3,MMOD1,"dynamic","Tog. Dynamic Core"); #endif MAPPER_AddHandler(CPU_ToggleSimpleCore,MK_4,MMOD1,"simple","Tog. Simple Core"); @@ -2457,13 +2446,7 @@ public: } else if (core == "dynamic_nodhfpu") { cpudecoder=&CPU_Core_Dyn_X86_Run; CPU_Core_Dyn_X86_SetFPUMode(false); -#elif (C_DYNREC) - CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE; - } - else if (core == "dynamic") { - cpudecoder=&CPU_Core_Dynrec_Run; #else - #endif } else { strcpy(core_mode,"normal"); @@ -2473,8 +2456,6 @@ public: #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Cache_Init((core == "dynamic") || (core == "dynamic_nodhfpu")); -#elif (C_DYNREC) - CPU_Core_Dynrec_Cache_Init( core == "dynamic" ); #endif CPU_ArchitectureType = CPU_ARCHTYPE_MIXED; @@ -2535,8 +2516,6 @@ static CPU * test; void CPU_ShutDown(Section* sec) { #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Cache_Close(); -#elif (C_DYNREC) - CPU_Core_Dynrec_Cache_Close(); #endif delete test; } @@ -2622,15 +2601,9 @@ Bit16u CPU_FindDecoderType( CPU_Decoder *decoder ) else if( cpudecoder == &CPU_Core_Simple_Run ) decoder_idx = 2; else if( cpudecoder == &CPU_Core_Full_Run ) decoder_idx = 3; else if( cpudecoder == &CPU_Core_Dyn_X86_Run ) decoder_idx = 4; -#if (C_DYNREC) - else if( cpudecoder == &CPU_Core_Dynrec_Run ) decoder_idx = 5; -#endif else if( cpudecoder == &CPU_Core_Normal_Trap_Run ) decoder_idx = 100; else if( cpudecoder == &CPU_Core_Dyn_X86_Trap_Run ) decoder_idx = 101; -#if(C_DYNREC) - else if( cpudecoder == &CPU_Core_Dynrec_Trap_Run ) decoder_idx = 102; -#endif else if( cpudecoder == &HLT_Decode ) decoder_idx = 200; @@ -2651,15 +2624,9 @@ CPU_Decoder *CPU_IndexDecoderType( Bit16u decoder_idx ) case 2: cpudecoder = &CPU_Core_Simple_Run; break; case 3: cpudecoder = &CPU_Core_Full_Run; break; case 4: cpudecoder = &CPU_Core_Dyn_X86_Run; break; -#if (C_DYNREC) - case 5: cpudecoder = &CPU_Core_Dynrec_Run; break; -#endif case 100: cpudecoder = &CPU_Core_Normal_Trap_Run; break; case 101: cpudecoder = &CPU_Core_Dyn_X86_Trap_Run; break; -#if (C_DYNREC) - case 102: cpudecoder = &CPU_Core_Dynrec_Trap_Run; break; -#endif case 200: cpudecoder = &HLT_Decode; break; } diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index 1de61b6b6..8675d44f0 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -148,7 +148,7 @@ void DOS_Terminate(Bit16u pspseg,bool tsr,Bit8u exitcode) { } else { GFX_SetTitle(-1,-1,-1,false); } -#if (C_DYNAMIC_X86) || (C_DYNREC) +#if (C_DYNAMIC_X86) if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) { cpudecoder=&CPU_Core_Normal_Run; CPU_CycleLeft=0; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index c4b27ccac..73ba3e233 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -707,7 +707,7 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("cpu",&CPU_Init,true);//done const char* cores[] = { "auto", -#if (C_DYNAMIC_X86) || (C_DYNREC) +#if (C_DYNAMIC_X86) "dynamic", #endif "normal", "full", "simple", 0 };