From 03fe25d8184aa25dd23d8a2c52684b1aa36ef431 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 17 Jun 2018 20:26:15 +0100 Subject: [PATCH 001/181] First stage of dynamic recompiler rewrite. Basic IR generation calls C implementation of all instructions. Backend generation implemented for x86, x86-64, ARM and ARM64. --- Makefile.in | 24 +- configure | 380 +- configure.ac | 14 +- src/386_dynarec.c | 1 + src/386_dynarec_ops.c | 92 +- src/Makefile.am | 14 +- src/Makefile.in | 1620 ++++++-- src/codegen.c | 43 + src/codegen.h | 52 +- src/codegen_backend.c | 416 ++ src/codegen_backend.h | 65 + src/codegen_backend_arm.c | 101 + src/codegen_backend_arm.h | 33 + src/codegen_backend_arm64.c | 115 + src/codegen_backend_arm64.h | 40 + src/codegen_backend_arm64_defs.h | 72 + src/codegen_backend_arm64_uops.c | 300 ++ src/codegen_backend_arm_defs.h | 44 + src/codegen_backend_arm_uops.c | 314 ++ src/codegen_backend_x86-64.c | 156 + src/codegen_backend_x86-64.h | 16 + src/codegen_backend_x86-64_defs.h | 8 + src/codegen_backend_x86-64_uops.c | 232 ++ src/codegen_backend_x86.c | 121 + src/codegen_backend_x86.h | 16 + src/codegen_backend_x86_defs.h | 8 + src/codegen_backend_x86_uops.c | 195 + src/codegen_ir.c | 34 + src/codegen_ir.h | 5 + src/codegen_ir_defs.h | 152 + src/codegen_ops.c | 591 --- src/codegen_ops_arith.h | 1028 ----- src/codegen_ops_fpu.h | 645 --- src/codegen_ops_jump.h | 270 -- src/codegen_ops_logic.h | 564 --- src/codegen_ops_misc.h | 269 -- src/codegen_ops_mmx.h | 277 -- src/codegen_ops_mov.h | 656 --- src/codegen_ops_shift.h | 125 - src/codegen_ops_stack.h | 269 -- src/codegen_ops_x86-64.h | 6213 ----------------------------- src/codegen_ops_x86.h | 3995 ------------------- src/codegen_ops_xchg.h | 93 - src/codegen_x86.c | 2180 ---------- src/codegen_x86.h | 42 - src/wx-utils.cc | 1 + 46 files changed, 4134 insertions(+), 17767 deletions(-) create mode 100644 src/codegen_backend.c create mode 100644 src/codegen_backend.h create mode 100644 src/codegen_backend_arm.c create mode 100644 src/codegen_backend_arm.h create mode 100644 src/codegen_backend_arm64.c create mode 100644 src/codegen_backend_arm64.h create mode 100644 src/codegen_backend_arm64_defs.h create mode 100644 src/codegen_backend_arm64_uops.c create mode 100644 src/codegen_backend_arm_defs.h create mode 100644 src/codegen_backend_arm_uops.c create mode 100644 src/codegen_backend_x86-64.c create mode 100644 src/codegen_backend_x86-64.h create mode 100644 src/codegen_backend_x86-64_defs.h create mode 100644 src/codegen_backend_x86-64_uops.c create mode 100644 src/codegen_backend_x86.c create mode 100644 src/codegen_backend_x86.h create mode 100644 src/codegen_backend_x86_defs.h create mode 100644 src/codegen_backend_x86_uops.c create mode 100644 src/codegen_ir.c create mode 100644 src/codegen_ir.h create mode 100644 src/codegen_ir_defs.h delete mode 100644 src/codegen_ops.c delete mode 100644 src/codegen_ops_arith.h delete mode 100644 src/codegen_ops_fpu.h delete mode 100644 src/codegen_ops_jump.h delete mode 100644 src/codegen_ops_logic.h delete mode 100644 src/codegen_ops_misc.h delete mode 100644 src/codegen_ops_mmx.h delete mode 100644 src/codegen_ops_mov.h delete mode 100644 src/codegen_ops_shift.h delete mode 100644 src/codegen_ops_stack.h delete mode 100644 src/codegen_ops_x86-64.h delete mode 100644 src/codegen_ops_x86.h delete mode 100644 src/codegen_ops_xchg.h delete mode 100644 src/codegen_x86.c delete mode 100644 src/codegen_x86.h diff --git a/Makefile.in b/Makefile.in index 903d123..bcd0ae0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -133,7 +133,7 @@ am__recursive_targets = \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck + cscope distdir distdir-am dist dist-all distcheck 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 @@ -308,7 +308,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -342,8 +341,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -461,7 +460,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -526,7 +528,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -552,7 +554,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -570,7 +572,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -580,7 +582,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac diff --git a/configure b/configure index 1aa97de..a6186e3 100755 --- a/configure +++ b/configure @@ -590,6 +590,8 @@ LTLIBOBJS LIBOBJS OS_MACOSX_FALSE OS_MACOSX_TRUE +OS_OTHER_FALSE +OS_OTHER_TRUE OS_WINDOWS_FALSE OS_WINDOWS_TRUE OS_LINUX_FALSE @@ -622,6 +624,10 @@ USE_NETWORKING_FALSE USE_NETWORKING_TRUE USE_WX_FALSE USE_WX_TRUE +CPU_ARM64_FALSE +CPU_ARM64_TRUE +CPU_ARM_FALSE +CPU_ARM_TRUE CPU_X86_64_FALSE CPU_X86_64_TRUE CPU_I386_FALSE @@ -641,7 +647,6 @@ am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR OBJEXT @@ -705,7 +710,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -724,7 +728,8 @@ PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking @@ -798,7 +803,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1051,15 +1055,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1197,7 +1192,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1350,7 +1345,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -2130,7 +2124,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -am__api_version='1.15' +am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -2646,8 +2640,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The @@ -2698,7 +2692,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -3560,45 +3554,45 @@ DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" - -am_make=${MAKE-make} -cat > confinc << 'END' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : @@ -4220,10 +4214,20 @@ $as_echo "${host_cpu}" >&6; } x86_64) CPU=x86_64 { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${host_cpu}" >&5 +$as_echo "${host_cpu}" >&6; } + ;; + armv7l) + CPU=arm + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${host_cpu}" >&5 +$as_echo "${host_cpu}" >&6; } + ;; + aarch64) + CPU=arm64 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${host_cpu}" >&5 $as_echo "${host_cpu}" >&6; } ;; *) - as_fn_error $? "Unsupported CPU." "$LINENO" 5 + as_fn_error $? "Unsupported CPU. ${host_cpu}" "$LINENO" 5 ;; esac @@ -4243,9 +4247,25 @@ else CPU_X86_64_FALSE= fi + if test "$CPU" = "arm"; then + CPU_ARM_TRUE= + CPU_ARM_FALSE='#' +else + CPU_ARM_TRUE='#' + CPU_ARM_FALSE= +fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 -$as_echo_n "checking for off64_t... " >&6; } + if test "$CPU" = "arm64"; then + CPU_ARM64_TRUE= + CPU_ARM64_FALSE='#' +else + CPU_ARM64_TRUE='#' + CPU_ARM64_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t $CPU" >&5 +$as_echo_n "checking for off64_t $CPU... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4265,6 +4285,11 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +case "$host" in + *-*-freebsd*) # has off64_t but no fopen64/etc. + has_lfs="no" + ;; +esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_lfs" >&5 $as_echo "$has_lfs" >&6; } @@ -4464,8 +4489,8 @@ fi if test "x$sdl_prefix$sdl_exec_prefix" = x ; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5 -$as_echo_n "checking for SDL... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sdl2 >= $min_sdl_version" >&5 +$as_echo_n "checking for sdl2 >= $min_sdl_version... " >&6; } if test -n "$SDL_CFLAGS"; then pkg_cv_SDL_CFLAGS="$SDL_CFLAGS" @@ -4505,7 +4530,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -4523,7 +4548,7 @@ fi sdl_pc=no elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } sdl_pc=no else @@ -5213,6 +5238,7 @@ fi build_macosx="no" build_linux="no" build_win="no" +build_other="no" case "$host" in *-*-darwin*) @@ -5317,7 +5343,7 @@ fi SET_MAKE='MAKE=mingw32-make' ;; - *) + *-*-linux*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glGetError in -lGL" >&5 $as_echo_n "checking for glGetError in -lGL... " >&6; } if ${ac_cv_lib_GL_glGetError+:} false; then : @@ -5418,6 +5444,107 @@ fi build_linux="yes" ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glGetError in -lGL" >&5 +$as_echo_n "checking for glGetError in -lGL... " >&6; } +if ${ac_cv_lib_GL_glGetError+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glGetError (); +int +main () +{ +return glGetError (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GL_glGetError=yes +else + ac_cv_lib_GL_glGetError=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glGetError" >&5 +$as_echo "$ac_cv_lib_GL_glGetError" >&6; } +if test "x$ac_cv_lib_GL_glGetError" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGL 1 +_ACEOF + + LIBS="-lGL $LIBS" + +else + \ + echo "You need to install the OpenGL library." + exit -1 +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alGetError in -lopenal" >&5 +$as_echo_n "checking for alGetError in -lopenal... " >&6; } +if ${ac_cv_lib_openal_alGetError+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopenal $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char alGetError (); +int +main () +{ +return alGetError (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_openal_alGetError=yes +else + ac_cv_lib_openal_alGetError=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_openal_alGetError" >&5 +$as_echo "$ac_cv_lib_openal_alGetError" >&6; } +if test "x$ac_cv_lib_openal_alGetError" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBOPENAL 1 +_ACEOF + + LIBS="-lopenal $LIBS" + +else + \ + echo "You need to install the OpenAL library." + exit -1 +fi + + build_other="yes" + ;; esac LIBS="$LIBS $WX_LIBS $SDL_LIBS" @@ -5438,6 +5565,14 @@ else OS_WINDOWS_FALSE= fi + if test "$build_other" = "yes"; then + OS_OTHER_TRUE= + OS_OTHER_FALSE='#' +else + OS_OTHER_TRUE='#' + OS_OTHER_FALSE= +fi + if test "$build_macosx" = "yes"; then OS_MACOSX_TRUE= OS_MACOSX_FALSE='#' @@ -5634,6 +5769,14 @@ if test -z "${CPU_X86_64_TRUE}" && test -z "${CPU_X86_64_FALSE}"; then as_fn_error $? "conditional \"CPU_X86_64\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${CPU_ARM_TRUE}" && test -z "${CPU_ARM_FALSE}"; then + as_fn_error $? "conditional \"CPU_ARM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CPU_ARM64_TRUE}" && test -z "${CPU_ARM64_FALSE}"; then + as_fn_error $? "conditional \"CPU_ARM64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${USE_WX_TRUE}" && test -z "${USE_WX_FALSE}"; then as_fn_error $? "conditional \"USE_WX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -5658,6 +5801,10 @@ if test -z "${OS_WINDOWS_TRUE}" && test -z "${OS_WINDOWS_FALSE}"; then as_fn_error $? "conditional \"OS_WINDOWS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${OS_OTHER_TRUE}" && test -z "${OS_OTHER_FALSE}"; then + as_fn_error $? "conditional \"OS_OTHER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${OS_MACOSX_TRUE}" && test -z "${OS_MACOSX_FALSE}"; then as_fn_error $? "conditional \"OS_MACOSX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -6224,7 +6371,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" _ACEOF @@ -6670,29 +6817,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -6710,53 +6863,48 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)[^/].*/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; diff --git a/configure.ac b/configure.ac index 4a30d37..e4a6932 100644 --- a/configure.ac +++ b/configure.ac @@ -64,15 +64,25 @@ case "${host_cpu}" in CPU=x86_64 AC_MSG_RESULT(${host_cpu}) ;; + armv7l) + CPU=arm + AC_MSG_RESULT(${host_cpu}) + ;; + aarch64) + CPU=arm64 + AC_MSG_RESULT(${host_cpu}) + ;; *) - AC_MSG_ERROR([Unsupported CPU.]) + AC_MSG_ERROR([Unsupported CPU. ${host_cpu}]) ;; esac AM_CONDITIONAL(CPU_I386, test "$CPU" = "i386") AM_CONDITIONAL(CPU_X86_64, test "$CPU" = "x86_64") +AM_CONDITIONAL(CPU_ARM, test "$CPU" = "arm") +AM_CONDITIONAL(CPU_ARM64, test "$CPU" = "arm64") -AC_MSG_CHECKING([for off64_t]) +AC_MSG_CHECKING([for off64_t $CPU]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],[[off64_t n=0;]])],[has_lfs="yes"],[has_lfs="no"]) case "$host" in *-*-freebsd*) # has off64_t but no fopen64/etc. diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 2ccc1dd..4dff9e7 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -8,6 +8,7 @@ #include "x87.h" #include "mem.h" #include "codegen.h" +#include "codegen_backend.h" #include "cpu.h" #include "fdc.h" #include "nmi.h" diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index 5be12c1..23c8036 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -23,6 +23,64 @@ static inline void fetch_ea_32_long(uint32_t rmdat) eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; ea_rseg = cpu_state.ea_seg->seg; + if (cpu_rm == 4) + { + uint8_t sib = rmdat >> 8; + + switch (cpu_mod) + { + case 0: + cpu_state.eaaddr = cpu_state.regs[sib & 7].l; + cpu_state.pc++; + break; + case 1: + cpu_state.pc++; + cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l; +// cpu_state.pc++; + break; + case 2: + cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; + cpu_state.pc += 5; + break; + } + /*SIB byte present*/ + if ((sib & 7) == 5 && !cpu_mod) + cpu_state.eaaddr = getlong(); + else if ((sib & 6) == 4 && !cpu_state.ssegs) + { + easeg = ss; + ea_rseg = SS; + cpu_state.ea_seg = &_ss; + } + if (((sib >> 3) & 7) != 4) + cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); + } + else + { + cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; + if (cpu_mod) + { + if (cpu_rm == 5 && !cpu_state.ssegs) + { + easeg = ss; + ea_rseg = SS; + cpu_state.ea_seg = &_ss; + } + if (cpu_mod == 1) + { + cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); + cpu_state.pc++; + } + else + { + cpu_state.eaaddr += getlong(); + } + } + else if (cpu_rm == 5) + { + cpu_state.eaaddr = getlong(); + } + } if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { uint32_t addr = easeg + cpu_state.eaaddr; @@ -38,6 +96,33 @@ static inline void fetch_ea_16_long(uint32_t rmdat) eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; ea_rseg = cpu_state.ea_seg->seg; + if (!cpu_mod && cpu_rm == 6) + { + cpu_state.eaaddr = getword(); + } + else + { + switch (cpu_mod) + { + case 0: + cpu_state.eaaddr = 0; + break; + case 1: + cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++; + break; + case 2: + cpu_state.eaaddr = getword(); + break; + } + cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); + if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) + { + easeg = ss; + ea_rseg = SS; + cpu_state.ea_seg = &_ss; + } + cpu_state.eaaddr &= 0xFFFF; + } if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { uint32_t addr = easeg + cpu_state.eaaddr; @@ -48,8 +133,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat) } } -#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat); -#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat); +#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; } +#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1 #define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32) @@ -57,7 +142,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat) #define PREFETCH_FLUSH() #define OP_TABLE(name) dynarec_ops_ ## name -#define CLOCK_CYCLES(c) +/*Temporary*/ +#define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) #include "386_ops.h" diff --git a/src/Makefile.am b/src/Makefile.am index 56741ab..ff90dfa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ +cmd640.c codegen.c codegen_backend.c codegen_ir.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ @@ -70,12 +70,20 @@ pcem_SOURCES += wx-sdl2-midi.c endif if CPU_I386 -pcem_SOURCES += codegen_x86.c +pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_uops.c pcem_CFLAGS += -msse2 endif if CPU_X86_64 -pcem_SOURCES += codegen_x86-64.c +pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_uops.c +endif + +if CPU_ARM +pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_uops.c +endif + +if CPU_ARM64 +pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_uops.c endif if USE_NETWORKING diff --git a/src/Makefile.in b/src/Makefile.in index bd8acad..ba15208 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -97,13 +97,15 @@ bin_PROGRAMS = pcem$(EXEEXT) @USE_ALSA_TRUE@am__append_3 = -lasound @USE_ALSA_TRUE@am__append_4 = midi_alsa.c @USE_ALSA_FALSE@am__append_5 = wx-sdl2-midi.c -@CPU_I386_TRUE@am__append_6 = codegen_x86.c +@CPU_I386_TRUE@am__append_6 = codegen_backend_x86.c codegen_backend_x86_uops.c @CPU_I386_TRUE@am__append_7 = -msse2 -@CPU_X86_64_TRUE@am__append_8 = codegen_x86-64.c -@USE_NETWORKING_TRUE@am__append_9 = -DUSE_NETWORKING -@USE_NETWORKING_TRUE@am__append_10 = -DUSE_NETWORKING +@CPU_X86_64_TRUE@am__append_8 = codegen_backend_x86-64.c codegen_backend_x86-64_uops.c +@CPU_ARM_TRUE@am__append_9 = codegen_backend_arm.c codegen_backend_arm_uops.c +@CPU_ARM64_TRUE@am__append_10 = codegen_backend_arm64.c codegen_backend_arm64_uops.c +@USE_NETWORKING_TRUE@am__append_11 = -DUSE_NETWORKING +@USE_NETWORKING_TRUE@am__append_12 = -DUSE_NETWORKING # SLiRP -@USE_NETWORKING_TRUE@am__append_11 = ne2000.c nethandler.c \ +@USE_NETWORKING_TRUE@am__append_13 = ne2000.c nethandler.c \ @USE_NETWORKING_TRUE@ wx-hostconfig.c slirp/bootp.c \ @USE_NETWORKING_TRUE@ slirp/cksum.c slirp/debug.c slirp/if.c \ @USE_NETWORKING_TRUE@ slirp/ip_icmp.c slirp/ip_input.c \ @@ -113,17 +115,19 @@ bin_PROGRAMS = pcem$(EXEEXT) @USE_NETWORKING_TRUE@ slirp/tcp_input.c slirp/tcp_output.c \ @USE_NETWORKING_TRUE@ slirp/tcp_subr.c slirp/tcp_timer.c \ @USE_NETWORKING_TRUE@ slirp/tftp.c slirp/udp.c -@OS_WINDOWS_TRUE@@USE_NETWORKING_TRUE@am__append_12 = -lwsock32 -liphlpapi -@OS_LINUX_TRUE@am__append_13 = cdrom-ioctl-linux.c wx-sdl2-display.c -@OS_MACOSX_TRUE@am__append_14 = cdrom-ioctl-osx.c wx-sdl2-display.c -@OS_MACOSX_TRUE@am__append_15 = -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP -@OS_MACOSX_TRUE@am__append_16 = -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP +@OS_WINDOWS_TRUE@@USE_NETWORKING_TRUE@am__append_14 = -lwsock32 -liphlpapi +@OS_LINUX_TRUE@am__append_15 = cdrom-ioctl-linux.c wx-sdl2-display.c +@OS_OTHER_TRUE@am__append_16 = cdrom-ioctl-dummy.c wx-sdl2-display.c +@OS_MACOSX_TRUE@am__append_17 = cdrom-ioctl-osx.c wx-sdl2-display.c +@OS_MACOSX_TRUE@am__append_18 = -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP +@OS_MACOSX_TRUE@am__append_19 = -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP DEFAULT_INCLUDES = -I.@am__isrc@ -@OS_WINDOWS_TRUE@am__append_17 = cdrom-ioctl.c wx-sdl2-display-win.c -@OS_WINDOWS_TRUE@am__append_18 = wx.res -@HAS_OFF64T_FALSE@am__append_19 = -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell -@RELEASE_BUILD_TRUE@am__append_20 = -DRELEASE_BUILD -@RELEASE_BUILD_TRUE@am__append_21 = -DRELEASE_BUILD +@OS_WINDOWS_TRUE@am__append_20 = cdrom-ioctl.c wx-sdl2-display-win.c +@OS_WINDOWS_TRUE@am__append_21 = wx.res + +#pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell +@RELEASE_BUILD_TRUE@am__append_22 = -DRELEASE_BUILD +@RELEASE_BUILD_TRUE@am__append_23 = -DRELEASE_BUILD subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac @@ -137,23 +141,23 @@ am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am__pcem_SOURCES_DIST = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c \ acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c \ - cdrom-image.cc cdrom-null.c cmd640.c codegen.c codegen_ops.c \ - codegen_timing_486.c codegen_timing_686.c \ - codegen_timing_common.c codegen_timing_pentium.c \ - codegen_timing_winchip.c compaq.c config.c cpu.c dells200.c \ - device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c \ - esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c hdd.c \ - hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c \ - ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c \ - joystick_ch_flightstick_pro.c joystick_standard.c \ - joystick_sw_pad.c joystick_tm_fcs.c keyboard.c \ - keyboard_amstrad.c keyboard_at.c keyboard_olim24.c \ + cdrom-image.cc cdrom-null.c cmd640.c codegen.c \ + codegen_backend.c codegen_ir.c codegen_timing_486.c \ + codegen_timing_686.c codegen_timing_common.c \ + codegen_timing_pentium.c codegen_timing_winchip.c compaq.c \ + config.c cpu.c dells200.c device.c disc.c disc_fdi.c \ + disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c \ + fdd.c fdi2raw.c gameport.c hdd.c hdd_esdi.c hdd_file.c \ + headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c \ + intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c \ + joystick_standard.c joystick_sw_pad.c joystick_tm_fcs.c \ + keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c \ keyboard_pcjr.c keyboard_xt.c laserxt.c lpt.c lpt_dac.c \ - lpt_dss.c mca.c mcr.c mem.c mfm_at.c mfm_xebec.c model.c \ - mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c neat.c \ - nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c \ - pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c \ - nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c \ + lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c \ + model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c \ + neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c \ + pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \ + ps2_nvr.c nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c \ scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \ serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c \ sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c \ @@ -190,20 +194,31 @@ am__pcem_SOURCES_DIST = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c \ wx-sdl2-video-renderer.c wx-sdl2-video-gl3.c wx-glslp-parser.c \ wx-shader_man.c wx-shaderconfig.cc wx-joystickconfig.cc \ wx-createdisc.cc wx-resources.cpp midi_alsa.c wx-sdl2-midi.c \ - codegen_x86.c codegen_x86-64.c ne2000.c nethandler.c \ - wx-hostconfig.c slirp/bootp.c slirp/cksum.c slirp/debug.c \ - slirp/if.c slirp/ip_icmp.c slirp/ip_input.c slirp/ip_output.c \ - slirp/mbuf.c slirp/misc.c slirp/queue.c slirp/sbuf.c \ - slirp/slirp.c slirp/socket.c slirp/tcp_input.c \ + codegen_backend_x86.c codegen_backend_x86_uops.c \ + codegen_backend_x86-64.c codegen_backend_x86-64_uops.c \ + codegen_backend_arm.c codegen_backend_arm_uops.c \ + codegen_backend_arm64.c codegen_backend_arm64_uops.c ne2000.c \ + nethandler.c wx-hostconfig.c slirp/bootp.c slirp/cksum.c \ + slirp/debug.c slirp/if.c slirp/ip_icmp.c slirp/ip_input.c \ + slirp/ip_output.c slirp/mbuf.c slirp/misc.c slirp/queue.c \ + slirp/sbuf.c slirp/slirp.c slirp/socket.c slirp/tcp_input.c \ slirp/tcp_output.c slirp/tcp_subr.c slirp/tcp_timer.c \ slirp/tftp.c slirp/udp.c cdrom-ioctl-linux.c wx-sdl2-display.c \ - cdrom-ioctl-osx.c cdrom-ioctl.c wx-sdl2-display-win.c + cdrom-ioctl-dummy.c cdrom-ioctl-osx.c cdrom-ioctl.c \ + wx-sdl2-display-win.c am__dirstamp = $(am__leading_dot)dirstamp @USE_ALSA_TRUE@am__objects_1 = pcem-midi_alsa.$(OBJEXT) @USE_ALSA_FALSE@am__objects_2 = pcem-wx-sdl2-midi.$(OBJEXT) -@CPU_I386_TRUE@am__objects_3 = pcem-codegen_x86.$(OBJEXT) -@CPU_X86_64_TRUE@am__objects_4 = pcem-codegen_x86-64.$(OBJEXT) -@USE_NETWORKING_TRUE@am__objects_5 = pcem-ne2000.$(OBJEXT) \ +@CPU_I386_TRUE@am__objects_3 = pcem-codegen_backend_x86.$(OBJEXT) \ +@CPU_I386_TRUE@ pcem-codegen_backend_x86_uops.$(OBJEXT) +@CPU_X86_64_TRUE@am__objects_4 = \ +@CPU_X86_64_TRUE@ pcem-codegen_backend_x86-64.$(OBJEXT) \ +@CPU_X86_64_TRUE@ pcem-codegen_backend_x86-64_uops.$(OBJEXT) +@CPU_ARM_TRUE@am__objects_5 = pcem-codegen_backend_arm.$(OBJEXT) \ +@CPU_ARM_TRUE@ pcem-codegen_backend_arm_uops.$(OBJEXT) +@CPU_ARM64_TRUE@am__objects_6 = pcem-codegen_backend_arm64.$(OBJEXT) \ +@CPU_ARM64_TRUE@ pcem-codegen_backend_arm64_uops.$(OBJEXT) +@USE_NETWORKING_TRUE@am__objects_7 = pcem-ne2000.$(OBJEXT) \ @USE_NETWORKING_TRUE@ pcem-nethandler.$(OBJEXT) \ @USE_NETWORKING_TRUE@ pcem-wx-hostconfig.$(OBJEXT) \ @USE_NETWORKING_TRUE@ slirp/pcem-bootp.$(OBJEXT) \ @@ -225,11 +240,13 @@ am__dirstamp = $(am__leading_dot)dirstamp @USE_NETWORKING_TRUE@ slirp/pcem-tcp_timer.$(OBJEXT) \ @USE_NETWORKING_TRUE@ slirp/pcem-tftp.$(OBJEXT) \ @USE_NETWORKING_TRUE@ slirp/pcem-udp.$(OBJEXT) -@OS_LINUX_TRUE@am__objects_6 = pcem-cdrom-ioctl-linux.$(OBJEXT) \ +@OS_LINUX_TRUE@am__objects_8 = pcem-cdrom-ioctl-linux.$(OBJEXT) \ @OS_LINUX_TRUE@ pcem-wx-sdl2-display.$(OBJEXT) -@OS_MACOSX_TRUE@am__objects_7 = pcem-cdrom-ioctl-osx.$(OBJEXT) \ +@OS_OTHER_TRUE@am__objects_9 = pcem-cdrom-ioctl-dummy.$(OBJEXT) \ +@OS_OTHER_TRUE@ pcem-wx-sdl2-display.$(OBJEXT) +@OS_MACOSX_TRUE@am__objects_10 = pcem-cdrom-ioctl-osx.$(OBJEXT) \ @OS_MACOSX_TRUE@ pcem-wx-sdl2-display.$(OBJEXT) -@OS_WINDOWS_TRUE@am__objects_8 = pcem-cdrom-ioctl.$(OBJEXT) \ +@OS_WINDOWS_TRUE@am__objects_11 = pcem-cdrom-ioctl.$(OBJEXT) \ @OS_WINDOWS_TRUE@ pcem-wx-sdl2-display-win.$(OBJEXT) am_pcem_OBJECTS = pcem-386.$(OBJEXT) pcem-386_dynarec.$(OBJEXT) \ pcem-386_dynarec_ops.$(OBJEXT) pcem-808x.$(OBJEXT) \ @@ -237,8 +254,8 @@ am_pcem_OBJECTS = pcem-386.$(OBJEXT) pcem-386_dynarec.$(OBJEXT) \ pcem-ali1429.$(OBJEXT) pcem-amstrad.$(OBJEXT) \ pcem-cbm_io.$(OBJEXT) pcem-cdrom-image.$(OBJEXT) \ pcem-cdrom-null.$(OBJEXT) pcem-cmd640.$(OBJEXT) \ - pcem-codegen.$(OBJEXT) pcem-codegen_ops.$(OBJEXT) \ - pcem-codegen_timing_486.$(OBJEXT) \ + pcem-codegen.$(OBJEXT) pcem-codegen_backend.$(OBJEXT) \ + pcem-codegen_ir.$(OBJEXT) pcem-codegen_timing_486.$(OBJEXT) \ pcem-codegen_timing_686.$(OBJEXT) \ pcem-codegen_timing_common.$(OBJEXT) \ pcem-codegen_timing_pentium.$(OBJEXT) \ @@ -265,11 +282,11 @@ am_pcem_OBJECTS = pcem-386.$(OBJEXT) pcem-386_dynarec.$(OBJEXT) \ pcem-laserxt.$(OBJEXT) pcem-lpt.$(OBJEXT) \ pcem-lpt_dac.$(OBJEXT) pcem-lpt_dss.$(OBJEXT) \ pcem-mca.$(OBJEXT) pcem-mcr.$(OBJEXT) pcem-mem.$(OBJEXT) \ - pcem-mfm_at.$(OBJEXT) pcem-mfm_xebec.$(OBJEXT) \ - pcem-model.$(OBJEXT) pcem-mouse.$(OBJEXT) \ - pcem-mouse_msystems.$(OBJEXT) pcem-mouse_ps2.$(OBJEXT) \ - pcem-mouse_serial.$(OBJEXT) pcem-neat.$(OBJEXT) \ - pcem-nmi.$(OBJEXT) pcem-nvr.$(OBJEXT) \ + pcem-mem_bios.$(OBJEXT) pcem-mfm_at.$(OBJEXT) \ + pcem-mfm_xebec.$(OBJEXT) pcem-model.$(OBJEXT) \ + pcem-mouse.$(OBJEXT) pcem-mouse_msystems.$(OBJEXT) \ + pcem-mouse_ps2.$(OBJEXT) pcem-mouse_serial.$(OBJEXT) \ + pcem-neat.$(OBJEXT) pcem-nmi.$(OBJEXT) pcem-nvr.$(OBJEXT) \ pcem-olivetti_m24.$(OBJEXT) pcem-opti495.$(OBJEXT) \ pcem-paths.$(OBJEXT) pcem-pc.$(OBJEXT) pcem-pc87306.$(OBJEXT) \ pcem-pci.$(OBJEXT) pcem-pic.$(OBJEXT) pcem-piix.$(OBJEXT) \ @@ -354,11 +371,12 @@ am_pcem_OBJECTS = pcem-386.$(OBJEXT) pcem-386_dynarec.$(OBJEXT) \ pcem-wx-joystickconfig.$(OBJEXT) pcem-wx-createdisc.$(OBJEXT) \ pcem-wx-resources.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ $(am__objects_3) $(am__objects_4) $(am__objects_5) \ - $(am__objects_6) $(am__objects_7) $(am__objects_8) + $(am__objects_6) $(am__objects_7) $(am__objects_8) \ + $(am__objects_9) $(am__objects_10) $(am__objects_11) pcem_OBJECTS = $(am_pcem_OBJECTS) am__DEPENDENCIES_1 = pcem_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__append_18) + $(am__append_21) pcem_LINK = $(CXXLD) $(pcem_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SCRIPTS = $(noinst_SCRIPTS) @@ -375,7 +393,194 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/pcem-386.Po \ + ./$(DEPDIR)/pcem-386_dynarec.Po \ + ./$(DEPDIR)/pcem-386_dynarec_ops.Po ./$(DEPDIR)/pcem-808x.Po \ + ./$(DEPDIR)/pcem-acc2036.Po ./$(DEPDIR)/pcem-acer386sx.Po \ + ./$(DEPDIR)/pcem-ali1429.Po ./$(DEPDIR)/pcem-amstrad.Po \ + ./$(DEPDIR)/pcem-cbm_io.Po ./$(DEPDIR)/pcem-cdrom-image.Po \ + ./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po \ + ./$(DEPDIR)/pcem-cdrom-ioctl-linux.Po \ + ./$(DEPDIR)/pcem-cdrom-ioctl-osx.Po \ + ./$(DEPDIR)/pcem-cdrom-ioctl.Po ./$(DEPDIR)/pcem-cdrom-null.Po \ + ./$(DEPDIR)/pcem-cmd640.Po ./$(DEPDIR)/pcem-codegen.Po \ + ./$(DEPDIR)/pcem-codegen_backend.Po \ + ./$(DEPDIR)/pcem-codegen_backend_arm.Po \ + ./$(DEPDIR)/pcem-codegen_backend_arm64.Po \ + ./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po \ + ./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po \ + ./$(DEPDIR)/pcem-codegen_backend_x86-64.Po \ + ./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po \ + ./$(DEPDIR)/pcem-codegen_backend_x86.Po \ + ./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po \ + ./$(DEPDIR)/pcem-codegen_ir.Po \ + ./$(DEPDIR)/pcem-codegen_timing_486.Po \ + ./$(DEPDIR)/pcem-codegen_timing_686.Po \ + ./$(DEPDIR)/pcem-codegen_timing_common.Po \ + ./$(DEPDIR)/pcem-codegen_timing_pentium.Po \ + ./$(DEPDIR)/pcem-codegen_timing_winchip.Po \ + ./$(DEPDIR)/pcem-compaq.Po ./$(DEPDIR)/pcem-config.Po \ + ./$(DEPDIR)/pcem-cpu.Po ./$(DEPDIR)/pcem-dells200.Po \ + ./$(DEPDIR)/pcem-device.Po ./$(DEPDIR)/pcem-disc.Po \ + ./$(DEPDIR)/pcem-disc_fdi.Po ./$(DEPDIR)/pcem-disc_img.Po \ + ./$(DEPDIR)/pcem-disc_sector.Po ./$(DEPDIR)/pcem-dma.Po \ + ./$(DEPDIR)/pcem-esdi_at.Po ./$(DEPDIR)/pcem-fdc.Po \ + ./$(DEPDIR)/pcem-fdc37c665.Po ./$(DEPDIR)/pcem-fdd.Po \ + ./$(DEPDIR)/pcem-fdi2raw.Po ./$(DEPDIR)/pcem-gameport.Po \ + ./$(DEPDIR)/pcem-hdd.Po ./$(DEPDIR)/pcem-hdd_esdi.Po \ + ./$(DEPDIR)/pcem-hdd_file.Po ./$(DEPDIR)/pcem-headland.Po \ + ./$(DEPDIR)/pcem-i430fx.Po ./$(DEPDIR)/pcem-i430lx.Po \ + ./$(DEPDIR)/pcem-i430vx.Po ./$(DEPDIR)/pcem-ide.Po \ + ./$(DEPDIR)/pcem-ide_atapi.Po ./$(DEPDIR)/pcem-intel.Po \ + ./$(DEPDIR)/pcem-intel_flash.Po ./$(DEPDIR)/pcem-io.Po \ + ./$(DEPDIR)/pcem-jim.Po \ + ./$(DEPDIR)/pcem-joystick_ch_flightstick_pro.Po \ + ./$(DEPDIR)/pcem-joystick_standard.Po \ + ./$(DEPDIR)/pcem-joystick_sw_pad.Po \ + ./$(DEPDIR)/pcem-joystick_tm_fcs.Po \ + ./$(DEPDIR)/pcem-keyboard.Po \ + ./$(DEPDIR)/pcem-keyboard_amstrad.Po \ + ./$(DEPDIR)/pcem-keyboard_at.Po \ + ./$(DEPDIR)/pcem-keyboard_olim24.Po \ + ./$(DEPDIR)/pcem-keyboard_pcjr.Po \ + ./$(DEPDIR)/pcem-keyboard_xt.Po ./$(DEPDIR)/pcem-laserxt.Po \ + ./$(DEPDIR)/pcem-lpt.Po ./$(DEPDIR)/pcem-lpt_dac.Po \ + ./$(DEPDIR)/pcem-lpt_dss.Po ./$(DEPDIR)/pcem-mca.Po \ + ./$(DEPDIR)/pcem-mcr.Po ./$(DEPDIR)/pcem-mem.Po \ + ./$(DEPDIR)/pcem-mem_bios.Po ./$(DEPDIR)/pcem-mfm_at.Po \ + ./$(DEPDIR)/pcem-mfm_xebec.Po ./$(DEPDIR)/pcem-midi_alsa.Po \ + ./$(DEPDIR)/pcem-model.Po ./$(DEPDIR)/pcem-mouse.Po \ + ./$(DEPDIR)/pcem-mouse_msystems.Po \ + ./$(DEPDIR)/pcem-mouse_ps2.Po ./$(DEPDIR)/pcem-mouse_serial.Po \ + ./$(DEPDIR)/pcem-ne2000.Po ./$(DEPDIR)/pcem-neat.Po \ + ./$(DEPDIR)/pcem-nethandler.Po ./$(DEPDIR)/pcem-nmi.Po \ + ./$(DEPDIR)/pcem-nvr.Po ./$(DEPDIR)/pcem-nvr_tc8521.Po \ + ./$(DEPDIR)/pcem-olivetti_m24.Po ./$(DEPDIR)/pcem-opti495.Po \ + ./$(DEPDIR)/pcem-paths.Po ./$(DEPDIR)/pcem-pc.Po \ + ./$(DEPDIR)/pcem-pc87306.Po ./$(DEPDIR)/pcem-pci.Po \ + ./$(DEPDIR)/pcem-pic.Po ./$(DEPDIR)/pcem-piix.Po \ + ./$(DEPDIR)/pcem-pit.Po ./$(DEPDIR)/pcem-ppi.Po \ + ./$(DEPDIR)/pcem-ps1.Po ./$(DEPDIR)/pcem-ps2.Po \ + ./$(DEPDIR)/pcem-ps2_mca.Po ./$(DEPDIR)/pcem-ps2_nvr.Po \ + ./$(DEPDIR)/pcem-rom.Po ./$(DEPDIR)/pcem-rtc.Po \ + ./$(DEPDIR)/pcem-rtc_tc8521.Po ./$(DEPDIR)/pcem-scat.Po \ + ./$(DEPDIR)/pcem-scsi.Po ./$(DEPDIR)/pcem-scsi_53c400.Po \ + ./$(DEPDIR)/pcem-scsi_aha1540.Po ./$(DEPDIR)/pcem-scsi_cd.Po \ + ./$(DEPDIR)/pcem-scsi_hd.Po ./$(DEPDIR)/pcem-scsi_zip.Po \ + ./$(DEPDIR)/pcem-serial.Po ./$(DEPDIR)/pcem-sio.Po \ + ./$(DEPDIR)/pcem-sis496.Po ./$(DEPDIR)/pcem-sl82c460.Po \ + ./$(DEPDIR)/pcem-sound.Po ./$(DEPDIR)/pcem-sound_ad1848.Po \ + ./$(DEPDIR)/pcem-sound_adlib.Po \ + ./$(DEPDIR)/pcem-sound_adlibgold.Po \ + ./$(DEPDIR)/pcem-sound_audiopci.Po \ + ./$(DEPDIR)/pcem-sound_cms.Po ./$(DEPDIR)/pcem-sound_dbopl.Po \ + ./$(DEPDIR)/pcem-sound_emu8k.Po ./$(DEPDIR)/pcem-sound_gus.Po \ + ./$(DEPDIR)/pcem-sound_mpu401_uart.Po \ + ./$(DEPDIR)/pcem-sound_opl.Po ./$(DEPDIR)/pcem-sound_pas16.Po \ + ./$(DEPDIR)/pcem-sound_ps1.Po ./$(DEPDIR)/pcem-sound_pssj.Po \ + ./$(DEPDIR)/pcem-sound_resid.Po ./$(DEPDIR)/pcem-sound_sb.Po \ + ./$(DEPDIR)/pcem-sound_sb_dsp.Po \ + ./$(DEPDIR)/pcem-sound_sn76489.Po \ + ./$(DEPDIR)/pcem-sound_speaker.Po \ + ./$(DEPDIR)/pcem-sound_ssi2001.Po \ + ./$(DEPDIR)/pcem-sound_wss.Po ./$(DEPDIR)/pcem-sound_ym7128.Po \ + ./$(DEPDIR)/pcem-soundopenal.Po ./$(DEPDIR)/pcem-t1000.Po \ + ./$(DEPDIR)/pcem-t3100e.Po ./$(DEPDIR)/pcem-tandy_eeprom.Po \ + ./$(DEPDIR)/pcem-tandy_rom.Po ./$(DEPDIR)/pcem-timer.Po \ + ./$(DEPDIR)/pcem-um8669f.Po ./$(DEPDIR)/pcem-um8881f.Po \ + ./$(DEPDIR)/pcem-vid_ati18800.Po \ + ./$(DEPDIR)/pcem-vid_ati28800.Po \ + ./$(DEPDIR)/pcem-vid_ati68860_ramdac.Po \ + ./$(DEPDIR)/pcem-vid_ati_eeprom.Po \ + ./$(DEPDIR)/pcem-vid_ati_mach64.Po ./$(DEPDIR)/pcem-vid_cga.Po \ + ./$(DEPDIR)/pcem-vid_cl5429.Po \ + ./$(DEPDIR)/pcem-vid_colorplus.Po \ + ./$(DEPDIR)/pcem-vid_compaq_cga.Po ./$(DEPDIR)/pcem-vid_ega.Po \ + ./$(DEPDIR)/pcem-vid_et4000.Po \ + ./$(DEPDIR)/pcem-vid_et4000w32.Po \ + ./$(DEPDIR)/pcem-vid_genius.Po \ + ./$(DEPDIR)/pcem-vid_hercules.Po \ + ./$(DEPDIR)/pcem-vid_icd2061.Po \ + ./$(DEPDIR)/pcem-vid_ics2595.Po \ + ./$(DEPDIR)/pcem-vid_incolor.Po ./$(DEPDIR)/pcem-vid_mda.Po \ + ./$(DEPDIR)/pcem-vid_olivetti_m24.Po \ + ./$(DEPDIR)/pcem-vid_oti037.Po ./$(DEPDIR)/pcem-vid_oti067.Po \ + ./$(DEPDIR)/pcem-vid_paradise.Po \ + ./$(DEPDIR)/pcem-vid_pc1512.Po ./$(DEPDIR)/pcem-vid_pc1640.Po \ + ./$(DEPDIR)/pcem-vid_pc200.Po ./$(DEPDIR)/pcem-vid_pcjr.Po \ + ./$(DEPDIR)/pcem-vid_ps1_svga.Po ./$(DEPDIR)/pcem-vid_s3.Po \ + ./$(DEPDIR)/pcem-vid_s3_virge.Po \ + ./$(DEPDIR)/pcem-vid_sdac_ramdac.Po \ + ./$(DEPDIR)/pcem-vid_stg_ramdac.Po \ + ./$(DEPDIR)/pcem-vid_svga.Po \ + ./$(DEPDIR)/pcem-vid_svga_render.Po \ + ./$(DEPDIR)/pcem-vid_t1000.Po ./$(DEPDIR)/pcem-vid_t3100e.Po \ + ./$(DEPDIR)/pcem-vid_tandy.Po ./$(DEPDIR)/pcem-vid_tandysl.Po \ + ./$(DEPDIR)/pcem-vid_tgui9440.Po \ + ./$(DEPDIR)/pcem-vid_tkd8001_ramdac.Po \ + ./$(DEPDIR)/pcem-vid_tvga.Po \ + ./$(DEPDIR)/pcem-vid_unk_ramdac.Po ./$(DEPDIR)/pcem-vid_vga.Po \ + ./$(DEPDIR)/pcem-vid_voodoo.Po ./$(DEPDIR)/pcem-vid_wy700.Po \ + ./$(DEPDIR)/pcem-video.Po ./$(DEPDIR)/pcem-wd76c10.Po \ + ./$(DEPDIR)/pcem-wx-app.Po ./$(DEPDIR)/pcem-wx-common.Po \ + ./$(DEPDIR)/pcem-wx-config.Po \ + ./$(DEPDIR)/pcem-wx-config_sel.Po \ + ./$(DEPDIR)/pcem-wx-createdisc.Po \ + ./$(DEPDIR)/pcem-wx-deviceconfig.Po \ + ./$(DEPDIR)/pcem-wx-dialogbox.Po \ + ./$(DEPDIR)/pcem-wx-glslp-parser.Po \ + ./$(DEPDIR)/pcem-wx-hostconfig.Po \ + ./$(DEPDIR)/pcem-wx-joystickconfig.Po \ + ./$(DEPDIR)/pcem-wx-main.Po ./$(DEPDIR)/pcem-wx-resources.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-display-win.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-display.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-joystick.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-keyboard.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-midi.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-mouse.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-status.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-video-gl3.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-video-renderer.Po \ + ./$(DEPDIR)/pcem-wx-sdl2-video.Po ./$(DEPDIR)/pcem-wx-sdl2.Po \ + ./$(DEPDIR)/pcem-wx-shader_man.Po \ + ./$(DEPDIR)/pcem-wx-shaderconfig.Po \ + ./$(DEPDIR)/pcem-wx-status.Po ./$(DEPDIR)/pcem-wx-thread.Po \ + ./$(DEPDIR)/pcem-wx-utils.Po ./$(DEPDIR)/pcem-x86seg.Po \ + ./$(DEPDIR)/pcem-x87.Po ./$(DEPDIR)/pcem-xi8088.Po \ + ./$(DEPDIR)/pcem-xtide.Po dosbox/$(DEPDIR)/pcem-cdrom_image.Po \ + dosbox/$(DEPDIR)/pcem-dbopl.Po \ + dosbox/$(DEPDIR)/pcem-nukedopl.Po \ + dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po \ + resid-fp/$(DEPDIR)/pcem-convolve-sse.Po \ + resid-fp/$(DEPDIR)/pcem-convolve.Po \ + resid-fp/$(DEPDIR)/pcem-envelope.Po \ + resid-fp/$(DEPDIR)/pcem-extfilt.Po \ + resid-fp/$(DEPDIR)/pcem-filter.Po \ + resid-fp/$(DEPDIR)/pcem-pot.Po resid-fp/$(DEPDIR)/pcem-sid.Po \ + resid-fp/$(DEPDIR)/pcem-voice.Po \ + resid-fp/$(DEPDIR)/pcem-wave.Po \ + resid-fp/$(DEPDIR)/pcem-wave6581_PST.Po \ + resid-fp/$(DEPDIR)/pcem-wave6581_PS_.Po \ + resid-fp/$(DEPDIR)/pcem-wave6581_P_T.Po \ + resid-fp/$(DEPDIR)/pcem-wave6581__ST.Po \ + resid-fp/$(DEPDIR)/pcem-wave8580_PST.Po \ + resid-fp/$(DEPDIR)/pcem-wave8580_PS_.Po \ + resid-fp/$(DEPDIR)/pcem-wave8580_P_T.Po \ + resid-fp/$(DEPDIR)/pcem-wave8580__ST.Po \ + slirp/$(DEPDIR)/pcem-bootp.Po slirp/$(DEPDIR)/pcem-cksum.Po \ + slirp/$(DEPDIR)/pcem-debug.Po slirp/$(DEPDIR)/pcem-if.Po \ + slirp/$(DEPDIR)/pcem-ip_icmp.Po \ + slirp/$(DEPDIR)/pcem-ip_input.Po \ + slirp/$(DEPDIR)/pcem-ip_output.Po slirp/$(DEPDIR)/pcem-mbuf.Po \ + slirp/$(DEPDIR)/pcem-misc.Po slirp/$(DEPDIR)/pcem-queue.Po \ + slirp/$(DEPDIR)/pcem-sbuf.Po slirp/$(DEPDIR)/pcem-slirp.Po \ + slirp/$(DEPDIR)/pcem-socket.Po \ + slirp/$(DEPDIR)/pcem-tcp_input.Po \ + slirp/$(DEPDIR)/pcem-tcp_output.Po \ + slirp/$(DEPDIR)/pcem-tcp_subr.Po \ + slirp/$(DEPDIR)/pcem-tcp_timer.Po slirp/$(DEPDIR)/pcem-tftp.Po \ + slirp/$(DEPDIR)/pcem-udp.Po am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -542,7 +747,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -556,7 +760,7 @@ noinst_SCRIPTS = $(am__append_2) CLEANFILES = $(am__append_1) # Special wxWidgets files -WINDRES = $(shell wx-config --rescomp) +WINDRES = $(shell $(WX_CONFIG_PATH) --rescomp) # PCem @@ -565,7 +769,7 @@ WINDRES = $(shell wx-config --rescomp) # resid-fp pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c \ acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc \ - cdrom-null.c cmd640.c codegen.c codegen_ops.c \ + cdrom-null.c cmd640.c codegen.c codegen_backend.c codegen_ir.c \ codegen_timing_486.c codegen_timing_686.c \ codegen_timing_common.c codegen_timing_pentium.c \ codegen_timing_winchip.c compaq.c config.c cpu.c dells200.c \ @@ -577,11 +781,11 @@ pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c \ joystick_sw_pad.c joystick_tm_fcs.c keyboard.c \ keyboard_amstrad.c keyboard_at.c keyboard_olim24.c \ keyboard_pcjr.c keyboard_xt.c laserxt.c lpt.c lpt_dac.c \ - lpt_dss.c mca.c mcr.c mem.c mfm_at.c mfm_xebec.c model.c \ - mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c neat.c \ - nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c \ - pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c \ - nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c \ + lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c \ + model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c \ + neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c \ + pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \ + ps2_nvr.c nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c \ scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \ serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c \ sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c \ @@ -619,14 +823,16 @@ pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c \ wx-shader_man.c wx-shaderconfig.cc wx-joystickconfig.cc \ wx-createdisc.cc wx-resources.cpp $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_8) \ - $(am__append_11) $(am__append_13) $(am__append_14) \ - $(am__append_17) -pcem_CFLAGS = $(subst -fpermissive,,$(shell wx-config --cxxflags) \ - $(shell sdl2-config --cflags)) $(am__append_7) $(am__append_9) \ - $(am__append_15) $(am__append_19) $(am__append_20) -pcem_CXXFLAGS = $(shell wx-config --cxxflags) $(shell sdl2-config \ - --cflags) $(am__append_10) $(am__append_16) $(am__append_21) -pcem_LDADD = @LIBS@ $(am__append_3) $(am__append_12) $(am__append_18) + $(am__append_9) $(am__append_10) $(am__append_13) \ + $(am__append_15) $(am__append_16) $(am__append_17) \ + $(am__append_20) +pcem_CFLAGS = $(subst -fpermissive,,$(shell $(WX_CONFIG_PATH) \ + --cxxflags) $(shell sdl2-config --cflags)) $(am__append_7) \ + $(am__append_11) $(am__append_18) $(am__append_22) +pcem_CXXFLAGS = $(shell $(WX_CONFIG_PATH) --cxxflags) $(shell \ + sdl2-config --cflags) $(am__append_12) $(am__append_19) \ + $(am__append_23) +pcem_LDADD = @LIBS@ $(am__append_3) $(am__append_14) $(am__append_21) @OS_WINDOWS_TRUE@DEFAULT_INCLUDES = -iquote . all: all-am @@ -649,8 +855,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status *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);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -815,266 +1021,281 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_dynarec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_dynarec_ops.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-808x.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acc2036.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acer386sx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ali1429.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-amstrad.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cbm_io.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-image.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl-linux.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl-osx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-null.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cmd640.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_486.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_686.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_common.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_pentium.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_winchip.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_x86-64.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_x86.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-compaq.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cpu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dells200.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_fdi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_img.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_sector.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dma.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-esdi_at.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc37c665.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdi2raw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-gameport.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd_esdi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd_file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-headland.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430fx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430lx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430vx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide_atapi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-intel.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-intel_flash.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-io.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-jim.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_ch_flightstick_pro.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_standard.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_sw_pad.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_tm_fcs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_amstrad.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_at.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_olim24.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_pcjr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_xt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-laserxt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-lpt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-lpt_dac.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-lpt_dss.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mca.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mcr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mem.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mfm_at.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mfm_xebec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-midi_alsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_msystems.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_ps2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_serial.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ne2000.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-neat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nethandler.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nmi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nvr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nvr_tc8521.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-olivetti_m24.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-opti495.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-paths.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc87306.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pci.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pic.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-piix.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pit.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ppi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2_mca.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2_nvr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rom.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rtc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rtc_tc8521.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_53c400.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_aha1540.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_cd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_hd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_zip.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-serial.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sis496.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sl82c460.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ad1848.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_adlib.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_adlibgold.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_audiopci.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_cms.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_dbopl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_emu8k.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_gus.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_mpu401_uart.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_opl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_pas16.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ps1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_pssj.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_resid.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_sb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_sb_dsp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_sn76489.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_speaker.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ssi2001.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_wss.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ym7128.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-soundopenal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-t1000.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-t3100e.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-tandy_eeprom.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-tandy_rom.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-timer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-um8669f.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-um8881f.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati18800.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati28800.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati68860_ramdac.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati_eeprom.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati_mach64.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_cga.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_cl5429.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_colorplus.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_compaq_cga.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ega.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_et4000.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_et4000w32.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_genius.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_hercules.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_icd2061.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ics2595.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_incolor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_mda.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_olivetti_m24.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_oti037.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_oti067.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_paradise.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc1512.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc1640.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc200.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pcjr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ps1_svga.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_s3.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_s3_virge.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_sdac_ramdac.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_stg_ramdac.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_svga.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_svga_render.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_t1000.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_t3100e.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tandy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tandysl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tgui9440.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tkd8001_ramdac.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tvga.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_unk_ramdac.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_vga.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_wy700.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-video.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wd76c10.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-app.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-common.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-config_sel.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-createdisc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-deviceconfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-dialogbox.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-glslp-parser.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-hostconfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-joystickconfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-resources.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-display-win.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-display.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-joystick.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-keyboard.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-midi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-mouse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-status.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-video-gl3.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-video-renderer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-video.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-shader_man.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-shaderconfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-status.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-thread.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-utils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x86seg.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x87.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-xi8088.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-xtide.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-cdrom_image.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-dbopl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-nukedopl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-convolve-sse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-convolve.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-envelope.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-extfilt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-filter.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-pot.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-sid.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-voice.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581_PST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581_PS_.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581_P_T.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581__ST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580_PST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580_PS_.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580_P_T.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580__ST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-bootp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-cksum.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-debug.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-if.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-ip_icmp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-ip_input.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-ip_output.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-mbuf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-misc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-queue.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-sbuf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-slirp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-socket.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_input.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_output.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_subr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_timer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tftp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-udp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_dynarec.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_dynarec_ops.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-808x.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acc2036.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acer386sx.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ali1429.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-amstrad.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cbm_io.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-image.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl-linux.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl-osx.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-null.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cmd640.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm64.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86-64.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ir.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_486.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_686.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_common.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_pentium.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_winchip.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-compaq.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-config.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cpu.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dells200.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_fdi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_img.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_sector.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dma.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-esdi_at.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc37c665.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdi2raw.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-gameport.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd_esdi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd_file.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-headland.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430fx.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430lx.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430vx.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide_atapi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-intel.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-intel_flash.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-io.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-jim.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_ch_flightstick_pro.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_standard.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_sw_pad.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-joystick_tm_fcs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_amstrad.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_at.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_olim24.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_pcjr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-keyboard_xt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-laserxt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-lpt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-lpt_dac.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-lpt_dss.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mca.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mcr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mem.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mem_bios.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mfm_at.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mfm_xebec.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-midi_alsa.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-model.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_msystems.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_ps2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_serial.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ne2000.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-neat.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nethandler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nmi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nvr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nvr_tc8521.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-olivetti_m24.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-opti495.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-paths.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc87306.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pci.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pic.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-piix.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pit.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ppi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2_mca.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2_nvr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rom.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rtc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rtc_tc8521.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scat.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_53c400.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_aha1540.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_cd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_hd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_zip.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-serial.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sio.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sis496.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sl82c460.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ad1848.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_adlib.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_adlibgold.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_audiopci.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_cms.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_dbopl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_emu8k.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_gus.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_mpu401_uart.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_opl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_pas16.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ps1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_pssj.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_resid.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_sb.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_sb_dsp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_sn76489.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_speaker.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ssi2001.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_wss.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ym7128.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-soundopenal.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-t1000.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-t3100e.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-tandy_eeprom.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-tandy_rom.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-um8669f.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-um8881f.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati18800.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati28800.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati68860_ramdac.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati_eeprom.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ati_mach64.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_cga.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_cl5429.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_colorplus.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_compaq_cga.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ega.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_et4000.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_et4000w32.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_genius.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_hercules.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_icd2061.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ics2595.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_incolor.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_mda.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_olivetti_m24.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_oti037.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_oti067.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_paradise.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc1512.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc1640.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc200.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pcjr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ps1_svga.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_s3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_s3_virge.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_sdac_ramdac.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_stg_ramdac.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_svga.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_svga_render.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_t1000.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_t3100e.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tandy.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tandysl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tgui9440.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tkd8001_ramdac.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_tvga.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_unk_ramdac.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_vga.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_wy700.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-video.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wd76c10.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-app.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-common.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-config.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-config_sel.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-createdisc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-deviceconfig.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-dialogbox.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-glslp-parser.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-hostconfig.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-joystickconfig.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-resources.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-display-win.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-display.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-joystick.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-keyboard.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-midi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-mouse.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-status.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-video-gl3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-video-renderer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2-video.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-sdl2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-shader_man.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-shaderconfig.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-status.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-thread.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-utils.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x86seg.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x87.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-xi8088.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-xtide.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-cdrom_image.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-dbopl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-nukedopl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-convolve-sse.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-convolve.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-envelope.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-extfilt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-filter.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-pot.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-sid.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-voice.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581_PST.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581_PS_.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581_P_T.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave6581__ST.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580_PST.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580_PS_.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580_P_T.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-wave8580__ST.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-bootp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-cksum.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-debug.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-if.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-ip_icmp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-ip_input.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-ip_output.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-mbuf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-misc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-queue.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-sbuf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-slirp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-socket.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_input.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_output.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_subr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tcp_timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-tftp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@slirp/$(DEPDIR)/pcem-udp.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -1260,19 +1481,33 @@ pcem-codegen.obj: codegen.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen.obj `if test -f 'codegen.c'; then $(CYGPATH_W) 'codegen.c'; else $(CYGPATH_W) '$(srcdir)/codegen.c'; fi` -pcem-codegen_ops.o: codegen_ops.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops.Tpo -c -o pcem-codegen_ops.o `test -f 'codegen_ops.c' || echo '$(srcdir)/'`codegen_ops.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops.Tpo $(DEPDIR)/pcem-codegen_ops.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops.c' object='pcem-codegen_ops.o' libtool=no @AMDEPBACKSLASH@ +pcem-codegen_backend.o: codegen_backend.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend.Tpo -c -o pcem-codegen_backend.o `test -f 'codegen_backend.c' || echo '$(srcdir)/'`codegen_backend.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend.Tpo $(DEPDIR)/pcem-codegen_backend.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend.c' object='pcem-codegen_backend.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops.o `test -f 'codegen_ops.c' || echo '$(srcdir)/'`codegen_ops.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend.o `test -f 'codegen_backend.c' || echo '$(srcdir)/'`codegen_backend.c -pcem-codegen_ops.obj: codegen_ops.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops.Tpo -c -o pcem-codegen_ops.obj `if test -f 'codegen_ops.c'; then $(CYGPATH_W) 'codegen_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops.Tpo $(DEPDIR)/pcem-codegen_ops.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops.c' object='pcem-codegen_ops.obj' libtool=no @AMDEPBACKSLASH@ +pcem-codegen_backend.obj: codegen_backend.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend.Tpo -c -o pcem-codegen_backend.obj `if test -f 'codegen_backend.c'; then $(CYGPATH_W) 'codegen_backend.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend.Tpo $(DEPDIR)/pcem-codegen_backend.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend.c' object='pcem-codegen_backend.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops.obj `if test -f 'codegen_ops.c'; then $(CYGPATH_W) 'codegen_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend.obj `if test -f 'codegen_backend.c'; then $(CYGPATH_W) 'codegen_backend.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend.c'; fi` + +pcem-codegen_ir.o: codegen_ir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ir.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ir.Tpo -c -o pcem-codegen_ir.o `test -f 'codegen_ir.c' || echo '$(srcdir)/'`codegen_ir.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ir.Tpo $(DEPDIR)/pcem-codegen_ir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ir.c' object='pcem-codegen_ir.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ir.o `test -f 'codegen_ir.c' || echo '$(srcdir)/'`codegen_ir.c + +pcem-codegen_ir.obj: codegen_ir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ir.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ir.Tpo -c -o pcem-codegen_ir.obj `if test -f 'codegen_ir.c'; then $(CYGPATH_W) 'codegen_ir.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ir.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ir.Tpo $(DEPDIR)/pcem-codegen_ir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ir.c' object='pcem-codegen_ir.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ir.obj `if test -f 'codegen_ir.c'; then $(CYGPATH_W) 'codegen_ir.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ir.c'; fi` pcem-codegen_timing_486.o: codegen_timing_486.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_486.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_486.Tpo -c -o pcem-codegen_timing_486.o `test -f 'codegen_timing_486.c' || echo '$(srcdir)/'`codegen_timing_486.c @@ -1988,6 +2223,20 @@ pcem-mem.obj: mem.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-mem.obj `if test -f 'mem.c'; then $(CYGPATH_W) 'mem.c'; else $(CYGPATH_W) '$(srcdir)/mem.c'; fi` +pcem-mem_bios.o: mem_bios.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-mem_bios.o -MD -MP -MF $(DEPDIR)/pcem-mem_bios.Tpo -c -o pcem-mem_bios.o `test -f 'mem_bios.c' || echo '$(srcdir)/'`mem_bios.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-mem_bios.Tpo $(DEPDIR)/pcem-mem_bios.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mem_bios.c' object='pcem-mem_bios.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-mem_bios.o `test -f 'mem_bios.c' || echo '$(srcdir)/'`mem_bios.c + +pcem-mem_bios.obj: mem_bios.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-mem_bios.obj -MD -MP -MF $(DEPDIR)/pcem-mem_bios.Tpo -c -o pcem-mem_bios.obj `if test -f 'mem_bios.c'; then $(CYGPATH_W) 'mem_bios.c'; else $(CYGPATH_W) '$(srcdir)/mem_bios.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-mem_bios.Tpo $(DEPDIR)/pcem-mem_bios.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mem_bios.c' object='pcem-mem_bios.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-mem_bios.obj `if test -f 'mem_bios.c'; then $(CYGPATH_W) 'mem_bios.c'; else $(CYGPATH_W) '$(srcdir)/mem_bios.c'; fi` + pcem-mfm_at.o: mfm_at.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-mfm_at.o -MD -MP -MF $(DEPDIR)/pcem-mfm_at.Tpo -c -o pcem-mfm_at.o `test -f 'mfm_at.c' || echo '$(srcdir)/'`mfm_at.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-mfm_at.Tpo $(DEPDIR)/pcem-mfm_at.Po @@ -3864,33 +4113,117 @@ pcem-wx-sdl2-midi.obj: wx-sdl2-midi.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-wx-sdl2-midi.obj `if test -f 'wx-sdl2-midi.c'; then $(CYGPATH_W) 'wx-sdl2-midi.c'; else $(CYGPATH_W) '$(srcdir)/wx-sdl2-midi.c'; fi` -pcem-codegen_x86.o: codegen_x86.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_x86.o -MD -MP -MF $(DEPDIR)/pcem-codegen_x86.Tpo -c -o pcem-codegen_x86.o `test -f 'codegen_x86.c' || echo '$(srcdir)/'`codegen_x86.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_x86.Tpo $(DEPDIR)/pcem-codegen_x86.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_x86.c' object='pcem-codegen_x86.o' libtool=no @AMDEPBACKSLASH@ +pcem-codegen_backend_x86.o: codegen_backend_x86.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86.Tpo -c -o pcem-codegen_backend_x86.o `test -f 'codegen_backend_x86.c' || echo '$(srcdir)/'`codegen_backend_x86.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86.Tpo $(DEPDIR)/pcem-codegen_backend_x86.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86.c' object='pcem-codegen_backend_x86.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_x86.o `test -f 'codegen_x86.c' || echo '$(srcdir)/'`codegen_x86.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86.o `test -f 'codegen_backend_x86.c' || echo '$(srcdir)/'`codegen_backend_x86.c -pcem-codegen_x86.obj: codegen_x86.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_x86.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_x86.Tpo -c -o pcem-codegen_x86.obj `if test -f 'codegen_x86.c'; then $(CYGPATH_W) 'codegen_x86.c'; else $(CYGPATH_W) '$(srcdir)/codegen_x86.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_x86.Tpo $(DEPDIR)/pcem-codegen_x86.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_x86.c' object='pcem-codegen_x86.obj' libtool=no @AMDEPBACKSLASH@ +pcem-codegen_backend_x86.obj: codegen_backend_x86.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86.Tpo -c -o pcem-codegen_backend_x86.obj `if test -f 'codegen_backend_x86.c'; then $(CYGPATH_W) 'codegen_backend_x86.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86.Tpo $(DEPDIR)/pcem-codegen_backend_x86.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86.c' object='pcem-codegen_backend_x86.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_x86.obj `if test -f 'codegen_x86.c'; then $(CYGPATH_W) 'codegen_x86.c'; else $(CYGPATH_W) '$(srcdir)/codegen_x86.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86.obj `if test -f 'codegen_backend_x86.c'; then $(CYGPATH_W) 'codegen_backend_x86.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86.c'; fi` -pcem-codegen_x86-64.o: codegen_x86-64.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_x86-64.o -MD -MP -MF $(DEPDIR)/pcem-codegen_x86-64.Tpo -c -o pcem-codegen_x86-64.o `test -f 'codegen_x86-64.c' || echo '$(srcdir)/'`codegen_x86-64.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_x86-64.Tpo $(DEPDIR)/pcem-codegen_x86-64.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_x86-64.c' object='pcem-codegen_x86-64.o' libtool=no @AMDEPBACKSLASH@ +pcem-codegen_backend_x86_uops.o: codegen_backend_x86_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_uops.Tpo -c -o pcem-codegen_backend_x86_uops.o `test -f 'codegen_backend_x86_uops.c' || echo '$(srcdir)/'`codegen_backend_x86_uops.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_uops.Tpo $(DEPDIR)/pcem-codegen_backend_x86_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_uops.c' object='pcem-codegen_backend_x86_uops.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_x86-64.o `test -f 'codegen_x86-64.c' || echo '$(srcdir)/'`codegen_x86-64.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_uops.o `test -f 'codegen_backend_x86_uops.c' || echo '$(srcdir)/'`codegen_backend_x86_uops.c -pcem-codegen_x86-64.obj: codegen_x86-64.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_x86-64.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_x86-64.Tpo -c -o pcem-codegen_x86-64.obj `if test -f 'codegen_x86-64.c'; then $(CYGPATH_W) 'codegen_x86-64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_x86-64.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_x86-64.Tpo $(DEPDIR)/pcem-codegen_x86-64.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_x86-64.c' object='pcem-codegen_x86-64.obj' libtool=no @AMDEPBACKSLASH@ +pcem-codegen_backend_x86_uops.obj: codegen_backend_x86_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_uops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_uops.Tpo -c -o pcem-codegen_backend_x86_uops.obj `if test -f 'codegen_backend_x86_uops.c'; then $(CYGPATH_W) 'codegen_backend_x86_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_uops.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_uops.Tpo $(DEPDIR)/pcem-codegen_backend_x86_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_uops.c' object='pcem-codegen_backend_x86_uops.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_x86-64.obj `if test -f 'codegen_x86-64.c'; then $(CYGPATH_W) 'codegen_x86-64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_x86-64.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_uops.obj `if test -f 'codegen_backend_x86_uops.c'; then $(CYGPATH_W) 'codegen_backend_x86_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_uops.c'; fi` + +pcem-codegen_backend_x86-64.o: codegen_backend_x86-64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64.Tpo -c -o pcem-codegen_backend_x86-64.o `test -f 'codegen_backend_x86-64.c' || echo '$(srcdir)/'`codegen_backend_x86-64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64.c' object='pcem-codegen_backend_x86-64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64.o `test -f 'codegen_backend_x86-64.c' || echo '$(srcdir)/'`codegen_backend_x86-64.c + +pcem-codegen_backend_x86-64.obj: codegen_backend_x86-64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64.Tpo -c -o pcem-codegen_backend_x86-64.obj `if test -f 'codegen_backend_x86-64.c'; then $(CYGPATH_W) 'codegen_backend_x86-64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64.c' object='pcem-codegen_backend_x86-64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64.obj `if test -f 'codegen_backend_x86-64.c'; then $(CYGPATH_W) 'codegen_backend_x86-64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64.c'; fi` + +pcem-codegen_backend_x86-64_uops.o: codegen_backend_x86-64_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Tpo -c -o pcem-codegen_backend_x86-64_uops.o `test -f 'codegen_backend_x86-64_uops.c' || echo '$(srcdir)/'`codegen_backend_x86-64_uops.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64_uops.c' object='pcem-codegen_backend_x86-64_uops.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64_uops.o `test -f 'codegen_backend_x86-64_uops.c' || echo '$(srcdir)/'`codegen_backend_x86-64_uops.c + +pcem-codegen_backend_x86-64_uops.obj: codegen_backend_x86-64_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_uops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Tpo -c -o pcem-codegen_backend_x86-64_uops.obj `if test -f 'codegen_backend_x86-64_uops.c'; then $(CYGPATH_W) 'codegen_backend_x86-64_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64_uops.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64_uops.c' object='pcem-codegen_backend_x86-64_uops.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64_uops.obj `if test -f 'codegen_backend_x86-64_uops.c'; then $(CYGPATH_W) 'codegen_backend_x86-64_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64_uops.c'; fi` + +pcem-codegen_backend_arm.o: codegen_backend_arm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm.Tpo -c -o pcem-codegen_backend_arm.o `test -f 'codegen_backend_arm.c' || echo '$(srcdir)/'`codegen_backend_arm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm.Tpo $(DEPDIR)/pcem-codegen_backend_arm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm.c' object='pcem-codegen_backend_arm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm.o `test -f 'codegen_backend_arm.c' || echo '$(srcdir)/'`codegen_backend_arm.c + +pcem-codegen_backend_arm.obj: codegen_backend_arm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm.Tpo -c -o pcem-codegen_backend_arm.obj `if test -f 'codegen_backend_arm.c'; then $(CYGPATH_W) 'codegen_backend_arm.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm.Tpo $(DEPDIR)/pcem-codegen_backend_arm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm.c' object='pcem-codegen_backend_arm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm.obj `if test -f 'codegen_backend_arm.c'; then $(CYGPATH_W) 'codegen_backend_arm.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm.c'; fi` + +pcem-codegen_backend_arm_uops.o: codegen_backend_arm_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm_uops.Tpo -c -o pcem-codegen_backend_arm_uops.o `test -f 'codegen_backend_arm_uops.c' || echo '$(srcdir)/'`codegen_backend_arm_uops.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm_uops.Tpo $(DEPDIR)/pcem-codegen_backend_arm_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm_uops.c' object='pcem-codegen_backend_arm_uops.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm_uops.o `test -f 'codegen_backend_arm_uops.c' || echo '$(srcdir)/'`codegen_backend_arm_uops.c + +pcem-codegen_backend_arm_uops.obj: codegen_backend_arm_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm_uops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm_uops.Tpo -c -o pcem-codegen_backend_arm_uops.obj `if test -f 'codegen_backend_arm_uops.c'; then $(CYGPATH_W) 'codegen_backend_arm_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm_uops.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm_uops.Tpo $(DEPDIR)/pcem-codegen_backend_arm_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm_uops.c' object='pcem-codegen_backend_arm_uops.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm_uops.obj `if test -f 'codegen_backend_arm_uops.c'; then $(CYGPATH_W) 'codegen_backend_arm_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm_uops.c'; fi` + +pcem-codegen_backend_arm64.o: codegen_backend_arm64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64.Tpo -c -o pcem-codegen_backend_arm64.o `test -f 'codegen_backend_arm64.c' || echo '$(srcdir)/'`codegen_backend_arm64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64.Tpo $(DEPDIR)/pcem-codegen_backend_arm64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64.c' object='pcem-codegen_backend_arm64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64.o `test -f 'codegen_backend_arm64.c' || echo '$(srcdir)/'`codegen_backend_arm64.c + +pcem-codegen_backend_arm64.obj: codegen_backend_arm64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64.Tpo -c -o pcem-codegen_backend_arm64.obj `if test -f 'codegen_backend_arm64.c'; then $(CYGPATH_W) 'codegen_backend_arm64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64.Tpo $(DEPDIR)/pcem-codegen_backend_arm64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64.c' object='pcem-codegen_backend_arm64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64.obj `if test -f 'codegen_backend_arm64.c'; then $(CYGPATH_W) 'codegen_backend_arm64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64.c'; fi` + +pcem-codegen_backend_arm64_uops.o: codegen_backend_arm64_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_uops.Tpo -c -o pcem-codegen_backend_arm64_uops.o `test -f 'codegen_backend_arm64_uops.c' || echo '$(srcdir)/'`codegen_backend_arm64_uops.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_uops.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64_uops.c' object='pcem-codegen_backend_arm64_uops.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64_uops.o `test -f 'codegen_backend_arm64_uops.c' || echo '$(srcdir)/'`codegen_backend_arm64_uops.c + +pcem-codegen_backend_arm64_uops.obj: codegen_backend_arm64_uops.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_uops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_uops.Tpo -c -o pcem-codegen_backend_arm64_uops.obj `if test -f 'codegen_backend_arm64_uops.c'; then $(CYGPATH_W) 'codegen_backend_arm64_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64_uops.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_uops.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_uops.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64_uops.c' object='pcem-codegen_backend_arm64_uops.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64_uops.obj `if test -f 'codegen_backend_arm64_uops.c'; then $(CYGPATH_W) 'codegen_backend_arm64_uops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64_uops.c'; fi` pcem-ne2000.o: ne2000.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-ne2000.o -MD -MP -MF $(DEPDIR)/pcem-ne2000.Tpo -c -o pcem-ne2000.o `test -f 'ne2000.c' || echo '$(srcdir)/'`ne2000.c @@ -4228,6 +4561,20 @@ pcem-wx-sdl2-display.obj: wx-sdl2-display.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-wx-sdl2-display.obj `if test -f 'wx-sdl2-display.c'; then $(CYGPATH_W) 'wx-sdl2-display.c'; else $(CYGPATH_W) '$(srcdir)/wx-sdl2-display.c'; fi` +pcem-cdrom-ioctl-dummy.o: cdrom-ioctl-dummy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cdrom-ioctl-dummy.o -MD -MP -MF $(DEPDIR)/pcem-cdrom-ioctl-dummy.Tpo -c -o pcem-cdrom-ioctl-dummy.o `test -f 'cdrom-ioctl-dummy.c' || echo '$(srcdir)/'`cdrom-ioctl-dummy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cdrom-ioctl-dummy.Tpo $(DEPDIR)/pcem-cdrom-ioctl-dummy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cdrom-ioctl-dummy.c' object='pcem-cdrom-ioctl-dummy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cdrom-ioctl-dummy.o `test -f 'cdrom-ioctl-dummy.c' || echo '$(srcdir)/'`cdrom-ioctl-dummy.c + +pcem-cdrom-ioctl-dummy.obj: cdrom-ioctl-dummy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cdrom-ioctl-dummy.obj -MD -MP -MF $(DEPDIR)/pcem-cdrom-ioctl-dummy.Tpo -c -o pcem-cdrom-ioctl-dummy.obj `if test -f 'cdrom-ioctl-dummy.c'; then $(CYGPATH_W) 'cdrom-ioctl-dummy.c'; else $(CYGPATH_W) '$(srcdir)/cdrom-ioctl-dummy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cdrom-ioctl-dummy.Tpo $(DEPDIR)/pcem-cdrom-ioctl-dummy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cdrom-ioctl-dummy.c' object='pcem-cdrom-ioctl-dummy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cdrom-ioctl-dummy.obj `if test -f 'cdrom-ioctl-dummy.c'; then $(CYGPATH_W) 'cdrom-ioctl-dummy.c'; else $(CYGPATH_W) '$(srcdir)/cdrom-ioctl-dummy.c'; fi` + pcem-cdrom-ioctl-osx.o: cdrom-ioctl-osx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cdrom-ioctl-osx.o -MD -MP -MF $(DEPDIR)/pcem-cdrom-ioctl-osx.Tpo -c -o pcem-cdrom-ioctl-osx.o `test -f 'cdrom-ioctl-osx.c' || echo '$(srcdir)/'`cdrom-ioctl-osx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cdrom-ioctl-osx.Tpo $(DEPDIR)/pcem-cdrom-ioctl-osx.Po @@ -4816,7 +5163,10 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -4895,7 +5245,275 @@ clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) dosbox/$(DEPDIR) resid-fp/$(DEPDIR) slirp/$(DEPDIR) + -rm -f ./$(DEPDIR)/pcem-386.Po + -rm -f ./$(DEPDIR)/pcem-386_dynarec.Po + -rm -f ./$(DEPDIR)/pcem-386_dynarec_ops.Po + -rm -f ./$(DEPDIR)/pcem-808x.Po + -rm -f ./$(DEPDIR)/pcem-acc2036.Po + -rm -f ./$(DEPDIR)/pcem-acer386sx.Po + -rm -f ./$(DEPDIR)/pcem-ali1429.Po + -rm -f ./$(DEPDIR)/pcem-amstrad.Po + -rm -f ./$(DEPDIR)/pcem-cbm_io.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-image.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-linux.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-osx.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-null.Po + -rm -f ./$(DEPDIR)/pcem-cmd640.Po + -rm -f ./$(DEPDIR)/pcem-codegen.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_ir.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_486.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_686.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_common.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_pentium.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_winchip.Po + -rm -f ./$(DEPDIR)/pcem-compaq.Po + -rm -f ./$(DEPDIR)/pcem-config.Po + -rm -f ./$(DEPDIR)/pcem-cpu.Po + -rm -f ./$(DEPDIR)/pcem-dells200.Po + -rm -f ./$(DEPDIR)/pcem-device.Po + -rm -f ./$(DEPDIR)/pcem-disc.Po + -rm -f ./$(DEPDIR)/pcem-disc_fdi.Po + -rm -f ./$(DEPDIR)/pcem-disc_img.Po + -rm -f ./$(DEPDIR)/pcem-disc_sector.Po + -rm -f ./$(DEPDIR)/pcem-dma.Po + -rm -f ./$(DEPDIR)/pcem-esdi_at.Po + -rm -f ./$(DEPDIR)/pcem-fdc.Po + -rm -f ./$(DEPDIR)/pcem-fdc37c665.Po + -rm -f ./$(DEPDIR)/pcem-fdd.Po + -rm -f ./$(DEPDIR)/pcem-fdi2raw.Po + -rm -f ./$(DEPDIR)/pcem-gameport.Po + -rm -f ./$(DEPDIR)/pcem-hdd.Po + -rm -f ./$(DEPDIR)/pcem-hdd_esdi.Po + -rm -f ./$(DEPDIR)/pcem-hdd_file.Po + -rm -f ./$(DEPDIR)/pcem-headland.Po + -rm -f ./$(DEPDIR)/pcem-i430fx.Po + -rm -f ./$(DEPDIR)/pcem-i430lx.Po + -rm -f ./$(DEPDIR)/pcem-i430vx.Po + -rm -f ./$(DEPDIR)/pcem-ide.Po + -rm -f ./$(DEPDIR)/pcem-ide_atapi.Po + -rm -f ./$(DEPDIR)/pcem-intel.Po + -rm -f ./$(DEPDIR)/pcem-intel_flash.Po + -rm -f ./$(DEPDIR)/pcem-io.Po + -rm -f ./$(DEPDIR)/pcem-jim.Po + -rm -f ./$(DEPDIR)/pcem-joystick_ch_flightstick_pro.Po + -rm -f ./$(DEPDIR)/pcem-joystick_standard.Po + -rm -f ./$(DEPDIR)/pcem-joystick_sw_pad.Po + -rm -f ./$(DEPDIR)/pcem-joystick_tm_fcs.Po + -rm -f ./$(DEPDIR)/pcem-keyboard.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_amstrad.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_at.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_olim24.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_pcjr.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_xt.Po + -rm -f ./$(DEPDIR)/pcem-laserxt.Po + -rm -f ./$(DEPDIR)/pcem-lpt.Po + -rm -f ./$(DEPDIR)/pcem-lpt_dac.Po + -rm -f ./$(DEPDIR)/pcem-lpt_dss.Po + -rm -f ./$(DEPDIR)/pcem-mca.Po + -rm -f ./$(DEPDIR)/pcem-mcr.Po + -rm -f ./$(DEPDIR)/pcem-mem.Po + -rm -f ./$(DEPDIR)/pcem-mem_bios.Po + -rm -f ./$(DEPDIR)/pcem-mfm_at.Po + -rm -f ./$(DEPDIR)/pcem-mfm_xebec.Po + -rm -f ./$(DEPDIR)/pcem-midi_alsa.Po + -rm -f ./$(DEPDIR)/pcem-model.Po + -rm -f ./$(DEPDIR)/pcem-mouse.Po + -rm -f ./$(DEPDIR)/pcem-mouse_msystems.Po + -rm -f ./$(DEPDIR)/pcem-mouse_ps2.Po + -rm -f ./$(DEPDIR)/pcem-mouse_serial.Po + -rm -f ./$(DEPDIR)/pcem-ne2000.Po + -rm -f ./$(DEPDIR)/pcem-neat.Po + -rm -f ./$(DEPDIR)/pcem-nethandler.Po + -rm -f ./$(DEPDIR)/pcem-nmi.Po + -rm -f ./$(DEPDIR)/pcem-nvr.Po + -rm -f ./$(DEPDIR)/pcem-nvr_tc8521.Po + -rm -f ./$(DEPDIR)/pcem-olivetti_m24.Po + -rm -f ./$(DEPDIR)/pcem-opti495.Po + -rm -f ./$(DEPDIR)/pcem-paths.Po + -rm -f ./$(DEPDIR)/pcem-pc.Po + -rm -f ./$(DEPDIR)/pcem-pc87306.Po + -rm -f ./$(DEPDIR)/pcem-pci.Po + -rm -f ./$(DEPDIR)/pcem-pic.Po + -rm -f ./$(DEPDIR)/pcem-piix.Po + -rm -f ./$(DEPDIR)/pcem-pit.Po + -rm -f ./$(DEPDIR)/pcem-ppi.Po + -rm -f ./$(DEPDIR)/pcem-ps1.Po + -rm -f ./$(DEPDIR)/pcem-ps2.Po + -rm -f ./$(DEPDIR)/pcem-ps2_mca.Po + -rm -f ./$(DEPDIR)/pcem-ps2_nvr.Po + -rm -f ./$(DEPDIR)/pcem-rom.Po + -rm -f ./$(DEPDIR)/pcem-rtc.Po + -rm -f ./$(DEPDIR)/pcem-rtc_tc8521.Po + -rm -f ./$(DEPDIR)/pcem-scat.Po + -rm -f ./$(DEPDIR)/pcem-scsi.Po + -rm -f ./$(DEPDIR)/pcem-scsi_53c400.Po + -rm -f ./$(DEPDIR)/pcem-scsi_aha1540.Po + -rm -f ./$(DEPDIR)/pcem-scsi_cd.Po + -rm -f ./$(DEPDIR)/pcem-scsi_hd.Po + -rm -f ./$(DEPDIR)/pcem-scsi_zip.Po + -rm -f ./$(DEPDIR)/pcem-serial.Po + -rm -f ./$(DEPDIR)/pcem-sio.Po + -rm -f ./$(DEPDIR)/pcem-sis496.Po + -rm -f ./$(DEPDIR)/pcem-sl82c460.Po + -rm -f ./$(DEPDIR)/pcem-sound.Po + -rm -f ./$(DEPDIR)/pcem-sound_ad1848.Po + -rm -f ./$(DEPDIR)/pcem-sound_adlib.Po + -rm -f ./$(DEPDIR)/pcem-sound_adlibgold.Po + -rm -f ./$(DEPDIR)/pcem-sound_audiopci.Po + -rm -f ./$(DEPDIR)/pcem-sound_cms.Po + -rm -f ./$(DEPDIR)/pcem-sound_dbopl.Po + -rm -f ./$(DEPDIR)/pcem-sound_emu8k.Po + -rm -f ./$(DEPDIR)/pcem-sound_gus.Po + -rm -f ./$(DEPDIR)/pcem-sound_mpu401_uart.Po + -rm -f ./$(DEPDIR)/pcem-sound_opl.Po + -rm -f ./$(DEPDIR)/pcem-sound_pas16.Po + -rm -f ./$(DEPDIR)/pcem-sound_ps1.Po + -rm -f ./$(DEPDIR)/pcem-sound_pssj.Po + -rm -f ./$(DEPDIR)/pcem-sound_resid.Po + -rm -f ./$(DEPDIR)/pcem-sound_sb.Po + -rm -f ./$(DEPDIR)/pcem-sound_sb_dsp.Po + -rm -f ./$(DEPDIR)/pcem-sound_sn76489.Po + -rm -f ./$(DEPDIR)/pcem-sound_speaker.Po + -rm -f ./$(DEPDIR)/pcem-sound_ssi2001.Po + -rm -f ./$(DEPDIR)/pcem-sound_wss.Po + -rm -f ./$(DEPDIR)/pcem-sound_ym7128.Po + -rm -f ./$(DEPDIR)/pcem-soundopenal.Po + -rm -f ./$(DEPDIR)/pcem-t1000.Po + -rm -f ./$(DEPDIR)/pcem-t3100e.Po + -rm -f ./$(DEPDIR)/pcem-tandy_eeprom.Po + -rm -f ./$(DEPDIR)/pcem-tandy_rom.Po + -rm -f ./$(DEPDIR)/pcem-timer.Po + -rm -f ./$(DEPDIR)/pcem-um8669f.Po + -rm -f ./$(DEPDIR)/pcem-um8881f.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati18800.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati28800.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati68860_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati_eeprom.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati_mach64.Po + -rm -f ./$(DEPDIR)/pcem-vid_cga.Po + -rm -f ./$(DEPDIR)/pcem-vid_cl5429.Po + -rm -f ./$(DEPDIR)/pcem-vid_colorplus.Po + -rm -f ./$(DEPDIR)/pcem-vid_compaq_cga.Po + -rm -f ./$(DEPDIR)/pcem-vid_ega.Po + -rm -f ./$(DEPDIR)/pcem-vid_et4000.Po + -rm -f ./$(DEPDIR)/pcem-vid_et4000w32.Po + -rm -f ./$(DEPDIR)/pcem-vid_genius.Po + -rm -f ./$(DEPDIR)/pcem-vid_hercules.Po + -rm -f ./$(DEPDIR)/pcem-vid_icd2061.Po + -rm -f ./$(DEPDIR)/pcem-vid_ics2595.Po + -rm -f ./$(DEPDIR)/pcem-vid_incolor.Po + -rm -f ./$(DEPDIR)/pcem-vid_mda.Po + -rm -f ./$(DEPDIR)/pcem-vid_olivetti_m24.Po + -rm -f ./$(DEPDIR)/pcem-vid_oti037.Po + -rm -f ./$(DEPDIR)/pcem-vid_oti067.Po + -rm -f ./$(DEPDIR)/pcem-vid_paradise.Po + -rm -f ./$(DEPDIR)/pcem-vid_pc1512.Po + -rm -f ./$(DEPDIR)/pcem-vid_pc1640.Po + -rm -f ./$(DEPDIR)/pcem-vid_pc200.Po + -rm -f ./$(DEPDIR)/pcem-vid_pcjr.Po + -rm -f ./$(DEPDIR)/pcem-vid_ps1_svga.Po + -rm -f ./$(DEPDIR)/pcem-vid_s3.Po + -rm -f ./$(DEPDIR)/pcem-vid_s3_virge.Po + -rm -f ./$(DEPDIR)/pcem-vid_sdac_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_stg_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_svga.Po + -rm -f ./$(DEPDIR)/pcem-vid_svga_render.Po + -rm -f ./$(DEPDIR)/pcem-vid_t1000.Po + -rm -f ./$(DEPDIR)/pcem-vid_t3100e.Po + -rm -f ./$(DEPDIR)/pcem-vid_tandy.Po + -rm -f ./$(DEPDIR)/pcem-vid_tandysl.Po + -rm -f ./$(DEPDIR)/pcem-vid_tgui9440.Po + -rm -f ./$(DEPDIR)/pcem-vid_tkd8001_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_tvga.Po + -rm -f ./$(DEPDIR)/pcem-vid_unk_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_vga.Po + -rm -f ./$(DEPDIR)/pcem-vid_voodoo.Po + -rm -f ./$(DEPDIR)/pcem-vid_wy700.Po + -rm -f ./$(DEPDIR)/pcem-video.Po + -rm -f ./$(DEPDIR)/pcem-wd76c10.Po + -rm -f ./$(DEPDIR)/pcem-wx-app.Po + -rm -f ./$(DEPDIR)/pcem-wx-common.Po + -rm -f ./$(DEPDIR)/pcem-wx-config.Po + -rm -f ./$(DEPDIR)/pcem-wx-config_sel.Po + -rm -f ./$(DEPDIR)/pcem-wx-createdisc.Po + -rm -f ./$(DEPDIR)/pcem-wx-deviceconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-dialogbox.Po + -rm -f ./$(DEPDIR)/pcem-wx-glslp-parser.Po + -rm -f ./$(DEPDIR)/pcem-wx-hostconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-joystickconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-main.Po + -rm -f ./$(DEPDIR)/pcem-wx-resources.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-display-win.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-display.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-joystick.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-keyboard.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-midi.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-mouse.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-status.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-video-gl3.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-video-renderer.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-video.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2.Po + -rm -f ./$(DEPDIR)/pcem-wx-shader_man.Po + -rm -f ./$(DEPDIR)/pcem-wx-shaderconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-status.Po + -rm -f ./$(DEPDIR)/pcem-wx-thread.Po + -rm -f ./$(DEPDIR)/pcem-wx-utils.Po + -rm -f ./$(DEPDIR)/pcem-x86seg.Po + -rm -f ./$(DEPDIR)/pcem-x87.Po + -rm -f ./$(DEPDIR)/pcem-xi8088.Po + -rm -f ./$(DEPDIR)/pcem-xtide.Po + -rm -f dosbox/$(DEPDIR)/pcem-cdrom_image.Po + -rm -f dosbox/$(DEPDIR)/pcem-dbopl.Po + -rm -f dosbox/$(DEPDIR)/pcem-nukedopl.Po + -rm -f dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po + -rm -f resid-fp/$(DEPDIR)/pcem-convolve-sse.Po + -rm -f resid-fp/$(DEPDIR)/pcem-convolve.Po + -rm -f resid-fp/$(DEPDIR)/pcem-envelope.Po + -rm -f resid-fp/$(DEPDIR)/pcem-extfilt.Po + -rm -f resid-fp/$(DEPDIR)/pcem-filter.Po + -rm -f resid-fp/$(DEPDIR)/pcem-pot.Po + -rm -f resid-fp/$(DEPDIR)/pcem-sid.Po + -rm -f resid-fp/$(DEPDIR)/pcem-voice.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581_PST.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581_PS_.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581_P_T.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581__ST.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580_PST.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580_PS_.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580_P_T.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580__ST.Po + -rm -f slirp/$(DEPDIR)/pcem-bootp.Po + -rm -f slirp/$(DEPDIR)/pcem-cksum.Po + -rm -f slirp/$(DEPDIR)/pcem-debug.Po + -rm -f slirp/$(DEPDIR)/pcem-if.Po + -rm -f slirp/$(DEPDIR)/pcem-ip_icmp.Po + -rm -f slirp/$(DEPDIR)/pcem-ip_input.Po + -rm -f slirp/$(DEPDIR)/pcem-ip_output.Po + -rm -f slirp/$(DEPDIR)/pcem-mbuf.Po + -rm -f slirp/$(DEPDIR)/pcem-misc.Po + -rm -f slirp/$(DEPDIR)/pcem-queue.Po + -rm -f slirp/$(DEPDIR)/pcem-sbuf.Po + -rm -f slirp/$(DEPDIR)/pcem-slirp.Po + -rm -f slirp/$(DEPDIR)/pcem-socket.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_input.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_output.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_subr.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_timer.Po + -rm -f slirp/$(DEPDIR)/pcem-tftp.Po + -rm -f slirp/$(DEPDIR)/pcem-udp.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -4941,7 +5559,275 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) dosbox/$(DEPDIR) resid-fp/$(DEPDIR) slirp/$(DEPDIR) + -rm -f ./$(DEPDIR)/pcem-386.Po + -rm -f ./$(DEPDIR)/pcem-386_dynarec.Po + -rm -f ./$(DEPDIR)/pcem-386_dynarec_ops.Po + -rm -f ./$(DEPDIR)/pcem-808x.Po + -rm -f ./$(DEPDIR)/pcem-acc2036.Po + -rm -f ./$(DEPDIR)/pcem-acer386sx.Po + -rm -f ./$(DEPDIR)/pcem-ali1429.Po + -rm -f ./$(DEPDIR)/pcem-amstrad.Po + -rm -f ./$(DEPDIR)/pcem-cbm_io.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-image.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-linux.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-osx.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-ioctl.Po + -rm -f ./$(DEPDIR)/pcem-cdrom-null.Po + -rm -f ./$(DEPDIR)/pcem-cmd640.Po + -rm -f ./$(DEPDIR)/pcem-codegen.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86.Po + -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po + -rm -f ./$(DEPDIR)/pcem-codegen_ir.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_486.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_686.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_common.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_pentium.Po + -rm -f ./$(DEPDIR)/pcem-codegen_timing_winchip.Po + -rm -f ./$(DEPDIR)/pcem-compaq.Po + -rm -f ./$(DEPDIR)/pcem-config.Po + -rm -f ./$(DEPDIR)/pcem-cpu.Po + -rm -f ./$(DEPDIR)/pcem-dells200.Po + -rm -f ./$(DEPDIR)/pcem-device.Po + -rm -f ./$(DEPDIR)/pcem-disc.Po + -rm -f ./$(DEPDIR)/pcem-disc_fdi.Po + -rm -f ./$(DEPDIR)/pcem-disc_img.Po + -rm -f ./$(DEPDIR)/pcem-disc_sector.Po + -rm -f ./$(DEPDIR)/pcem-dma.Po + -rm -f ./$(DEPDIR)/pcem-esdi_at.Po + -rm -f ./$(DEPDIR)/pcem-fdc.Po + -rm -f ./$(DEPDIR)/pcem-fdc37c665.Po + -rm -f ./$(DEPDIR)/pcem-fdd.Po + -rm -f ./$(DEPDIR)/pcem-fdi2raw.Po + -rm -f ./$(DEPDIR)/pcem-gameport.Po + -rm -f ./$(DEPDIR)/pcem-hdd.Po + -rm -f ./$(DEPDIR)/pcem-hdd_esdi.Po + -rm -f ./$(DEPDIR)/pcem-hdd_file.Po + -rm -f ./$(DEPDIR)/pcem-headland.Po + -rm -f ./$(DEPDIR)/pcem-i430fx.Po + -rm -f ./$(DEPDIR)/pcem-i430lx.Po + -rm -f ./$(DEPDIR)/pcem-i430vx.Po + -rm -f ./$(DEPDIR)/pcem-ide.Po + -rm -f ./$(DEPDIR)/pcem-ide_atapi.Po + -rm -f ./$(DEPDIR)/pcem-intel.Po + -rm -f ./$(DEPDIR)/pcem-intel_flash.Po + -rm -f ./$(DEPDIR)/pcem-io.Po + -rm -f ./$(DEPDIR)/pcem-jim.Po + -rm -f ./$(DEPDIR)/pcem-joystick_ch_flightstick_pro.Po + -rm -f ./$(DEPDIR)/pcem-joystick_standard.Po + -rm -f ./$(DEPDIR)/pcem-joystick_sw_pad.Po + -rm -f ./$(DEPDIR)/pcem-joystick_tm_fcs.Po + -rm -f ./$(DEPDIR)/pcem-keyboard.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_amstrad.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_at.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_olim24.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_pcjr.Po + -rm -f ./$(DEPDIR)/pcem-keyboard_xt.Po + -rm -f ./$(DEPDIR)/pcem-laserxt.Po + -rm -f ./$(DEPDIR)/pcem-lpt.Po + -rm -f ./$(DEPDIR)/pcem-lpt_dac.Po + -rm -f ./$(DEPDIR)/pcem-lpt_dss.Po + -rm -f ./$(DEPDIR)/pcem-mca.Po + -rm -f ./$(DEPDIR)/pcem-mcr.Po + -rm -f ./$(DEPDIR)/pcem-mem.Po + -rm -f ./$(DEPDIR)/pcem-mem_bios.Po + -rm -f ./$(DEPDIR)/pcem-mfm_at.Po + -rm -f ./$(DEPDIR)/pcem-mfm_xebec.Po + -rm -f ./$(DEPDIR)/pcem-midi_alsa.Po + -rm -f ./$(DEPDIR)/pcem-model.Po + -rm -f ./$(DEPDIR)/pcem-mouse.Po + -rm -f ./$(DEPDIR)/pcem-mouse_msystems.Po + -rm -f ./$(DEPDIR)/pcem-mouse_ps2.Po + -rm -f ./$(DEPDIR)/pcem-mouse_serial.Po + -rm -f ./$(DEPDIR)/pcem-ne2000.Po + -rm -f ./$(DEPDIR)/pcem-neat.Po + -rm -f ./$(DEPDIR)/pcem-nethandler.Po + -rm -f ./$(DEPDIR)/pcem-nmi.Po + -rm -f ./$(DEPDIR)/pcem-nvr.Po + -rm -f ./$(DEPDIR)/pcem-nvr_tc8521.Po + -rm -f ./$(DEPDIR)/pcem-olivetti_m24.Po + -rm -f ./$(DEPDIR)/pcem-opti495.Po + -rm -f ./$(DEPDIR)/pcem-paths.Po + -rm -f ./$(DEPDIR)/pcem-pc.Po + -rm -f ./$(DEPDIR)/pcem-pc87306.Po + -rm -f ./$(DEPDIR)/pcem-pci.Po + -rm -f ./$(DEPDIR)/pcem-pic.Po + -rm -f ./$(DEPDIR)/pcem-piix.Po + -rm -f ./$(DEPDIR)/pcem-pit.Po + -rm -f ./$(DEPDIR)/pcem-ppi.Po + -rm -f ./$(DEPDIR)/pcem-ps1.Po + -rm -f ./$(DEPDIR)/pcem-ps2.Po + -rm -f ./$(DEPDIR)/pcem-ps2_mca.Po + -rm -f ./$(DEPDIR)/pcem-ps2_nvr.Po + -rm -f ./$(DEPDIR)/pcem-rom.Po + -rm -f ./$(DEPDIR)/pcem-rtc.Po + -rm -f ./$(DEPDIR)/pcem-rtc_tc8521.Po + -rm -f ./$(DEPDIR)/pcem-scat.Po + -rm -f ./$(DEPDIR)/pcem-scsi.Po + -rm -f ./$(DEPDIR)/pcem-scsi_53c400.Po + -rm -f ./$(DEPDIR)/pcem-scsi_aha1540.Po + -rm -f ./$(DEPDIR)/pcem-scsi_cd.Po + -rm -f ./$(DEPDIR)/pcem-scsi_hd.Po + -rm -f ./$(DEPDIR)/pcem-scsi_zip.Po + -rm -f ./$(DEPDIR)/pcem-serial.Po + -rm -f ./$(DEPDIR)/pcem-sio.Po + -rm -f ./$(DEPDIR)/pcem-sis496.Po + -rm -f ./$(DEPDIR)/pcem-sl82c460.Po + -rm -f ./$(DEPDIR)/pcem-sound.Po + -rm -f ./$(DEPDIR)/pcem-sound_ad1848.Po + -rm -f ./$(DEPDIR)/pcem-sound_adlib.Po + -rm -f ./$(DEPDIR)/pcem-sound_adlibgold.Po + -rm -f ./$(DEPDIR)/pcem-sound_audiopci.Po + -rm -f ./$(DEPDIR)/pcem-sound_cms.Po + -rm -f ./$(DEPDIR)/pcem-sound_dbopl.Po + -rm -f ./$(DEPDIR)/pcem-sound_emu8k.Po + -rm -f ./$(DEPDIR)/pcem-sound_gus.Po + -rm -f ./$(DEPDIR)/pcem-sound_mpu401_uart.Po + -rm -f ./$(DEPDIR)/pcem-sound_opl.Po + -rm -f ./$(DEPDIR)/pcem-sound_pas16.Po + -rm -f ./$(DEPDIR)/pcem-sound_ps1.Po + -rm -f ./$(DEPDIR)/pcem-sound_pssj.Po + -rm -f ./$(DEPDIR)/pcem-sound_resid.Po + -rm -f ./$(DEPDIR)/pcem-sound_sb.Po + -rm -f ./$(DEPDIR)/pcem-sound_sb_dsp.Po + -rm -f ./$(DEPDIR)/pcem-sound_sn76489.Po + -rm -f ./$(DEPDIR)/pcem-sound_speaker.Po + -rm -f ./$(DEPDIR)/pcem-sound_ssi2001.Po + -rm -f ./$(DEPDIR)/pcem-sound_wss.Po + -rm -f ./$(DEPDIR)/pcem-sound_ym7128.Po + -rm -f ./$(DEPDIR)/pcem-soundopenal.Po + -rm -f ./$(DEPDIR)/pcem-t1000.Po + -rm -f ./$(DEPDIR)/pcem-t3100e.Po + -rm -f ./$(DEPDIR)/pcem-tandy_eeprom.Po + -rm -f ./$(DEPDIR)/pcem-tandy_rom.Po + -rm -f ./$(DEPDIR)/pcem-timer.Po + -rm -f ./$(DEPDIR)/pcem-um8669f.Po + -rm -f ./$(DEPDIR)/pcem-um8881f.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati18800.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati28800.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati68860_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati_eeprom.Po + -rm -f ./$(DEPDIR)/pcem-vid_ati_mach64.Po + -rm -f ./$(DEPDIR)/pcem-vid_cga.Po + -rm -f ./$(DEPDIR)/pcem-vid_cl5429.Po + -rm -f ./$(DEPDIR)/pcem-vid_colorplus.Po + -rm -f ./$(DEPDIR)/pcem-vid_compaq_cga.Po + -rm -f ./$(DEPDIR)/pcem-vid_ega.Po + -rm -f ./$(DEPDIR)/pcem-vid_et4000.Po + -rm -f ./$(DEPDIR)/pcem-vid_et4000w32.Po + -rm -f ./$(DEPDIR)/pcem-vid_genius.Po + -rm -f ./$(DEPDIR)/pcem-vid_hercules.Po + -rm -f ./$(DEPDIR)/pcem-vid_icd2061.Po + -rm -f ./$(DEPDIR)/pcem-vid_ics2595.Po + -rm -f ./$(DEPDIR)/pcem-vid_incolor.Po + -rm -f ./$(DEPDIR)/pcem-vid_mda.Po + -rm -f ./$(DEPDIR)/pcem-vid_olivetti_m24.Po + -rm -f ./$(DEPDIR)/pcem-vid_oti037.Po + -rm -f ./$(DEPDIR)/pcem-vid_oti067.Po + -rm -f ./$(DEPDIR)/pcem-vid_paradise.Po + -rm -f ./$(DEPDIR)/pcem-vid_pc1512.Po + -rm -f ./$(DEPDIR)/pcem-vid_pc1640.Po + -rm -f ./$(DEPDIR)/pcem-vid_pc200.Po + -rm -f ./$(DEPDIR)/pcem-vid_pcjr.Po + -rm -f ./$(DEPDIR)/pcem-vid_ps1_svga.Po + -rm -f ./$(DEPDIR)/pcem-vid_s3.Po + -rm -f ./$(DEPDIR)/pcem-vid_s3_virge.Po + -rm -f ./$(DEPDIR)/pcem-vid_sdac_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_stg_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_svga.Po + -rm -f ./$(DEPDIR)/pcem-vid_svga_render.Po + -rm -f ./$(DEPDIR)/pcem-vid_t1000.Po + -rm -f ./$(DEPDIR)/pcem-vid_t3100e.Po + -rm -f ./$(DEPDIR)/pcem-vid_tandy.Po + -rm -f ./$(DEPDIR)/pcem-vid_tandysl.Po + -rm -f ./$(DEPDIR)/pcem-vid_tgui9440.Po + -rm -f ./$(DEPDIR)/pcem-vid_tkd8001_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_tvga.Po + -rm -f ./$(DEPDIR)/pcem-vid_unk_ramdac.Po + -rm -f ./$(DEPDIR)/pcem-vid_vga.Po + -rm -f ./$(DEPDIR)/pcem-vid_voodoo.Po + -rm -f ./$(DEPDIR)/pcem-vid_wy700.Po + -rm -f ./$(DEPDIR)/pcem-video.Po + -rm -f ./$(DEPDIR)/pcem-wd76c10.Po + -rm -f ./$(DEPDIR)/pcem-wx-app.Po + -rm -f ./$(DEPDIR)/pcem-wx-common.Po + -rm -f ./$(DEPDIR)/pcem-wx-config.Po + -rm -f ./$(DEPDIR)/pcem-wx-config_sel.Po + -rm -f ./$(DEPDIR)/pcem-wx-createdisc.Po + -rm -f ./$(DEPDIR)/pcem-wx-deviceconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-dialogbox.Po + -rm -f ./$(DEPDIR)/pcem-wx-glslp-parser.Po + -rm -f ./$(DEPDIR)/pcem-wx-hostconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-joystickconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-main.Po + -rm -f ./$(DEPDIR)/pcem-wx-resources.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-display-win.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-display.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-joystick.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-keyboard.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-midi.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-mouse.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-status.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-video-gl3.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-video-renderer.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2-video.Po + -rm -f ./$(DEPDIR)/pcem-wx-sdl2.Po + -rm -f ./$(DEPDIR)/pcem-wx-shader_man.Po + -rm -f ./$(DEPDIR)/pcem-wx-shaderconfig.Po + -rm -f ./$(DEPDIR)/pcem-wx-status.Po + -rm -f ./$(DEPDIR)/pcem-wx-thread.Po + -rm -f ./$(DEPDIR)/pcem-wx-utils.Po + -rm -f ./$(DEPDIR)/pcem-x86seg.Po + -rm -f ./$(DEPDIR)/pcem-x87.Po + -rm -f ./$(DEPDIR)/pcem-xi8088.Po + -rm -f ./$(DEPDIR)/pcem-xtide.Po + -rm -f dosbox/$(DEPDIR)/pcem-cdrom_image.Po + -rm -f dosbox/$(DEPDIR)/pcem-dbopl.Po + -rm -f dosbox/$(DEPDIR)/pcem-nukedopl.Po + -rm -f dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po + -rm -f resid-fp/$(DEPDIR)/pcem-convolve-sse.Po + -rm -f resid-fp/$(DEPDIR)/pcem-convolve.Po + -rm -f resid-fp/$(DEPDIR)/pcem-envelope.Po + -rm -f resid-fp/$(DEPDIR)/pcem-extfilt.Po + -rm -f resid-fp/$(DEPDIR)/pcem-filter.Po + -rm -f resid-fp/$(DEPDIR)/pcem-pot.Po + -rm -f resid-fp/$(DEPDIR)/pcem-sid.Po + -rm -f resid-fp/$(DEPDIR)/pcem-voice.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581_PST.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581_PS_.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581_P_T.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave6581__ST.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580_PST.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580_PS_.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580_P_T.Po + -rm -f resid-fp/$(DEPDIR)/pcem-wave8580__ST.Po + -rm -f slirp/$(DEPDIR)/pcem-bootp.Po + -rm -f slirp/$(DEPDIR)/pcem-cksum.Po + -rm -f slirp/$(DEPDIR)/pcem-debug.Po + -rm -f slirp/$(DEPDIR)/pcem-if.Po + -rm -f slirp/$(DEPDIR)/pcem-ip_icmp.Po + -rm -f slirp/$(DEPDIR)/pcem-ip_input.Po + -rm -f slirp/$(DEPDIR)/pcem-ip_output.Po + -rm -f slirp/$(DEPDIR)/pcem-mbuf.Po + -rm -f slirp/$(DEPDIR)/pcem-misc.Po + -rm -f slirp/$(DEPDIR)/pcem-queue.Po + -rm -f slirp/$(DEPDIR)/pcem-sbuf.Po + -rm -f slirp/$(DEPDIR)/pcem-slirp.Po + -rm -f slirp/$(DEPDIR)/pcem-socket.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_input.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_output.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_subr.Po + -rm -f slirp/$(DEPDIR)/pcem-tcp_timer.Po + -rm -f slirp/$(DEPDIR)/pcem-tftp.Po + -rm -f slirp/$(DEPDIR)/pcem-udp.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -4961,7 +5847,7 @@ uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ diff --git a/src/codegen.c b/src/codegen.c index 8256ab2..7e0dc9f 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -2,6 +2,13 @@ #include "x86_ops.h" #include "mem.h" #include "codegen.h" +#include "x86.h" + +#include "codegen_backend.h" +#include "codegen_ir.h" + +codeblock_t *codeblock; +codeblock_t **codeblock_hash; void (*codegen_timing_start)(); void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); @@ -19,3 +26,39 @@ void codegen_timing_set(codegen_timing_t *timing) } int codegen_in_recompile; + + +void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +{ + codeblock_t *block = &codeblock[block_current]; + ir_data_t *ir = codegen_get_ir_data(); + uint32_t op_pc = new_pc; + OpFn *op_table = x86_dynarec_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + uint32_t op_32 = use32; + + + //pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + + uop_STORE_PTR_IMM(ir, &cpu_state.pc, op_pc); + uop_STORE_PTR_IMM(ir, &cpu_state.oldpc, old_pc); + uop_STORE_PTR_IMM(ir, &cpu_state.op32, op_32); + uop_STORE_PTR_IMM(ir, &cpu_state.ea_seg, (uintptr_t)&_ds); + uop_STORE_PTR_IMM_8(ir, &cpu_state.ssegs, 0); + uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); + uop_CALL_INSTRUCTION_FUNC(ir, op); + + //codegen_block_ins++; + + block->ins++; + + if (block->ins >= 50) + CPU_BLOCK_END(); + +// addbyte(0xE8); /*CALL*/ +// addlong(((uint8_t *)codegen_debug - (uint8_t *)(&block->data[block_pos + 4]))); + + codegen_endpc = (cs + cpu_state.pc) + 8; +} diff --git a/src/codegen.h b/src/codegen.h index c5ad1ed..def016c 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -4,14 +4,6 @@ #include "mem.h" #include "x86_ops.h" -#ifdef __amd64__ -#include "codegen_x86-64.h" -#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 -#include "codegen_x86.h" -#else -#error Dynamic recompiler not implemented on your platform -#endif - /*Handling self-modifying code (of which there is a lot on x86) : PCem tracks a 'dirty mask' for each physical page, in which each bit @@ -37,6 +29,9 @@ same page). */ +/*Hack until better memory management written*/ +#define BLOCK_DATA_SIZE 0x10000 + typedef struct codeblock_t { uint64_t page_mask, page_mask2; @@ -66,7 +61,7 @@ typedef struct codeblock_t uint32_t status; uint32_t flags; - uint8_t data[2048]; + uint8_t data[BLOCK_DATA_SIZE]; } codeblock_t; /*Code block uses FPU*/ @@ -311,45 +306,6 @@ extern int block_pos; #define CPU_BLOCK_END() cpu_block_end = 1 -static inline void addbyte(uint8_t val) -{ - codeblock[block_current].data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addword(uint16_t val) -{ - *(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addlong(uint32_t val) -{ - *(uint32_t *)&codeblock[block_current].data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addquad(uint64_t val) -{ - *(uint64_t *)&codeblock[block_current].data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; diff --git a/src/codegen_backend.c b/src/codegen_backend.c new file mode 100644 index 0000000..a6ece39 --- /dev/null +++ b/src/codegen_backend.c @@ -0,0 +1,416 @@ +#include +#include "ibm.h" +#include "cpu.h" +#include "x86.h" +#include "x86_flags.h" +#include "x86_ops.h" +#include "x87.h" +#include "mem.h" + +#include "386_common.h" + +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_ir.h" + +int codegen_flat_ds, codegen_flat_ss; +int mmx_ebx_ecx_loaded; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_mmx_entered = 0; +int codegen_fpu_loaded_iq[8]; +x86seg *op_ea_seg; +int op_ssegs; +uint32_t op_old_pc; + +uint32_t recomp_page = -1; + +int block_current = 0; +static int block_num; +int block_pos; + +int cpu_recomp_flushes, cpu_recomp_flushes_latched; +int cpu_recomp_evicted, cpu_recomp_evicted_latched; +int cpu_recomp_reuse, cpu_recomp_reuse_latched; +int cpu_recomp_removed, cpu_recomp_removed_latched; + +uint32_t codegen_endpc; + +int codegen_block_cycles; +static int codegen_block_ins; +static int codegen_block_full_ins; + +static uint32_t last_op32; +static x86seg *last_ea_seg; +static int last_ssegs; + + +void codegen_init() +{ + codegen_backend_init(); +} + +void codegen_reset() +{ + int c; + + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + mem_reset_page_blocks(); + + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; +} + +void dump_block() +{ +/* codeblock_t *block = pages[0x119000 >> 12].block; + + pclog("dump_block:\n"); + while (block) + { + uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); + uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); + pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); + if (!block->pc) + fatal("Dead PC=0\n"); + + block = block->next; + } + pclog("dump_block done\n");*/ +} + +static void add_to_block_list(codeblock_t *block) +{ + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + + if (!block->page_mask) + fatal("add_to_block_list - mask = 0\n"); + + if (block_prev) + { + block->next = block_prev; + block_prev->prev = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } + else + { + block->next = NULL; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } + + if (block->next) + { + if (block->next->pc == BLOCK_PC_INVALID) + fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); + } + + if (block->page_mask2) + { + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + + if (block_prev) + { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + } + else + { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + } + } +} + +static void remove_from_block_list(codeblock_t *block, uint32_t pc) +{ + if (!block->page_mask) + return; + + if (block->prev) + { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } + else + { + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; + if (block->next) + block->next->prev = NULL; + else + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) + { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } + + if (block->prev_2) + { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } + else + { +// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } +} + +static void delete_block(codeblock_t *block) +{ + uint32_t old_pc = block->pc; + + if (block == codeblock_hash[HASH(block->phys)]) + codeblock_hash[HASH(block->phys)] = NULL; + + if (block->pc == BLOCK_PC_INVALID) + fatal("Deleting deleted block\n"); + block->pc = BLOCK_PC_INVALID; + + codeblock_tree_delete(block); + remove_from_block_list(block, old_pc); +} + +void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; + + while (block) + { + if (mask & block->page_mask) + { + delete_block(block); + cpu_recomp_evicted++; + } + if (block == block->next) + fatal("Broken 1\n"); + block = block->next; + } + + block = page->block_2[(phys_addr >> 10) & 3]; + + while (block) + { + if (mask & block->page_mask2) + { + delete_block(block); + cpu_recomp_evicted++; + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; + } +} + +void codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; + + if (!page->block[(phys_addr >> 10) & 3]) + mem_flush_write_page(phys_addr, cs+cpu_state.pc); + + block_current = (block_current + 1) & BLOCK_MASK; + block = &codeblock[block_current]; + +// if (block->pc == 0xb00b4ff5) +// pclog("Init target block\n"); + if (block->pc != BLOCK_PC_INVALID) + { +// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); + delete_block(block); + cpu_recomp_reuse++; + } + block_num = HASH(phys_addr); + codeblock_hash[block_num] = &codeblock[block_current]; + + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->pnt = block_current; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + block->page_mask = 0; + block->flags = CODEBLOCK_STATIC_TOP; + block->status = cpu_cur_status; + + block->was_recompiled = 0; + + recomp_page = block->phys & ~0xfff; + + codeblock_tree_add(block); +} + +static ir_data_t *ir_data; + +ir_data_t *codegen_get_ir_data() +{ + return ir_data; +} + +void codegen_block_start_recompile(codeblock_t *block) +{ + page_t *page = &pages[block->phys >> 12]; + + if (!page->block[(block->phys >> 10) & 3]) + mem_flush_write_page(block->phys, cs+cpu_state.pc); + + block_num = HASH(block->phys); + block_current = block->pnt; + + if (block->pc != cs + cpu_state.pc || block->was_recompiled) + fatal("Recompile to used block!\n"); + + block->status = cpu_cur_status; + + cpu_block_end = 0; + +// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num); + + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; + + codegen_block_cycles = 0; + codegen_timing_block_start(); + + codegen_block_ins = 0; + codegen_block_full_ins = 0; + + recomp_page = block->phys & ~0xfff; + + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; + + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = + codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; + + block->TOP = cpu_state.TOP; + block->was_recompiled = 1; + + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); + + ir_data = codegen_ir_init(); +} + + +void codegen_block_remove() +{ + codeblock_t *block = &codeblock[block_current]; + + delete_block(block); + cpu_recomp_removed++; + + recomp_page = -1; +} + +void codegen_block_generate_end_mask() +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + + block->endpc = codegen_endpc; + + block->page_mask = 0; + start_pc = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; + +// pclog("block_end: %08x %08x\n", start_pc, end_pc); + for (; start_pc <= end_pc; start_pc++) + { + block->page_mask |= ((uint64_t)1 << start_pc); +// pclog(" %08x %llx\n", start_pc, block->page_mask); + } + + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0x3ff) + { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) + { + page_t *page_2 = &pages[block->phys_2 >> 12]; + + start_pc = 0; + end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t)1 << start_pc); + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; + + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) + mem_flush_write_page(block->phys_2, block->endpc); + + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) + { +// pclog(" next_2->pc=%08x\n", block->next_2->pc); + if (block->next_2->pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)block->next_2); + } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + } + } + +// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); + recomp_page = -1; +} + +void codegen_block_end() +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + + remove_from_block_list(block, block->pc); + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + codegen_block_generate_end_mask(); + add_to_block_list(block); +// pclog("End block %i\n", block_num); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; + + codegen_ir_compile(ir_data, block); +} + +void codegen_flush() +{ + return; +} diff --git a/src/codegen_backend.h b/src/codegen_backend.h new file mode 100644 index 0000000..f281b75 --- /dev/null +++ b/src/codegen_backend.h @@ -0,0 +1,65 @@ +//#ifdef __amd64__ +//#include "codegen_x86-64.h" +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 +#include "codegen_backend_x86.h" +#elif defined __amd64__ +#include "codegen_backend_x86-64.h" +#elif defined __ARM_EABI__ +#include "codegen_backend_arm.h" +#elif defined __aarch64__ +#include "codegen_backend_arm64.h" +#else +#error Dynamic recompiler not implemented on your platform +#endif + +void codegen_backend_init(); +void codegen_backend_prologue(codeblock_t *block); +void codegen_backend_epilogue(codeblock_t *block); + +static inline void addbyte(uint8_t val) +{ + codeblock[block_current].data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + { + CPU_BLOCK_END(); + } +} + +static inline void addword(uint16_t val) +{ + *(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) + { + CPU_BLOCK_END(); + } +} + +static inline void addlong(uint32_t val) +{ + *(uint32_t *)&codeblock[block_current].data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + CPU_BLOCK_END(); + } +} + +static inline void addquad(uint64_t val) +{ + *(uint64_t *)&codeblock[block_current].data[block_pos] = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) + { + CPU_BLOCK_END(); + } +} + +struct ir_data_t; +struct uop_t; + +struct ir_data_t *codegen_get_ir_data(); + +typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop); + +extern const uOpFn uop_handlers[]; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c new file mode 100644 index 0000000..9f0be91 --- /dev/null +++ b/src/codegen_backend_arm.c @@ -0,0 +1,101 @@ +#ifdef __ARM_EABI__ + +#include +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm_defs.h" +#include "x86.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +void codegen_backend_init() +{ + int c; +#if defined(__linux__) || defined(__APPLE__) + void *start; + size_t len; + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); +#endif + +#if defined WIN32 || defined _WIN32 || defined _WIN32 + codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); +#endif + if (!codeblock) + fatal("codeblock failed to alloc - %i\n", (BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + + memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; + +#if defined(__linux__) || defined(__APPLE__) + start = (void *)((long)codeblock & pagemask); + len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + perror("mprotect"); + exit(-1); + } +#endif +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); +} + +/*R11 - literal pool + R10 - cpu_state*/ +void codegen_backend_prologue(codeblock_t *block) +{ + int offset; + + codegen_reset_literal_pool(block); + + block_pos = 0; + + block_pos = BLOCK_GPF_OFFSET; + host_arm_MOV_IMM(block, REG_R0, 0); + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_call(block, x86gpf); + while (block_pos != BLOCK_EXIT_OFFSET) + host_arm_nop(block); + + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); + while (block_pos != BLOCK_START) + host_arm_nop(block); + + /*Entry code*/ + + host_arm_STMDB_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_LR); + host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET); + host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START); + offset = add_literal(block, (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_CPUSTATE, REG_R11, offset); +} + +void codegen_backend_epilogue(codeblock_t *block) +{ + host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); + + if (block_pos > ARM_LITERAL_POOL_OFFSET) + fatal("Over limit!\n"); + + + + __clear_cache(&block->data[0], &block->data[block_pos]); +} + +#endif diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h new file mode 100644 index 0000000..43b3fad --- /dev/null +++ b/src/codegen_backend_arm.h @@ -0,0 +1,33 @@ +#define BLOCK_SIZE 0x1000 +#define BLOCK_MASK 0x0fff +#define BLOCK_START 32 + +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff + +#define HASH(l) ((l) & 0x1ffff) + +/*Hack until better memory management written*/ +/*#define BLOCK_EXIT_OFFSET 0x7f0*/ + +#define BLOCK_GPF_OFFSET 0 +#define BLOCK_EXIT_OFFSET 16 + +#define ARM_LITERAL_POOL_OFFSET 0xf000 + +/*#define BLOCK_MAX 1720*/ +#define BLOCK_MAX 65208 + + +void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); +void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset); +void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm); +void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); +void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); + +void host_arm_call(codeblock_t *block, void *dst_addr); +void host_arm_nop(codeblock_t *block); + +void codegen_reset_literal_pool(codeblock_t *block); +int add_literal(codeblock_t *block, uint32_t data); diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c new file mode 100644 index 0000000..5fb6115 --- /dev/null +++ b/src/codegen_backend_arm64.c @@ -0,0 +1,115 @@ +#ifdef __aarch64__ + +#include +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm64_defs.h" +#include "x86.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +void codegen_backend_init() +{ + int c; +#if defined(__linux__) || defined(__APPLE__) + void *start; + size_t len; + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); +#endif + +#if defined WIN32 || defined _WIN32 || defined _WIN32 + codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); +#endif + if (!codeblock) + fatal("codeblock failed to alloc - %i\n", (BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + + memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; + +#if defined(__linux__) || defined(__APPLE__) + start = (void *)((long)codeblock & pagemask); + len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + perror("mprotect"); + exit(-1); + } +#endif +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); +} + +/*R11 - literal pool + R10 - cpu_state*/ +void codegen_backend_prologue(codeblock_t *block) +{ + int offset; + + codegen_reset_literal_pool(block); + + block_pos = 0; + + block_pos = BLOCK_GPF_OFFSET; + host_arm64_mov_imm(block, REG_ARG0, 0); + host_arm64_mov_imm(block, REG_ARG1, 0); + host_arm64_call(block, x86gpf); + while (block_pos != BLOCK_EXIT_OFFSET) + host_arm64_NOP(block); + + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_RET(block, REG_X30); + + while (block_pos != BLOCK_START) + host_arm64_NOP(block); + + /*Entry code*/ + + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -16); + + offset = add_literal_q(block, (uintptr_t)&cpu_state); + host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); +} + +void codegen_backend_epilogue(codeblock_t *block) +{ + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_RET(block, REG_X30); + + if (block_pos > ARM_LITERAL_POOL_OFFSET) + fatal("Over limit!\n"); + + + + __clear_cache(&block->data[0], &block->data[block_pos]); +} + +#endif diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h new file mode 100644 index 0000000..6943eb6 --- /dev/null +++ b/src/codegen_backend_arm64.h @@ -0,0 +1,40 @@ +#define BLOCK_SIZE 0x1000 +#define BLOCK_MASK 0x0fff +#define BLOCK_START 64 + +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff + +#define HASH(l) ((l) & 0x1ffff) + +/*Hack until better memory management written*/ +/*#define BLOCK_EXIT_OFFSET 0x7f0*/ + +#define BLOCK_GPF_OFFSET 0 +#define BLOCK_EXIT_OFFSET 32 + +#define ARM_LITERAL_POOL_OFFSET 0xf000 + +/*#define BLOCK_MAX 1720*/ +#define BLOCK_MAX 65208 + + +void host_arm64_BLR(codeblock_t *block, int addr_reg); +void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); +void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data); +void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); +void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); +void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset); +void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); +void host_arm64_NOP(codeblock_t *block); +void host_arm64_RET(codeblock_t *block, int reg); +void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); +void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); + +void host_arm64_call(codeblock_t *block, void *dst_addr); +void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); + +void codegen_reset_literal_pool(codeblock_t *block); +int add_literal(codeblock_t *block, uint32_t data); +int add_literal_q(codeblock_t *block, uint64_t data); diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h new file mode 100644 index 0000000..d70990a --- /dev/null +++ b/src/codegen_backend_arm64_defs.h @@ -0,0 +1,72 @@ +#define REG_W0 0 +#define REG_W1 1 +#define REG_W2 2 +#define REG_W3 3 +#define REG_W4 4 +#define REG_W5 5 +#define REG_W6 6 +#define REG_W7 7 +#define REG_W8 8 +#define REG_W9 9 +#define REG_W10 10 +#define REG_W11 11 +#define REG_W12 12 +#define REG_W13 13 +#define REG_W14 14 +#define REG_W15 15 +#define REG_W16 16 +#define REG_W17 17 +#define REG_W18 18 +#define REG_W19 19 +#define REG_W20 20 +#define REG_W21 21 +#define REG_W22 22 +#define REG_W23 23 +#define REG_W24 24 +#define REG_W25 25 +#define REG_W26 26 +#define REG_W27 27 +#define REG_W28 28 +#define REG_W29 29 +#define REG_W30 30 + +#define REG_X0 0 +#define REG_X1 1 +#define REG_X2 2 +#define REG_X3 3 +#define REG_X4 4 +#define REG_X5 5 +#define REG_X6 6 +#define REG_X7 7 +#define REG_X8 8 +#define REG_X9 9 +#define REG_X10 10 +#define REG_X11 11 +#define REG_X12 12 +#define REG_X13 13 +#define REG_X14 14 +#define REG_X15 15 +#define REG_X16 16 +#define REG_X17 17 +#define REG_X18 18 +#define REG_X19 19 +#define REG_X20 20 +#define REG_X21 21 +#define REG_X22 22 +#define REG_X23 23 +#define REG_X24 24 +#define REG_X25 25 +#define REG_X26 26 +#define REG_X27 27 +#define REG_X28 28 +#define REG_X29 29 +#define REG_X30 30 + +#define REG_SP 31 + +#define REG_ARG0 REG_X0 +#define REG_ARG1 REG_X1 +#define REG_ARG2 REG_X2 +#define REG_ARG3 REG_X3 + +#define REG_CPUSTATE REG_X29 \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c new file mode 100644 index 0000000..ee29eb2 --- /dev/null +++ b/src/codegen_backend_arm64_uops.c @@ -0,0 +1,300 @@ +#ifdef __aarch64__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm64_defs.h" +#include "codegen_ir_defs.h" + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +#define Rt(x) (x) +#define Rd(x) (x) +#define Rn(x) ((x) << 5) +#define Rt2(x) ((x) << 10) + +#define DATA_OFFSET_UP (1 << 23) +#define DATA_OFFSET_DOWN (0 << 23) + +#define COND_SHIFT 28 +#define COND_NE (0x1 << COND_SHIFT) +#define COND_AL (0xe << COND_SHIFT) + +#define OPCODE_SHIFT 24 +#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) +#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) +#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) + +#define OPCODE_MOVK_W (0x0e5 << 23) +#define OPCODE_MOVZ_W (0x0a5 << 23) + +#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) +#define OPCODE_STP_PREIDX_X (0x2a6 << 22) +#define OPCODE_STR_IMM_W (0x2e4 << 22) +#define OPCODE_STRB_IMM (0x0e4 << 22) + +#define OPCODE_BLR (0xd63f0000) +#define OPCODE_NOP (0xd503201f) +#define OPCODE_RET (0xd65f0000) + +#define MOV_WIDE_HW(hw) (hw << 21) + +#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) +#define IMM16(imm_data) (imm_data << 5) + +#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) + +#define OFFSET12_B(offset) (offset << 10) +#define OFFSET12_W(offset) ((offset >> 2) << 10) + +static int literal_offset = 0; +void codegen_reset_literal_pool(codeblock_t *block) +{ + literal_offset = 0; +} + +/*Returns true if offset fits into 19 bits*/ +static int offset_is_19bit(int offset) +{ + if (offset >= (1 << (18+2))) + return 0; + if (offset < -(1 << (18+2))) + return 0; + return 1; +} + +#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) +#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) +#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) + +int add_literal(codeblock_t *block, uint32_t data) +{ + if (literal_offset >= 4096) + fatal("add_literal - literal pool full\n"); + + *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; + + literal_offset += 4; + + return literal_offset - 4; +} + +int add_literal_q(codeblock_t *block, uint64_t data) +{ + if (literal_offset & 4) + literal_offset += 4; + + if (literal_offset >= 4096-4) + fatal("add_literal - literal pool full\n"); + + *(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; + + literal_offset += 8; + + return literal_offset - 8; +} + +static inline int imm_is_imm16(uint32_t imm_data) +{ + if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) + return 1; + return 0; +} + + +void host_arm64_BLR(codeblock_t *block, int addr_reg) +{ + codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); +} + +void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) +{ + int offset = dest - (uintptr_t)&block->data[block_pos]; + if (!offset_is_19bit(offset)) + fatal("host_arm64_CBNZ - offset out of range %x\n", offset); + codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); +} + +void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +{ + if (!in_range7_x(offset)) + fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); +} + +void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) +{ + int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; + + if (!offset_is_19bit(offset)) + fatal("host_arm64_CBNZ - offset out of range %x\n", offset); + + codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg)); +} +void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset) +{ + int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; + + if (!offset_is_19bit(offset)) + fatal("host_arm64_CBNZ - offset out of range %x\n", offset); + + codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg)); +} + +void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + int hw; + + if (!imm_is_imm16(imm_data)) + fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); + + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; + + codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); +} + +void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + int hw; + + if (!imm_is_imm16(imm_data)) + fatal("MOVK_IMM - imm not representable %08x\n", imm_data); + + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; + + codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); +} + +void host_arm64_NOP(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_NOP); +} + +void host_arm64_RET(codeblock_t *block, int reg) +{ + codegen_addlong(block, OPCODE_RET | Rn(reg)); +} + +void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +{ + if (!in_range7_x(offset)) + fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); +} + +void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_w(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); +} +void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_b(offset)) + fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); +} + + +void host_arm64_call(codeblock_t *block, void *dst_addr) +{ + int offset = add_literal_q(block, (uintptr_t)dst_addr); + host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_BLR(block, REG_X16); +} + +void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) +{ + if (imm_is_imm16(imm_data)) + host_arm64_MOVZ_IMM(block, reg, imm_data); + else + { + host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); + } +} + + +static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm64_call(block, uop->p); + host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); + + return 0; +} +static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, REG_ARG1, uop->imm_data); + + return 0; +} +static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, REG_ARG2, uop->imm_data); + + return 0; +} +static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, REG_ARG3, uop->imm_data); + + return 0; +} + +static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, REG_W16, uop->imm_data); + + if (in_range12_w((uintptr_t)uop->p - (uintptr_t)&cpu_state)) + host_arm64_STR_IMM_W(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); + + return 0; +} +static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, REG_W16, uop->imm_data); + + if (in_range12_b((uintptr_t)uop->p - (uintptr_t)&cpu_state)) + host_arm64_STRB_IMM(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); + + return 0; +} + +const uOpFn uop_handlers[UOP_MAX] = +{ + [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 +}; + +#endif diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h new file mode 100644 index 0000000..a9253ab --- /dev/null +++ b/src/codegen_backend_arm_defs.h @@ -0,0 +1,44 @@ +#define REG_R0 0 +#define REG_R1 1 +#define REG_R2 2 +#define REG_R3 3 +#define REG_R4 4 +#define REG_R5 5 +#define REG_R6 6 +#define REG_R7 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_SP 13 +#define REG_LR 14 +#define REG_PC 15 + +#define REG_ARG0 REG_R0 +#define REG_ARG1 REG_R1 +#define REG_ARG2 REG_R2 +#define REG_ARG3 REG_R3 + +#define REG_CPUSTATE REG_R10 +#define REG_LITERAL REG_R11 + +#define REG_MASK_R0 (1 << REG_R0) +#define REG_MASK_R1 (1 << REG_R1) +#define REG_MASK_R2 (1 << REG_R2) +#define REG_MASK_R3 (1 << REG_R3) +#define REG_MASK_R4 (1 << REG_R4) +#define REG_MASK_R5 (1 << REG_R5) +#define REG_MASK_R6 (1 << REG_R6) +#define REG_MASK_R7 (1 << REG_R7) +#define REG_MASK_R8 (1 << REG_R8) +#define REG_MASK_R9 (1 << REG_R9) +#define REG_MASK_R10 (1 << REG_R10) +#define REG_MASK_R11 (1 << REG_R11) +#define REG_MASK_R12 (1 << REG_R12) +#define REG_MASK_SP (1 << REG_SP) +#define REG_MASK_LR (1 << REG_LR) +#define REG_MASK_PC (1 << REG_PC) + +#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \ + REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c new file mode 100644 index 0000000..5152fe4 --- /dev/null +++ b/src/codegen_backend_arm_uops.c @@ -0,0 +1,314 @@ +#ifdef __ARM_EABI__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm_defs.h" +#include "codegen_ir_defs.h" + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +#define Rm(x) (x) +#define Rd(x) ((x) << 12) +#define Rn(x) ((x) << 16) + +#define DATA_OFFSET_UP (1 << 23) +#define DATA_OFFSET_DOWN (0 << 23) + +#define COND_SHIFT 28 +#define COND_NE (0x1 << COND_SHIFT) +#define COND_AL (0xe << COND_SHIFT) + +#define OPCODE_SHIFT 20 +#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) +#define OPCODE_B (0xa0 << OPCODE_SHIFT) +#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) +#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) +#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) +#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) +#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) +#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) +#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) +#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) + +#define OPCODE_BLX 0xe12fff30 + +#define B_OFFSET(x) (((x) >> 2) & 0xffffff) + +static int literal_offset = 0; +void codegen_reset_literal_pool(codeblock_t *block) +{ + literal_offset = 0; +} + +int add_literal(codeblock_t *block, uint32_t data) +{ + if (literal_offset >= 4096) + fatal("add_literal - literal pool full\n"); + + *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; + + literal_offset += 4; + + return literal_offset - 4; +} + + +static inline uint32_t arm_data_offset(int offset) +{ + if (offset < -0xffc || offset > 0xffc) + fatal("arm_data_offset out of range - %i\n", offset); + + if (offset >= 0) + return offset | DATA_OFFSET_UP; + return (-offset) | DATA_OFFSET_DOWN; +} + +static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) +{ + int shift = 0; +//pclog("get_arm_imm - imm_data=%08x\n", imm_data); + if (!(imm_data & 0xffff)) + { + shift += 16; + imm_data >>= 16; + } + if (!(imm_data & 0xff)) + { + shift += 8; + imm_data >>= 8; + } + if (!(imm_data & 0xf)) + { + shift += 4; + imm_data >>= 4; + } + if (!(imm_data & 0x3)) + { + shift += 2; + imm_data >>= 2; + } + if (imm_data > 0xff) /*Note - should handle rotation round the word*/ + return 0; +//pclog(" imm_data=%02x shift=%i\n", imm_data, shift); + *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); + return 1; +} + +static inline int in_range(void *addr, void *base) +{ + int diff = (uintptr_t)addr - (uintptr_t)base; + + if (diff < -4095 || diff > 4095) + return 0; + return 1; +} + +void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (!get_arm_imm(imm, &arm_imm)) + fatal("host_arm_ADD_IMM !check_arm_imm %08x\n", imm); + + codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); +} + +void host_arm_BLX(codeblock_t *block, int addr_reg) +{ + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); +} + +void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); + + codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); +} + +void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +{ + codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); +} + +void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); +} + +void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (!get_arm_imm(imm, &arm_imm)) + fatal("host_arm_MOV_IMM !check_arm_imm %08x\n", imm); + + codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); +} + +void host_arm_MOV_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg)); +} + +void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +{ + codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); +} + +void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); +} + +void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); +} + +void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (!get_arm_imm(imm, &arm_imm)) + fatal("host_arm_SUB_IMM !check_arm_imm %08x\n", imm); + + codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); +} + +void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) +{ + codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); +} + + +void host_arm_call(codeblock_t *block, void *dst_addr) +{ + int offset = add_literal(block, (uintptr_t)dst_addr); + host_arm_LDR_IMM(block, REG_R3, REG_LITERAL, offset); + host_arm_BLX(block, REG_R3); +} + +void host_arm_nop(codeblock_t *block) +{ + host_arm_MOV_REG(block, REG_R0, REG_R0); +} + +static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm_call(block, uop->p); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, REG_ARG0, REG_LITERAL, offset); + } + return 0; +} +static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, REG_ARG1, REG_LITERAL, offset); + } + return 0; +} +static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, REG_ARG2, REG_LITERAL, offset); + } + return 0; +} +static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, REG_ARG3, REG_LITERAL, offset); + } + return 0; +} + +static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, REG_R0, REG_LITERAL, offset); + } + if (in_range(uop->p, &cpu_state)) + host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); + + return 0; +} +static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + if (in_range(uop->p, &cpu_state)) + host_arm_STRB_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); + + return 0; +} + +const uOpFn uop_handlers[UOP_MAX] = +{ + [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 +}; + +#endif diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c new file mode 100644 index 0000000..e123823 --- /dev/null +++ b/src/codegen_backend_x86-64.c @@ -0,0 +1,156 @@ +#ifdef __amd64__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "x86.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +static void *mem_abrt_rout; + +void codegen_backend_init() +{ + int c; +#if defined(__linux__) || defined(__APPLE__) + void *start; + size_t len; + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); +#endif + +#if defined WIN32 || defined _WIN32 || defined _WIN32 + codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); +#endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + + memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; + +#if defined(__linux__) || defined(__APPLE__) + start = (void *)((long)codeblock & pagemask); + len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + perror("mprotect"); + exit(-1); + } +#endif +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); +} + +static inline void call(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + addbyte(0xE8); /*CALL*/ + addlong((uint32_t)diff); + } + else + { + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); + } +} + +void codegen_backend_prologue(codeblock_t *block) +{ + block_pos = 0; /*Entry code*/ + addbyte(0x53); /*PUSH RBX*/ + addbyte(0x55); /*PUSH RBP*/ + addbyte(0x56); /*PUSH RSI*/ + addbyte(0x57); /*PUSH RDI*/ + addbyte(0x41); /*PUSH R12*/ + addbyte(0x54); + addbyte(0x41); /*PUSH R13*/ + addbyte(0x55); + addbyte(0x41); /*PUSH R14*/ + addbyte(0x56); + addbyte(0x41); /*PUSH R15*/ + addbyte(0x57); + addbyte(0x48); /*SUBL $40,%rsp*/ + addbyte(0x83); + addbyte(0xEC); + addbyte(0x28); + addbyte(0x48); /*MOVL RBP, &cpu_state*/ + addbyte(0xBD); + addquad(((uintptr_t)&cpu_state) + 128); +} + +void codegen_backend_epilogue(codeblock_t *block) +{ + addbyte(0x48); /*ADDL $40,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x28); + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5d); /*POP RBP*/ + addbyte(0x5b); /*POP RDX*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); + + block_pos = BLOCK_GPF_OFFSET; +#if WIN64 + addbyte(0x48); /*XOR RCX, RCX*/ + addbyte(0x31); + addbyte(0xc9); + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); +#else + addbyte(0x48); /*XOR RDI, RDI*/ + addbyte(0x31); + addbyte(0xff); + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); +#endif + call(block, (uintptr_t)x86gpf); + while (block_pos < BLOCK_EXIT_OFFSET) + addbyte(0x90); /*NOP*/ + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x48); /*ADDL $40,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x28); + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5d); /*POP RBP*/ + addbyte(0x5b); /*POP RDX*/ + addbyte(0xC3); /*RET*/ +} + +#endif diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h new file mode 100644 index 0000000..6c0cfca --- /dev/null +++ b/src/codegen_backend_x86-64.h @@ -0,0 +1,16 @@ +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 + +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff + +#define HASH(l) ((l) & 0x1ffff) + +/*Hack until better memory management written*/ +#define BLOCK_EXIT_OFFSET 0xffe0 +/*#define BLOCK_EXIT_OFFSET 0x7f0*/ +#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) + +/*#define BLOCK_MAX 1720*/ +#define BLOCK_MAX 65208 diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h new file mode 100644 index 0000000..dcb9a58 --- /dev/null +++ b/src/codegen_backend_x86-64_defs.h @@ -0,0 +1,8 @@ +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 +#define REG_ESP 4 +#define REG_EBP 5 +#define REG_ESI 6 +#define REG_EDI 7 diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c new file mode 100644 index 0000000..f64636f --- /dev/null +++ b/src/codegen_backend_x86-64_uops.c @@ -0,0 +1,232 @@ +#ifdef __amd64__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_x86-64_defs.h" +#include "codegen_ir_defs.h" + +#define STACK_ARG0 (0) +#define STACK_ARG1 (4) +#define STACK_ARG2 (8) +#define STACK_ARG3 (12) + +static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +{ + block->data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte over! %i\n", block_pos); +// CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + block->data[block_pos++] = vald; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addword(codeblock_t *block, uint16_t val) +{ + *(uint16_t *)&block->data[block_pos] = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addquad(codeblock_t *block, uint64_t val) +{ + *(uint64_t *)&block->data[block_pos] = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void call(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + codegen_addbyte(block, 0xE8); /*CALL*/ + codegen_addlong(block, (uint32_t)diff); + } + else + { + codegen_addbyte2(block, 0x48, 0xb8); /*MOV RAX, func*/ + codegen_addquad(block, func); + codegen_addbyte2(block, 0xff, 0xd0); /*CALL RAX*/ + } +} + +static void host_x86_CALL(codeblock_t *block, void *p) +{ + call(block, (uintptr_t)p); +} + +static void host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + +static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addlong(block, imm_data); +} +static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addbyte(block, imm_data); +} + +static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + codegen_addbyte(block, 0xb8 | reg); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); +} + +static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + if (!offset) + { + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else if (offset >= -80 || offset < 0x80) + { + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } +} + +#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) + +static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} + +static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +{ + host_x86_CALL(block, uop->p); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ +#if WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); +#else + host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); +#endif + return 0; +} +static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ +#if WIN64 + host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data); +#else + host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data); +#endif + return 0; +} +static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2_IMM\n"); + return 0; +} +static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3_IMM\n"); + return 0; +} + +static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ + if (((uintptr_t)uop->p) >> 32) + fatal("STORE_PTR_IMM 64-bit addr\n"); + host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ + if (((uintptr_t)uop->p) >> 32) + fatal("STORE_PTR_IMM_8 64-bit addr\n"); + host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} + +const uOpFn uop_handlers[UOP_MAX] = +{ + [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 +}; + +#endif diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c new file mode 100644 index 0000000..01a27b2 --- /dev/null +++ b/src/codegen_backend_x86.c @@ -0,0 +1,121 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "x86.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +static void *mem_abrt_rout; + +void codegen_backend_init() +{ + int c; +#if defined(__linux__) || defined(__APPLE__) + void *start; + size_t len; + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); +#endif + +#if defined WIN32 || defined _WIN32 || defined _WIN32 + codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); +#endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + + memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; + +#if defined(__linux__) || defined(__APPLE__) + start = (void *)((long)codeblock & pagemask); + len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + perror("mprotect"); + exit(-1); + } +#endif +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); + + block_current = BLOCK_SIZE; + block_pos = 0; + mem_abrt_rout = &codeblock[block_current].data[block_pos]; + addbyte(0x83); /*ADDL $16+4,%esp*/ + addbyte(0xC4); + addbyte(0x10+4); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + + asm( + "fstcw %0\n" + : "=m" (cpu_state.old_npxc) + ); +} + +void codegen_backend_prologue(codeblock_t *block) +{ + block_pos = 0; /*Entry code*/ + addbyte(0x53); /*PUSH EBX*/ + addbyte(0x55); /*PUSH EBP*/ + addbyte(0x56); /*PUSH ESI*/ + addbyte(0x57); /*PUSH EDI*/ + addbyte(0x83); /*SUBL $16,%esp*/ + addbyte(0xEC); + addbyte(0x10); + addbyte(0xBD); /*MOVL EBP, &cpu_state*/ + addlong(((uintptr_t)&cpu_state) + 128); +} + +void codegen_backend_epilogue(codeblock_t *block) +{ + addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0xC4); + addbyte(0x10); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); + + block_pos = BLOCK_GPF_OFFSET; + addbyte(0xc7); /*MOV [ESP],0*/ + addbyte(0x04); + addbyte(0x24); + addlong(0); + addbyte(0xc7); /*MOV [ESP+4],0*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addlong(0); + addbyte(0xe8); /*CALL x86gpf*/ + addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0xC4); + addbyte(0x10); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ +} + +#endif diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h new file mode 100644 index 0000000..36361ec --- /dev/null +++ b/src/codegen_backend_x86.h @@ -0,0 +1,16 @@ +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 + +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff + +#define HASH(l) ((l) & 0x1ffff) + +/*Hack until better memory management written*/ +#define BLOCK_EXIT_OFFSET 0xfff0 +/*#define BLOCK_EXIT_OFFSET 0x7f0*/ +#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) + +/*#define BLOCK_MAX 1720*/ +#define BLOCK_MAX 65208 diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h new file mode 100644 index 0000000..dcb9a58 --- /dev/null +++ b/src/codegen_backend_x86_defs.h @@ -0,0 +1,8 @@ +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 +#define REG_ESP 4 +#define REG_EBP 5 +#define REG_ESI 6 +#define REG_EDI 7 diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c new file mode 100644 index 0000000..365382b --- /dev/null +++ b/src/codegen_backend_x86_uops.c @@ -0,0 +1,195 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_x86_defs.h" +#include "codegen_ir_defs.h" + +#define STACK_ARG0 (0) +#define STACK_ARG1 (4) +#define STACK_ARG2 (8) +#define STACK_ARG3 (12) + +static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +{ + block->data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte over! %i\n", block_pos); +// CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + block->data[block_pos++] = vald; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addword(codeblock_t *block, uint16_t val) +{ + *(uint16_t *)&block->data[block_pos] = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addquad(codeblock_t *block, uint64_t val) +{ + *(uint64_t *)&block->data[block_pos] = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static void host_x86_CALL(codeblock_t *block, void *p) +{ + codegen_addbyte(block, 0xe8); /*CALL*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + +static void host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + +static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addlong(block, imm_data); +} +static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addbyte(block, imm_data); +} + +static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + if (!offset) + { + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else if (offset >= -80 || offset < 0x80) + { + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } +} + +#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) + +static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} + +static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +{ + host_x86_CALL(block, uop->p); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); + return 0; +} +static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, uop->imm_data); + return 0; +} +static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_STACK_IMM(block, STACK_ARG2, uop->imm_data); + return 0; +} +static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_STACK_IMM(block, STACK_ARG3, uop->imm_data); + return 0; +} + +static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} + +const uOpFn uop_handlers[UOP_MAX] = +{ + [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 +}; + +#endif diff --git a/src/codegen_ir.c b/src/codegen_ir.c new file mode 100644 index 0000000..4f8e1b4 --- /dev/null +++ b/src/codegen_ir.c @@ -0,0 +1,34 @@ +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_ir.h" + +static ir_data_t ir_block; + +ir_data_t *codegen_ir_init() +{ + ir_block.wr_pos = 0; + //pclog("codegen_ir_init\n"); + + return &ir_block; +} + +void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) +{ + int c; + + codegen_backend_prologue(block); + + for (c = 0; c < ir->wr_pos; c++) + { + uop_t *uop = &ir->uops[c]; + + //pclog("uOP %i : %08x\n", c, uop->type); + + uop_handlers[uop->type & UOP_MASK](block, uop); + } + + codegen_backend_epilogue(block); + +// fatal("IR compilation complete\n"); +} diff --git a/src/codegen_ir.h b/src/codegen_ir.h new file mode 100644 index 0000000..aafeca6 --- /dev/null +++ b/src/codegen_ir.h @@ -0,0 +1,5 @@ +#include "codegen_ir_defs.h" + +ir_data_t *codegen_ir_init(); + +void codegen_ir_compile(ir_data_t *ir, codeblock_t *block); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h new file mode 100644 index 0000000..9293447 --- /dev/null +++ b/src/codegen_ir_defs.h @@ -0,0 +1,152 @@ +#ifndef _CODEGEN_IR_DEFS_ +#define _CODEGEN_IR_DEFS_ + +#define IREG_L (0 << 6) +#define IREG_W (1 << 6) +#define IREG_B (2 << 6) +#define IREG_BH (3 << 6) + +enum +{ + ireg_EAX = 0, + ireg_ECX = 1, + ireg_EDX = 2, + ireg_EBX = 3, + ireg_ESP = 4, + ireg_EBP = 5, + ireg_ESI = 6, + ireg_EDI = 7, + + ireg_flags_op = 8, + ireg_flags_reg = 9, + ireg_flags_op1 = 10, + ireg_flags_op2 = 11, + + ireg_flags_pc = 12, + ireg_flags_oldpc = 13, + + ireg_eaaddr = 14, + + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + ireg_temp0 = 16, + ireg_temp1 = 17, + ireg_temp2 = 18, + ireg_temp3 = 19 +}; + +#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8)) + +#define UOP_REG_UNUSED 0xffff + +/*uOP is a barrier. All previous uOPs must have completed before this one executes. + All registers must have been written back or discarded*/ +#define UOP_TYPE_BARRIER (1 << 31) + +/*uOP uses source and dest registers*/ +#define UOP_TYPE_PARAMS_REGS (1 << 28) +/*uOP uses pointer*/ +#define UOP_TYPE_PARAMS_POINTER (1 << 29) +/*uOP uses immediate data*/ +#define UOP_TYPE_PARAMS_IMM (1 << 30) + + + +#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00) +#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01) +#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02) +#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03) +#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08) +#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09) +#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a) +#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b) +#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) +#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) +#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) +#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) + +#define UOP_MAX 0x14 + +#define UOP_MASK 0xffff + +typedef struct uop_t +{ + uint32_t type; + uint16_t dest_reg_a; + uint16_t src_reg_a; + uint16_t src_reg_b; + uint16_t src_reg_c; + uint32_t imm_data; + void *p; +} uop_t; + +#define UOP_NR_MAX 4096 + +typedef struct ir_data_t +{ + uop_t uops[UOP_NR_MAX]; + int wr_pos; +} ir_data_t; + +static inline uop_t *uop_alloc(ir_data_t *ir) +{ + uop_t *uop; + + if (ir->wr_pos >= UOP_NR_MAX) + fatal("Exceeded uOP max\n"); + + uop = &ir->uops[ir->wr_pos++]; + + uop->dest_reg_a = UOP_REG_UNUSED; + uop->src_reg_a = UOP_REG_UNUSED; + uop->src_reg_b = UOP_REG_UNUSED; + uop->src_reg_c = UOP_REG_UNUSED; + + return uop; +} + +static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, uint16_t src_reg_a) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = src_reg_a; +} + +static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->imm_data = imm; +} + +static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->p = p; +} + +static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->p = p; + uop->imm_data = imm; +} + +#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) + +#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) + +#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) +#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) + +#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) +#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) + +#endif diff --git a/src/codegen_ops.c b/src/codegen_ops.c deleted file mode 100644 index 68da1ed..0000000 --- a/src/codegen_ops.c +++ /dev/null @@ -1,591 +0,0 @@ -#include "ibm.h" -#include "x86.h" -#include "x86_ops.h" -#include "x86_flags.h" -#include "x87.h" -#include "386_common.h" -#include "cpu.h" -#include "codegen.h" -#include "codegen_ops.h" - -#ifdef __amd64__ -#include "codegen_ops_x86-64.h" -#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 -#include "codegen_ops_x86.h" -#endif - -#include "codegen_ops_arith.h" -#include "codegen_ops_fpu.h" -#include "codegen_ops_jump.h" -#include "codegen_ops_logic.h" -#include "codegen_ops_misc.h" -#include "codegen_ops_mmx.h" -#include "codegen_ops_mov.h" -#include "codegen_ops_shift.h" -#include "codegen_ops_stack.h" -#include "codegen_ops_xchg.h" - -RecompOpFn recomp_opcodes[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16, -/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, -/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, - -/*40*/ ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, -/*50*/ ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL, -/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE, - -/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_w, ropMOV_seg_w, NULL, -/*90*/ ropNOP, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, - -/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES, ropLDS, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32, -/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, -/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, - -/*40*/ ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, -/*50*/ ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL, -/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE, - -/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_w_seg, ropLEA_l, ropMOV_seg_w, NULL, -/*90*/ ropNOP, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, - -/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES, ropLDS, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32 -}; - -RecompOpFn recomp_opcodes_0f[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_mm_l, ropMOVQ_mm_q, -/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm, - -/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, -/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, -/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, -}; - - -RecompOpFn recomp_opcodes_d8[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, -/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, -/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, - -/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, -/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, -/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, - -/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, -/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, -/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, - -/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, -/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, -/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, -/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, -/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, -/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, - -/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, -/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, -/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, - -/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, -/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, -/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, - -/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, -/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, -/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, -/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, -}; - -RecompOpFn recomp_opcodes_d9[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, - -/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, - -/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, - -/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, - -/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, - -/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, - -/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -RecompOpFn recomp_opcodes_da[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, -/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, -/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, -/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, - -/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, -/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, -/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, -/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, - -/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, -/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, -/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, -/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, -/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, -/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, -/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, - -/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, -/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, -/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, -/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, - -/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, -/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, -/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, -/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -RecompOpFn recomp_opcodes_db[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -RecompOpFn recomp_opcodes_dc[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, -/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, -/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, - -/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, -/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, -/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, - -/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, -/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, -/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, - -/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, -/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, -/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, -/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, -/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, -/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, - -/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, -/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, -/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, - -/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, -/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, -/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, - -/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, -/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, -/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, -/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, -}; - -RecompOpFn recomp_opcodes_dd[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -RecompOpFn recomp_opcodes_de[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, -/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, -/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, -/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, - -/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, -/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, -/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, -/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, - -/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, -/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, -/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, -/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, - -/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, -/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, -/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, -/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, -/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, - -/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, -/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, -/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, -/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, - -/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, -/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, -/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, -/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, - -/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, -/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, -}; - -RecompOpFn recomp_opcodes_df[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, - -/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, - -/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, - -/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, - -/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -RecompOpFn recomp_opcodes_REPE[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; - -RecompOpFn recomp_opcodes_REPNE[512] = -{ - /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -}; diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h deleted file mode 100644 index 57c5e8e..0000000 --- a/src/codegen_ops_arith.h +++ /dev/null @@ -1,1028 +0,0 @@ -static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); - - host_reg = LOAD_REG_W(opcode & 7); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - - return op_pc; -} -static uint32_t ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); - - host_reg = LOAD_REG_L(opcode & 7); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - - return op_pc; -} -static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); - - host_reg = LOAD_REG_W(opcode & 7); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - - return op_pc; -} -static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); - - host_reg = LOAD_REG_L(opcode & 7); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - - return op_pc; -} - -#define ROP_ARITH_RMW(name, op, writeback) \ - static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \ - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_B_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_W(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \ - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_W_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_L(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \ - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_L_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } - -#define ROP_ARITH_RM(name, op, writeback) \ - static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_B(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_B_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_W_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_L_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } - -ROP_ARITH_RMW(ADD, ADD, 1) -ROP_ARITH_RMW(SUB, SUB, 1) -ROP_ARITH_RM(ADD, ADD, 1) -ROP_ARITH_RM(SUB, SUB, 1) - -static uint32_t ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - src_reg = 0; - } - - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - src_reg = 0; - } - - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - src_reg = 0; - } - - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -static uint32_t ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - dst_reg = 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - dst_reg = 0; - } \ - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - dst_reg = 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} - - -static uint32_t ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - ADD_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - SUB_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_B(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_B(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD8); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffffff00); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - break; - } - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_B_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} - -static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - imm = fastreadw(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xffff; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - } - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_W_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 3; -} -static uint32_t rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - } - else - { - host_reg = LOAD_REG_L(fetchdat & 7); - } - imm = fastreadl(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - } - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_L_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 5; -} - -static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - if (imm & 0x80) - imm |= 0xff80; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - } - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_W_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_L(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_L(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - if (imm & 0x80) - imm |= 0xffffff80; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - } - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_L_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} diff --git a/src/codegen_ops_fpu.h b/src/codegen_ops_fpu.h deleted file mode 100644 index 5065094..0000000 --- a/src/codegen_ops_fpu.h +++ /dev/null @@ -1,645 +0,0 @@ -static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - - FP_FXCH(opcode & 7); - - return op_pc; -} - -static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - - FP_FLD(opcode & 7); - - return op_pc; -} - -static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - - FP_FST(opcode & 7); - - return op_pc; -} -static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - - FP_FST(opcode & 7); - FP_POP(); - - return op_pc; -} - - -static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - - FP_LOAD_S(); - - return op_pc + 1; -} -static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); - - FP_LOAD_D(); - - return op_pc + 1; -} - -static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); - - FP_LOAD_IW(); - - return op_pc + 1; -} -static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - - FP_LOAD_IL(); - - return op_pc + 1; -} -static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); - - FP_LOAD_IQ(); - - codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1; - - return op_pc + 1; -} - -static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - host_reg = FP_LOAD_REG(0); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - - return op_pc + 1; -} -static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg1, host_reg2; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - FP_LOAD_REG_D(0, &host_reg1, &host_reg2); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 7); - - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - - return op_pc + 1; -} - -static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; -} -static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; -} - -#define ropFarith(name, size, load, op) \ -static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(FPU_ ## name); \ - \ - return op_pc + 1; \ -} - -ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); - -#define ropFcompare(name, size, load, op) \ -static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(); \ - \ - return op_pc + 1; \ -} \ -static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \ - \ - FP_POP(); \ - \ - return new_pc; \ -} - -ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S); -ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D); -ropFcompare(COM, iw, MEM_LOAD_ADDR_EA_W, FP_COMPARE_IW); -ropFcompare(COM, il, MEM_LOAD_ADDR_EA_L, FP_COMPARE_IL); - -/*static uint32_t ropFADDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - - FP_OP_S(FPU_ADD); - - return op_pc + 1; -} -static uint32_t ropFDIVs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - - FP_OP_S(FPU_DIV); - - return op_pc + 1; -} -static uint32_t ropFMULs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - - FP_OP_S(FPU_MUL); - - return op_pc + 1; -} -static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - - FP_OP_S(FPU_SUB); - - return op_pc + 1; -}*/ - - -static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_ADD, 0, opcode & 7); - - return op_pc; -} -static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_COMPARE_REG(0, opcode & 7); - - return op_pc; -} -static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_DIV, 0, opcode & 7); - - return op_pc; -} -static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_DIVR, 0, opcode & 7); - - return op_pc; -} -static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_MUL, 0, opcode & 7); - - return op_pc; -} -static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_SUB, 0, opcode & 7); - - return op_pc; -} -static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_SUBR, 0, opcode & 7); - - return op_pc; -} - -static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_ADD, opcode & 7, 0); - - return op_pc; -} -static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_DIV, opcode & 7, 0); - - return op_pc; -} -static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_DIVR, opcode & 7, 0); - - return op_pc; -} -static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_MUL, opcode & 7, 0); - - return op_pc; -} -static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_SUB, opcode & 7, 0); - - return op_pc; -} -static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_SUBR, opcode & 7, 0); - - return op_pc; -} - -static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_ADD, opcode & 7, 0); - FP_POP(); - - return op_pc; -} -static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_COMPARE_REG(0, opcode & 7); - FP_POP(); - - return op_pc; -} -static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_DIV, opcode & 7, 0); - FP_POP(); - - return op_pc; -} -static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_DIVR, opcode & 7, 0); - FP_POP(); - - return op_pc; -} -static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_MUL, opcode & 7, 0); - FP_POP(); - - return op_pc; -} -static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_SUB, opcode & 7, 0); - FP_POP(); - - return op_pc; -} -static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_SUBR, opcode & 7, 0); - FP_POP(); - - return op_pc; -} - -static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_COMPARE_REG(0, 1); - FP_POP2(); - - return op_pc; -} - -static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - FP_ENTER(); - host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs); - STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); - - return op_pc; -} - - -static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - host_reg = FP_LOAD_REG_INT_W(0); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - - return op_pc + 1; -} -static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - host_reg = FP_LOAD_REG_INT(0); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - - return op_pc + 1; -} - -static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; -} -static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; -} -static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg1, host_reg2; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - - FP_POP(); - - return op_pc + 1; -} - - -static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0); - UPDATE_NPXC(0); - - return op_pc + 1; -} -static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - CHECK_SEG_WRITE(target_seg); - - host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc); - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - - return op_pc + 1; -} - - -static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_FCHS(); - - return op_pc; -} - -#define opFLDimm(name, v) \ - static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - static double fp_imm = v; \ - \ - FP_ENTER(); \ - FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \ - \ - return op_pc; \ - } - -opFLDimm(1, 1.0) -opFLDimm(L2T, 3.3219280948873623) -opFLDimm(L2E, 1.4426950408889634); -opFLDimm(PI, 3.141592653589793); -opFLDimm(EG2, 0.3010299956639812); -opFLDimm(Z, 0.0) - -static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull); - - return op_pc; -} diff --git a/src/codegen_ops_jump.h b/src/codegen_ops_jump.h deleted file mode 100644 index d2271cf..0000000 --- a/src/codegen_ops_jump.h +++ /dev/null @@ -1,270 +0,0 @@ -static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t offset = fetchdat & 0xff; - - if (offset & 0x80) - offset |= 0xffffff00; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset); - - return -1; -} - -static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint16_t offset = fetchdat & 0xffff; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff); - - return -1; -} - -static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t offset = fastreadl(cs + op_pc); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset); - - return -1; -} - - -static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t offset = fetchdat & 0xff; - - if (offset & 0x80) - offset |= 0xffffff00; - - if (op_32 & 0x200) - { - int host_reg = LOAD_REG_L(REG_ECX); - TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0); - } - else - { - int host_reg = LOAD_REG_W(REG_CX); - TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0); - } - - return op_pc+1; -} - -static uint32_t ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t offset = fetchdat & 0xff; - - if (offset & 0x80) - offset |= 0xffffff00; - - if (op_32 & 0x200) - { - int host_reg = LOAD_REG_L(REG_ECX); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_REG_L_RELEASE(host_reg); - TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0); - } - else - { - int host_reg = LOAD_REG_W(REG_CX); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_REG_W_RELEASE(host_reg); - TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0); - } - - return op_pc+1; -} - -static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - CALL_FUNC((uintptr_t)CF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); -} - -static void BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - int host_reg; - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - if (not) - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_UNKNOWN: - CALL_FUNC((uintptr_t)ZF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - break; - } -} - -static void BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - CALL_FUNC((uintptr_t)VF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); -} - -static void BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - CALL_FUNC((uintptr_t)PF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); -} - -static void BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - int host_reg; - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - AND_HOST_REG_IMM(host_reg, 0x80); - if (not) - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - AND_HOST_REG_IMM(host_reg, 0x8000); - if (not) - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - AND_HOST_REG_IMM(host_reg, 0x80000000); - if (not) - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_UNKNOWN: - CALL_FUNC((uintptr_t)NF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - break; - } -} - - -#define ropBRANCH(name, func, not) \ -static uint32_t rop ## name(uint8_t opcode, uint32_t fetchdat, \ - uint32_t op_32, uint32_t op_pc, \ - codeblock_t *block) \ -{ \ - uint32_t offset = fetchdat & 0xff; \ - \ - if (offset & 0x80) \ - offset |= 0xffffff00; \ - \ - func(1, op_pc, offset, not); \ - \ - return op_pc+1; \ -} \ -static uint32_t rop ## name ## _w(uint8_t opcode, \ - uint32_t fetchdat, uint32_t op_32, \ - uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t offset = fetchdat & 0xffff; \ - \ - if (offset & 0x8000) \ - offset |= 0xffff0000; \ - \ - func(2, op_pc, offset, not); \ - \ - return op_pc+2; \ -} \ -static uint32_t rop ## name ## _l(uint8_t opcode, \ - uint32_t fetchdat, uint32_t op_32, \ - uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t offset = fastreadl(cs + op_pc); \ - \ - func(4, op_pc, offset, not); \ - \ - return op_pc+4; \ -} - -ropBRANCH(JB, BRANCH_COND_B, 0) -ropBRANCH(JNB, BRANCH_COND_B, 1) -ropBRANCH(JE, BRANCH_COND_E, 0) -ropBRANCH(JNE, BRANCH_COND_E, 1) -ropBRANCH(JO, BRANCH_COND_O, 0) -ropBRANCH(JNO, BRANCH_COND_O, 1) -ropBRANCH(JP, BRANCH_COND_P, 0) -ropBRANCH(JNP, BRANCH_COND_P, 1) -ropBRANCH(JS, BRANCH_COND_S, 0) -ropBRANCH(JNS, BRANCH_COND_S, 1) -ropBRANCH(JL, BRANCH_COND_L, 0) -ropBRANCH(JNL, BRANCH_COND_L, 1) -ropBRANCH(JLE, BRANCH_COND_LE, 0) -ropBRANCH(JNLE, BRANCH_COND_LE, 1) -ropBRANCH(JBE, BRANCH_COND_BE, 0) -ropBRANCH(JNBE, BRANCH_COND_BE, 1) diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h deleted file mode 100644 index ca57fca..0000000 --- a/src/codegen_ops_logic.h +++ /dev/null @@ -1,564 +0,0 @@ -#define ROP_LOGIC(name, op, writeback) \ - static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \ - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_B_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_W(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \ - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_W_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_L(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \ - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_L_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_B(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_B_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_W_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_L_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } - -ROP_LOGIC(AND, AND, 1) -ROP_LOGIC(OR, OR, 1) -ROP_LOGIC(XOR, XOR, 1) - -static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - src_reg = 0; - } - - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - dst_reg = TEST_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - return op_pc + 1; -} -static uint32_t ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - src_reg = 0; - } - - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - dst_reg = TEST_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - return op_pc + 1; -} -static uint32_t ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - src_reg = 0; - } - - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - dst_reg = TEST_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - return op_pc + 1; -} - -static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - AND_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - OR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - OR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 1; -} -static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 2; -} -static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 4; -} - -static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - XOR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint8_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_B(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadb(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 2; - - case 0x10: /*NOT b*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_B(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xff); - STORE_REG_B_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG b*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - host_reg = LOAD_REG_B(fetchdat & 7); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_B(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_B_RELEASE(host_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} -static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint16_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST w,#*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xffff; - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadw(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 3; - - case 0x10: /*NOT w*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_W(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xffff); - STORE_REG_W_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG w*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - host_reg = LOAD_REG_W(fetchdat & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_W_RELEASE(host_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} -static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint32_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST l,#*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_L(fetchdat & 7); - imm = fastreadl(cs + op_pc + 1); - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadl(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 5; - - case 0x10: /*NOT l*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_L(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xffffffff); - STORE_REG_L_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG l*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - host_reg = LOAD_REG_L(fetchdat & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_L(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_L_RELEASE(host_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h deleted file mode 100644 index 9eb9567..0000000 --- a/src/codegen_ops_misc.h +++ /dev/null @@ -1,269 +0,0 @@ -static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - return op_pc; -} - -static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - CLEAR_BITS((uintptr_t)&flags, D_FLAG); - return op_pc; -} -static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - SET_BITS((uintptr_t)&flags, D_FLAG); - return op_pc; -} - -static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; - CLEAR_BITS((uintptr_t)&flags, I_FLAG); - return op_pc; -} -static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; - SET_BITS((uintptr_t)&flags, I_FLAG); - return op_pc; -} - -static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int host_reg; - - if ((fetchdat & 0x30) != 0x00) - return 0; - - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_B(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - break; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - break; - } - - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_B_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - - return op_pc + 1; -} -static uint32_t codegen_temp; -static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int host_reg; - - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) - return 0; - - if ((fetchdat & 0x30) == 0x00) - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_W(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0x30) != 0x00) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_W_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_W_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - - case 0x10: /*CALL*/ - STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg); - RELEASE_REG(host_reg); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(op_pc + 1); - MEM_STORE_ADDR_EA_W(&_ss, host_reg); - SP_MODIFY(-2); - - host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); - STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x20: /*JMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x30: /*PUSH*/ - if (!host_reg) - host_reg = LOAD_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - MEM_STORE_ADDR_EA_W(&_ss, host_reg); - SP_MODIFY(-2); - return op_pc + 1; - } - return 0; -} -static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int host_reg; - - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) - return 0; - - if ((fetchdat & 0x30) == 0x00) - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_L(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0x30) != 0x00) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_L(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_L_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_L_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - - case 0x10: /*CALL*/ - STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg); - RELEASE_REG(host_reg); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(op_pc + 1); - MEM_STORE_ADDR_EA_L(&_ss, host_reg); - SP_MODIFY(-4); - - host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x20: /*JMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x30: /*PUSH*/ - if (!host_reg) - host_reg = LOAD_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - MEM_STORE_ADDR_EA_L(&_ss, host_reg); - SP_MODIFY(-4); - return op_pc + 1; - } - return 0; -} diff --git a/src/codegen_ops_mmx.h b/src/codegen_ops_mmx.h deleted file mode 100644 index 78239cb..0000000 --- a/src/codegen_ops_mmx.h +++ /dev/null @@ -1,277 +0,0 @@ -static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg1, host_reg2; - - MMX_ENTER(); - - LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 7); - - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - } - - return op_pc + 1; -} - -static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - MMX_ENTER(); - - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg1, host_reg2; - - LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2); - STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_Q(target_seg); - STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2); - } - - return op_pc + 1; -} - -static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - MMX_ENTER(); - - host_reg = LOAD_MMX_D((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 3); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - MMX_ENTER(); - - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_L(fetchdat & 7); - STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_L(target_seg); - STORE_MMX_LQ((fetchdat >> 3) & 7, 0); - } - - return op_pc + 1; -} - -#define MMX_OP(name, func) \ -static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int src_reg1, src_reg2; \ - int xmm_src, xmm_dst; \ - \ - MMX_ENTER(); \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - \ - MEM_LOAD_ADDR_EA_Q(target_seg); \ - src_reg1 = LOAD_Q_REG_1; \ - src_reg2 = LOAD_Q_REG_2; \ - xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ - } \ - xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \ - func(xmm_dst, xmm_src); \ - STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \ - \ - return op_pc + 1; \ -} - -MMX_OP(ropPAND, MMX_AND) -MMX_OP(ropPANDN, MMX_ANDN) -MMX_OP(ropPOR, MMX_OR) -MMX_OP(ropPXOR, MMX_XOR) - -MMX_OP(ropPADDB, MMX_ADDB) -MMX_OP(ropPADDW, MMX_ADDW) -MMX_OP(ropPADDD, MMX_ADDD) -MMX_OP(ropPADDSB, MMX_ADDSB) -MMX_OP(ropPADDSW, MMX_ADDSW) -MMX_OP(ropPADDUSB, MMX_ADDUSB) -MMX_OP(ropPADDUSW, MMX_ADDUSW) - -MMX_OP(ropPSUBB, MMX_SUBB) -MMX_OP(ropPSUBW, MMX_SUBW) -MMX_OP(ropPSUBD, MMX_SUBD) -MMX_OP(ropPSUBSB, MMX_SUBSB) -MMX_OP(ropPSUBSW, MMX_SUBSW) -MMX_OP(ropPSUBUSB, MMX_SUBUSB) -MMX_OP(ropPSUBUSW, MMX_SUBUSW) - -MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW); -MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD); -MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ); -MMX_OP(ropPACKSSWB, MMX_PACKSSWB); -MMX_OP(ropPCMPGTB, MMX_PCMPGTB); -MMX_OP(ropPCMPGTW, MMX_PCMPGTW); -MMX_OP(ropPCMPGTD, MMX_PCMPGTD); -MMX_OP(ropPACKUSWB, MMX_PACKUSWB); -MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW); -MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD); -MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ); -MMX_OP(ropPACKSSDW, MMX_PACKSSDW); - -MMX_OP(ropPCMPEQB, MMX_PCMPEQB); -MMX_OP(ropPCMPEQW, MMX_PCMPEQW); -MMX_OP(ropPCMPEQD, MMX_PCMPEQD); - -MMX_OP(ropPSRLW, MMX_PSRLW) -MMX_OP(ropPSRLD, MMX_PSRLD) -MMX_OP(ropPSRLQ, MMX_PSRLQ) -MMX_OP(ropPSRAW, MMX_PSRAW) -MMX_OP(ropPSRAD, MMX_PSRAD) -MMX_OP(ropPSLLW, MMX_PSLLW) -MMX_OP(ropPSLLD, MMX_PSLLD) -MMX_OP(ropPSLLQ, MMX_PSLLQ) - -MMX_OP(ropPMULLW, MMX_PMULLW); -MMX_OP(ropPMULHW, MMX_PMULHW); -MMX_OP(ropPMADDWD, MMX_PMADDWD); - -static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLW*/ - MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAW*/ - MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLW*/ - MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} -static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLD*/ - MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAD*/ - MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLD*/ - MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} -static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLQ*/ - MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAQ*/ - MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLQ*/ - MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} - -static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - codegen_mmx_entered = 0; - - return 0; -} diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h deleted file mode 100644 index 61fcd0f..0000000 --- a/src/codegen_ops_mov.h +++ /dev/null @@ -1,656 +0,0 @@ -static uint32_t ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff); - - return op_pc + 1; -} -static uint32_t ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff); - - return op_pc + 2; -} -static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - fetchdat = fastreadl(cs + op_pc); - - STORE_IMM_REG_L(opcode & 7, fetchdat); - - return op_pc + 4; -} - - -static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 0); - - MEM_STORE_ADDR_EA_B(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 1); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - host_reg = LOAD_REG_L((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 3); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - RELEASE_REG(host_reg); - - } - - return op_pc + 1; -} - -static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_L(fetchdat & 7); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_L(target_seg); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadb(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_B(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 2; -} -static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadw(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 3; -} -static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - uint32_t imm = fastreadl(cs + op_pc + 1); - - STORE_IMM_REG_L(fetchdat & 7, imm); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadl(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 5; -} - - -static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr); - STORE_REG_TARGET_B_RELEASE(0, REG_AL); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr); - STORE_REG_TARGET_W_RELEASE(0, REG_AX); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr); - STORE_REG_TARGET_L_RELEASE(0, REG_EAX); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - int host_reg; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_B(REG_AL); - - MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg); - RELEASE_REG(host_reg); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - int host_reg; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_W(REG_AX); - - MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg); - RELEASE_REG(host_reg); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - int host_reg; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_L(REG_EAX); - - MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg); - RELEASE_REG(host_reg); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -static uint32_t ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int dest_reg = (fetchdat >> 3) & 7; - - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_REG_TARGET_W_RELEASE(0, dest_reg); - - return op_pc + 1; -} -static uint32_t ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int dest_reg = (fetchdat >> 3) & 7; - - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_REG_TARGET_L_RELEASE(0, dest_reg); - - return op_pc + 1; -} - -static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = ZERO_EXTEND_W_B(host_reg); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - ZERO_EXTEND_W_B(0); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = ZERO_EXTEND_L_B(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - ZERO_EXTEND_L_B(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - host_reg = ZERO_EXTEND_L_W(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - ZERO_EXTEND_L_W(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = SIGN_EXTEND_W_B(host_reg); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - SIGN_EXTEND_W_B(0); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = SIGN_EXTEND_L_B(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - SIGN_EXTEND_L_B(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - host_reg = SIGN_EXTEND_L_W(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - SIGN_EXTEND_L_W(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - host_reg = LOAD_VAR_WL((uintptr_t)&ES); - break; - case 0x08: /*CS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&CS); - break; - case 0x18: /*DS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&DS); - break; - case 0x10: /*SS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&SS); - break; - case 0x20: /*FS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&FS); - break; - case 0x28: /*GS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&GS); - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - if (op_32 & 0x100) - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - else - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 1); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - case 0x18: /*DS*/ - case 0x20: /*FS*/ - case 0x28: /*GS*/ - break; - case 0x10: /*SS*/ - default: - return 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_W(fetchdat & 7); - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); - - host_reg = 0; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - LOAD_SEG(host_reg, &_es); - break; - case 0x18: /*DS*/ - LOAD_SEG(host_reg, &_ds); - break; - case 0x20: /*FS*/ - LOAD_SEG(host_reg, &_fs); - break; - case 0x28: /*GS*/ - LOAD_SEG(host_reg, &_gs); - break; - } - - return op_pc + 1; -} - -#define ropLseg(seg, rseg) \ -static uint32_t ropL ## seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - SAVE_EA(); \ - \ - if (op_32 & 0x100) \ - { \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, 0); \ - LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ - } \ - else \ - { \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, 0); \ - LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ - } \ - LOAD_SEG(0, &rseg); \ - if (op_32 & 0x100) \ - { \ - \ - int host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); \ - STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \ - } \ - else \ - { \ - int host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); \ - STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \ - } \ - \ - if (&rseg == &_ss) \ - CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \ - return op_pc + 1; \ -} - -ropLseg(DS, _ds) -ropLseg(ES, _es) -ropLseg(FS, _fs) -ropLseg(GS, _gs) -ropLseg(SS, _ss) diff --git a/src/codegen_ops_shift.h b/src/codegen_ops_shift.h deleted file mode 100644 index 75d024f..0000000 --- a/src/codegen_ops_shift.h +++ /dev/null @@ -1,125 +0,0 @@ -#define SHIFT(size, size2, res_store, immediate) \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - reg = LOAD_REG_ ## size(fetchdat & 7); \ - if (immediate) count = (fetchdat >> 8) & 0x1f; \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_ ## size(target_seg); \ - reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \ - if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \ - \ - res_store((uintptr_t)&cpu_state.flags_op1, reg); \ - \ - switch (fetchdat & 0x38) \ - { \ - case 0x20: case 0x30: /*SHL*/ \ - SHL_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \ - break; \ - \ - case 0x28: /*SHR*/ \ - SHR_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \ - break; \ - \ - case 0x38: /*SAR*/ \ - SAR_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \ - break; \ - } \ - \ - res_store((uintptr_t)&cpu_state.flags_res, reg); \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_ ## size ## _RELEASE(reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \ - } - -static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int count; - int reg; - - if ((fetchdat & 0x38) < 0x20) - return 0; - - SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1); - - return op_pc + 2; -} -static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int count; - int reg; - - if ((fetchdat & 0x38) < 0x20) - return 0; - - SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1); - - return op_pc + 2; -} -static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int count; - int reg; - - if ((fetchdat & 0x38) < 0x20) - return 0; - - SHIFT(L, 32, STORE_HOST_REG_ADDR, 1); - - return op_pc + 2; -} - -static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int count = 1; - int reg; - - if ((fetchdat & 0x38) < 0x20) - return 0; - - SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0); - - return op_pc + 1; -} -static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int count = 1; - int reg; - - if ((fetchdat & 0x38) < 0x20) - return 0; - - SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0); - - return op_pc + 1; -} -static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg = NULL; - int count = 1; - int reg; - - if ((fetchdat & 0x38) < 0x20) - return 0; - - SHIFT(L, 32, STORE_HOST_REG_ADDR, 0); - - return op_pc + 1; -} diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h deleted file mode 100644 index 3ea27d3..0000000 --- a/src/codegen_ops_stack.h +++ /dev/null @@ -1,269 +0,0 @@ -static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_W(opcode & 7); - MEM_STORE_ADDR_EA_W(&_ss, host_reg); - SP_MODIFY(-2); - - return op_pc; -} -static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_L(opcode & 7); - MEM_STORE_ADDR_EA_L(&_ss, host_reg); - SP_MODIFY(-4); - - return op_pc; -} - -static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint16_t imm = fetchdat & 0xffff; - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_W(&_ss, host_reg); - SP_MODIFY(-2); - - return op_pc+2; -} -static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t imm = fastreadl(cs + op_pc); - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_L(&_ss, host_reg); - SP_MODIFY(-4); - - return op_pc+4; -} - -static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint16_t imm = fetchdat & 0xff; - int host_reg; - - if (imm & 0x80) - imm |= 0xff00; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_W(&_ss, host_reg); - SP_MODIFY(-2); - - return op_pc+1; -} -static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t imm = fetchdat & 0xff; - int host_reg; - - if (imm & 0x80) - imm |= 0xffffff00; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_L(&_ss, host_reg); - SP_MODIFY(-4); - - return op_pc+1; -} - -static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&_ss); - SP_MODIFY(2); - STORE_REG_TARGET_W_RELEASE(0, opcode & 7); - - return op_pc; -} -static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&_ss); - SP_MODIFY(4); - STORE_REG_TARGET_L_RELEASE(0, opcode & 7); - - return op_pc; -} - -static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(2); - - return -1; -} -static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(4); - - return -1; -} - -static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint16_t offset = fetchdat & 0xffff; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(2+offset); - - return -1; -} -static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint16_t offset = fetchdat & 0xffff; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(4+offset); - - return -1; -} - -static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint16_t offset = fetchdat & 0xffff; - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(op_pc+2); - MEM_STORE_ADDR_EA_W(&_ss, host_reg); - SP_MODIFY(-2); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff); - - return -1; -} -static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t offset = fastreadl(cs + op_pc); - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(op_pc+4); - MEM_STORE_ADDR_EA_L(&_ss, host_reg); - SP_MODIFY(-4); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset); - - return -1; -} - -static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_EBP_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&_ss); - host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/ - ADD_HOST_REG_IMM_W(host_reg, 2); - STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP); - STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ - - return op_pc; -} -static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_EBP_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&_ss); - host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/ - ADD_HOST_REG_IMM(host_reg, 4); - STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP); - STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ - - return op_pc; -} - -#define ROP_PUSH_SEG(seg) \ -static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-2); \ - host_reg = LOAD_VAR_W((uintptr_t)&seg); \ - MEM_STORE_ADDR_EA_W(&_ss, host_reg); \ - SP_MODIFY(-2); \ - \ - return op_pc; \ -} \ -static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-4); \ - host_reg = LOAD_VAR_W((uintptr_t)&seg); \ - MEM_STORE_ADDR_EA_L(&_ss, host_reg); \ - SP_MODIFY(-4); \ - \ - return op_pc; \ -} - -ROP_PUSH_SEG(CS) -ROP_PUSH_SEG(DS) -ROP_PUSH_SEG(ES) -ROP_PUSH_SEG(FS) -ROP_PUSH_SEG(GS) -ROP_PUSH_SEG(SS) - -#define ROP_POP_SEG(seg, rseg) \ -static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(2); \ - \ - return op_pc; \ -} \ -static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(4); \ - \ - return op_pc; \ -} - -ROP_POP_SEG(DS, _ds) -ROP_POP_SEG(ES, _es) -ROP_POP_SEG(FS, _fs) -ROP_POP_SEG(GS, _gs) diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h deleted file mode 100644 index f50eba2..0000000 --- a/src/codegen_ops_x86-64.h +++ /dev/null @@ -1,6213 +0,0 @@ -/*Register allocation : - R8-R15 - emulated registers -*/ -#include - -#define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 - -#define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000) - -static inline int find_host_xmm_reg() -{ - int c; - for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) - { - if (host_reg_xmm_mapping[c] == -1) - break; - } - - if (c == HOST_REG_XMM_END) - fatal("Out of host XMM regs!\n"); - return c; -} -static inline void call(codeblock_t *block, uintptr_t func) -{ - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; - - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - addbyte(0xE8); /*CALL*/ - addlong((uint32_t)diff); - } - else - { - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); - } -} - -static inline void call_long(uintptr_t func) -{ - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); -} - -static inline void load_param_1_32(codeblock_t *block, uint32_t param) -{ -#if WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif - addlong(param); -} -static inline void load_param_1_reg_32(int reg) -{ -#if WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc0 | REG_ECX | (reg << 3)); -#else - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc0 | REG_EDI | (reg << 3)); -#endif -} -#if 0 -static inline void load_param_1_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); -#if WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif - addquad(param); -} -#endif - -static inline void load_param_2_32(codeblock_t *block, uint32_t param) -{ -#if WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ -#else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ -#endif - addlong(param); -} -static inline void load_param_2_reg_32(int reg) -{ -#if WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDX, EAX*/ - addbyte(0xc0 | REG_EDX | (reg << 3)); -#else - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV ESI, EAX*/ - addbyte(0xc0 | REG_ESI | (reg << 3)); -#endif -} -static inline void load_param_2_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); -#if WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ -#else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ -#endif - addquad(param); -} - -static inline void load_param_3_reg_32(int reg) -{ - if (reg & 8) - { -#if WIN64 - addbyte(0x45); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x44); /*MOV EDX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | (reg << 3)); -#endif - } - else - { -#if WIN64 - addbyte(0x41); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x90); - addbyte(0x89); /*MOV EDX, reg*/ - addbyte(0xc0 | REG_EDX | (reg << 3)); -#endif - } -} -static inline void load_param_3_reg_64(int reg) -{ - if (reg & 8) - { -#if WIN64 - addbyte(0x4d); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x4c); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#endif - } - else - { -#if WIN64 - addbyte(0x49); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x48); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#endif - } -} - -static inline void CALL_FUNC(uintptr_t func) -{ - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); -} - -static inline void RELEASE_REG(int host_reg) -{ -} - -static inline int LOAD_REG_B(int reg) -{ - int host_reg = reg & 3; -// host_reg_mapping[host_reg] = reg; - - if (!codegen_reg_loaded[reg & 3]) - { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[host_reg & 3].b)); - } - - codegen_reg_loaded[reg & 3] = 1; - - if (reg & 4) - return host_reg | 0x18; - - return host_reg | 8; -} -static inline int LOAD_REG_W(int reg) -{ - int host_reg = reg; -// host_reg_mapping[host_reg] = reg; - - if (!codegen_reg_loaded[reg & 7]) - { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].w)); - } - - codegen_reg_loaded[reg & 7] = 1; - - return host_reg | 8; -} -static inline int LOAD_REG_L(int reg) -{ - int host_reg = reg; -// host_reg_mapping[host_reg] = reg; - - if (!codegen_reg_loaded[reg & 7]) - { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); - } - - codegen_reg_loaded[reg & 7] = 1; - - return host_reg | 8; -} - -static inline int LOAD_REG_IMM(uint32_t imm) -{ - int host_reg = REG_EBX; - - addbyte(0xb8 | REG_EBX); /*MOVL EBX, imm*/ - addlong(imm); - - return host_reg; -} - -static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) -{ - int dest_reg = LOAD_REG_L(guest_reg & 3) & 7; - - if (guest_reg & 4) - { - if (host_reg & 8) - { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - if (host_reg & 0x10) - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - else - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(0x08); - } - } - else - { - if (host_reg) - { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - } - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(0x08); - } - addbyte(0x66); /*AND dest_reg, 0x00ff*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | dest_reg); - addword(0x00ff); - addbyte(0x66); /*OR dest_reg, AX*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | dest_reg); - addbyte(0x66); /*MOVW regs[guest_reg].w, dest_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (dest_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].w)); - } - else - { - if (host_reg & 8) - { - if (host_reg & 0x10) - { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - addbyte(0x88); /*MOV AL, AH*/ - addbyte(0xe0); - addbyte(0x41); /*MOV dest_reg, AL*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7)); - addbyte(0x88); /*MOVB regs[reg].b, AH*/ - addbyte(0x65); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - else - { - addbyte(0x45); /*MOVB dest_reg, host_reg*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); - addbyte(0x44); /*MOVB regs[guest_reg].b, host_reg*/ - addbyte(0x88); - addbyte(0x45 | ((host_reg & 3) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - } - else - { - if (host_reg & 0x10) - { - addbyte(0xc1); /*SHR host_reg, 8*/ - addbyte(0xe8 | (host_reg & 7)); - addbyte(8); - } - addbyte(0x41); /*MOVB dest_reg, host_reg*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); - addbyte(0x88); /*MOVB regs[guest_reg].b, host_reg*/ - addbyte(0x45 | ((host_reg & 3) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - } -} -static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) -{ - int dest_reg = LOAD_REG_L(guest_reg & 7) & 7; - - if (host_reg & 8) - { - addbyte(0x66); /*MOVW guest_reg, host_reg*/ - addbyte(0x45); - addbyte(0x89); - addbyte(0xc0 | dest_reg | ((host_reg & 7) << 3)); - addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].w)); - } - else - { - addbyte(0x66); /*MOVW guest_reg, host_reg*/ - addbyte(0x41); - addbyte(0x89); - addbyte(0xc0 | dest_reg | (host_reg << 3)); - addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].w)); - } -} -static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) -{ - if (host_reg & 8) - { - addbyte(0x45); /*MOVL guest_reg, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | guest_reg | (host_reg << 3)); - addbyte(0x44); /*MOVL regs[guest_reg].l, host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].l)); - } - else - { - addbyte(0x41); /*MOVL guest_reg, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | guest_reg | (host_reg << 3)); - addbyte(0x89); /*MOVL regs[guest_reg].l, host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].l)); - } -} - -static inline void STORE_REG_B_RELEASE(int host_reg) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*MOVW [reg],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].w)); - } - else - { - addbyte(0x44); /*MOVB [reg],host_reg*/ - addbyte(0x88); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].b)); - } -} -static inline void STORE_REG_W_RELEASE(int host_reg) -{ - addbyte(0x66); /*MOVW [reg],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].w)); -} -static inline void STORE_REG_L_RELEASE(int host_reg) -{ - addbyte(0x44); /*MOVL [reg],host_reg*/ - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].l)); -} - -static inline void STORE_IMM_REG_B(int reg, uint8_t val) -{ - if (reg & 4) - { - int host_reg = LOAD_REG_W(reg & 3) & 7; - addbyte(0x66); /*AND host_reg, 0x00ff*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | host_reg); - addword(0x00ff); - addbyte(0x66); /*OR host_reg, val << 8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xc8 | host_reg); - addword(val << 8); - addbyte(0x66); /*MOVW host_reg, regs[host_reg].w*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 3].w)); - } - else - { - addbyte(0x41); /*MOVB reg, imm*/ - addbyte(0xb0 | reg); - addbyte(val); - addbyte(0x44); /*MOVB reg, regs[reg].b*/ - addbyte(0x88); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].b)); - } -} -static inline void STORE_IMM_REG_W(int reg, uint16_t val) -{ - addbyte(0x66); /*MOVW reg, imm*/ - addbyte(0x41); - addbyte(0xb8 | reg); - addword(val); - addbyte(0x66); /*MOVW reg, regs[reg].w*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].w)); -} -static inline void STORE_IMM_REG_L(int reg, uint32_t val) -{ - addbyte(0x41); /*MOVL reg, imm*/ - addbyte(0xb8 | reg); - addlong(val); - addbyte(0x44); /*MOVL reg, regs[reg].l*/ - addbyte(0x89); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); -} - -static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x45); - addbyte(addr - (uintptr_t)&cpu_state - 128); - addlong(val); - } - else if (addr < 0x100000000) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x04); - addbyte(0x25); - addlong(addr); - addlong(val); - } - else - { - addbyte(0x48); /*MOV ESI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad(addr); - addbyte(0xc7); /*MOVL [ESI], val*/ - addbyte(0x00 | REG_ESI); - addlong(val); - } -} - - - - -static x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - int mod = (fetchdat >> 6) & 3; -// int reg = (fetchdat >> 3) & 7; - int rm = fetchdat & 7; - - if (!mod && rm == 6) - { - addbyte(0xb8); /*MOVL EAX, imm*/ - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } - else - { - int base_reg, index_reg; - - switch (rm) - { - case 0: case 1: case 7: - base_reg = LOAD_REG_W(REG_BX); - break; - case 2: case 3: case 6: - base_reg = LOAD_REG_W(REG_BP); - break; - case 4: - base_reg = LOAD_REG_W(REG_SI); - break; - case 5: - base_reg = LOAD_REG_W(REG_DI); - break; - } - if (!(rm & 4)) - { - if (rm & 1) - index_reg = LOAD_REG_W(REG_DI); - else - index_reg = LOAD_REG_W(REG_SI); - } - base_reg &= 7; - index_reg &= 7; - - switch (mod) - { - case 0: - if (rm & 4) - { - addbyte(0x41); /*MOVZX EAX, base_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xc0 | base_reg); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) - { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte(0); - } - else - { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3)); - } - } - break; - case 1: - if (rm & 4) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte((fetchdat >> 8) & 0xff); - } - (*op_pc)++; - break; - case 2: - if (rm & 4) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong((fetchdat >> 8) & 0xffff); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3)); - addlong((fetchdat >> 8) & 0xffff); - } - (*op_pc) += 2; - break; - - } - if (mod || !(rm & 4)) - { - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - } - - if (mod1seg[rm] == &ss && !op_ssegs) - op_ea_seg = &_ss; - } - return op_ea_seg; -} -static x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - int mod = (fetchdat >> 6) & 3; -// int reg = (fetchdat >> 3) & 7; - int rm = fetchdat & 7; - uint32_t new_eaaddr; - - if (rm == 4) - { - uint8_t sib = fetchdat >> 8; - int base_reg = -1, index_reg = -1; - - (*op_pc)++; - - if (mod || (sib & 7) != 5) - base_reg = LOAD_REG_L(sib & 7) & 7; - - if (((sib >> 3) & 7) != 4) - index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; - - if (index_reg == -1) - { - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOV EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x44); /*MOV EAX, base_reg*/ - addbyte(0x89); - addbyte(0xc0 | (base_reg << 3)); - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) - { - addbyte(0x44); - addbyte(0x24); - } - else - { - addbyte(0x40 | base_reg); - } - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) - { - addbyte(0x84); - addbyte(0x24); - } - else - { - addbyte(0x80 | base_reg); - } - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } - } - else - { - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - if (sib >> 6) - { - addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ - addbyte(0x42); - addbyte(0x8d); - addbyte(0x04); - addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); - addlong(new_eaaddr); - } - else - { - addbyte(0x67); /*LEA EAX, imm32+index_reg*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | index_reg); - addlong(new_eaaddr); - } - (*op_pc) += 4; - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) - { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte(0); - } - else - { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - } - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } - } - if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &_ss; - } - else - { - int base_reg; - - if (!mod && rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - base_reg = LOAD_REG_L(rm) & 7; - if (mod) - { - if (rm == 5 && !op_ssegs) - op_ea_seg = &_ss; - if (mod == 1) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, base_reg+imm32*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - else - { - addbyte(0x44); /*MOV EAX, base_reg*/ - addbyte(0x89); - addbyte(0xc0 | (base_reg << 3)); - } - } - return op_ea_seg; -} - -static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) -{ - if (op_32 & 0x200) - return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); - return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); -} - - - -static inline void CHECK_SEG_READ(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &_cs || seg == &_ss) - return; - if (seg->checked) - return; - if (seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - if (IS_32_ADDR(&seg->base)) - { - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x83); /*CMP RSI, -1*/ - addbyte(0xe8 | REG_ESI); - addbyte(0xff); - } - addbyte(0x0f); /*JE BLOCK_GPF_OFFSET*/ - addbyte(0x84); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static inline void CHECK_SEG_WRITE(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &_cs || seg == &_ss) - return; - if (seg->checked) - return; - if (seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - if (IS_32_ADDR(&seg->base)) - { - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x83); /*CMP RSI, -1*/ - addbyte(0xe8 | REG_ESI); - addbyte(0xff); - } - addbyte(0x0f); /*JE BLOCK_GPF_OFFSET*/ - addbyte(0x84); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - return; - - if (IS_32_ADDR(&seg->base)) - { - addbyte(0xb8 | REG_ESI); /*MOV ESI, &addr*/ - addlong((uint32_t)(uintptr_t)seg); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)seg); - } - addbyte(0x3b); /*CMP EAX, seg->limit_low*/ - addbyte(0x46); - addbyte((uintptr_t)&seg->limit_low - (uintptr_t)seg); - addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ - addbyte(0x82); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - if (end_offset) - { - addbyte(0x83); /*ADD EAX, end_offset*/ - addbyte(0xc0); - addbyte(end_offset); - addbyte(0x3b); /*CMP EAX, seg->limit_high*/ - addbyte(0x46); - addbyte((uintptr_t)&seg->limit_high - (uintptr_t)seg); - addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ - addbyte(0x87); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - addbyte(0x83); /*SUB EAX, end_offset*/ - addbyte(0xe8); - addbyte(end_offset); - } -} - -static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemb386l); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemwl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) -{ - addbyte(0x83); /*ADD EAX, offset*/ - addbyte(0xc0); - addbyte(offset); - MEM_LOAD_ADDR_EA_W(seg); -} -static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemll); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - addbyte(0x48); /*MOV RAX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemql); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} - -static inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_B(seg); -} -static inline void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_W(seg); -} -static inline void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_L(seg); -} - -static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) -{ - if (host_reg & 0x10) - { - /*Handle high byte of register*/ - if (host_reg & 8) - { - addbyte(0x45); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - addbyte(0x66); /*SHR R8, 8*/ - addbyte(0x41); - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - host_reg = 8; - } - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x88); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - load_param_3_reg_32(host_reg); - call_long((uintptr_t)writememb386l); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 5:4)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 5:4)+2); - if (host_reg & 8) - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - load_param_3_reg_32(host_reg); - call_long((uintptr_t)writememwl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 4:3)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - load_param_3_reg_32(host_reg); - call_long((uintptr_t)writememll); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - if (host_reg & 8) - { - addbyte(0x4c); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x48); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12+4+6); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - load_param_3_reg_64(host_reg); - call_long((uintptr_t)writememql); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} - -static inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_B(seg, host_reg); -} -static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_W(seg, host_reg); -} -static inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_L(seg, host_reg); -} - -static inline void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) -{ - int temp_reg = REG_ECX; - - if (host_reg_mapping[REG_ECX] != -1) - temp_reg = REG_EBX; - - if (host_reg & 0x10) - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb7); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - addbyte(0xc1); /*SHR temp_reg, 8*/ - addbyte(0xe8 | temp_reg); - addbyte(8); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb6); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - } - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x45 | (temp_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x04 | (temp_reg << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - addbyte(0x89); /*MOV [RSI], temp_reg*/ - addbyte(0x06 | (temp_reg << 3)); - } -} -static inline void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) -{ - int temp_reg = REG_ECX; - - if (host_reg_mapping[REG_ECX] != -1) - temp_reg = REG_EBX; - - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb7); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x45 | (temp_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x04 | (temp_reg << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - addbyte(0x89); /*MOV [RSI], temp_reg*/ - addbyte(0x06 | (temp_reg << 3)); - } -} -static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x66); /*MOVW [addr],host_reg*/ - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x66); - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVW addr,host_reg*/ - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - - addbyte(0x66); - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVW [RSI],host_reg*/ - addbyte(0x06 | ((host_reg & 7) << 3)); - } -} -static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [addr],host_reg*/ - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL addr,host_reg*/ - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [RSI],host_reg*/ - addbyte(0x06 | ((host_reg & 7) << 3)); - } -} - -static inline void AND_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - addbyte(0x66); /*OR AX, 0x00ff*/ - addbyte(0x0d); - addword(0xff); - addbyte(0x66); /*ANDW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ANDB dst_reg, AL*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*OR src_reg, 0xff*/ - addbyte(0x81); - addbyte(0xc8 | src_reg); - addword(0xff); - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x20); /*ANDB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x20); /*ANDB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x20); /*ANDB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static inline void AND_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void AND_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x21); /*ANDL dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*ANDW host_reg, imm<<8*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | (host_reg & 7)); - addword((imm << 8) | 0xff); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xe0 | (host_reg & 7)); - addlong(imm); - } -} - -static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = (dst_reg & 0x10) | REG_EDX; - } - - AND_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; -} -static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - AND_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - AND_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((host_reg & 7) << 3)); - host_reg = REG_EDX | (host_reg & 0x10); - } - if (host_reg & 0x10) - { - addbyte(0x66); /*ANDW host_reg, imm<<8*/ - addbyte(0x81); - addbyte(0xe0 | (host_reg & 7)); - addword((imm << 8) | 0xff); - } - else - { - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xe0 | (host_reg & 7)); - addlong(imm); - } - - return host_reg; -} - -static inline void OR_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*ORW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ORB dst_reg, AL*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x08); /*ORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x08); /*ORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x08); /*ORB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static inline void OR_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void OR_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x09); /*ORW dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*ORW host_reg, imm<<8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xc8 | (host_reg & 7)); - addword(imm << 8); - } - else if (host_reg & 8) - { - addbyte(0x41); /*ORL host_reg, imm*/ - addbyte(0x81); - addbyte(0xc8 | (host_reg & 7)); - addlong(imm); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xc8 | (host_reg & 7)); - addlong(imm); - } -// fatal("OR to bad register\n"); -} - -static inline void XOR_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*XORW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*XORB dst_reg, AL*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x30); /*XORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x30); /*XORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x30); /*XORB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static inline void XOR_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*XORL dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*XORL dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*XORW dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x31); /*XORW dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*ORW host_reg, imm<<8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xf0 | (host_reg & 7)); - addword(imm << 8); - } - else if (host_reg & 8) - { - addbyte(0x41); /*ORL host_reg, imm*/ - addbyte(0x81); - addbyte(0xf0 | (host_reg & 7)); - addlong(imm); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xf0 | (host_reg & 7)); - addlong(imm); - } -// fatal("XOR to bad register\n"); -} - -static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*ADDW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ADDB dst_reg, AL*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x00); /*ADDB dst_reg, AL*/ - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - fatal("!(dst_reg & src_reg & 8)\n"); -} -static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - fatal("!(dst_reg & src_reg & 8)\n"); -} -static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - fatal("!(dst_reg & src_reg & 8)\n"); -} - -static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*SUBW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*SUBB dst_reg, AL*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x28); /*SUBB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x28); /*SUBB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x28); /*SUBB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - -// fatal("!(dst_reg & src_reg & 8) subb %i %i\n", dst_reg, src_reg); -} -static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x29); /*SUBL dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} - -static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = (dst_reg & 0x10) | REG_EDX; - } - - SUB_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; -} -static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - SUB_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - SUB_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} - -static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*ADDW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xC0 | (host_reg & 7)); - addword(imm << 8); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*ADDB host_reg, imm*/ - addbyte(0xC0 | (host_reg & 7)); - addbyte(imm); - } -} -static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - addbyte(0x66); /*ADDW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xC0 | (host_reg & 7)); - addword(imm); -} -static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ADDL host_reg, imm*/ - addbyte(0xC0 | (host_reg & 7)); - addlong(imm); -} - -static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*SUBW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xE8 | (host_reg & 7)); - addword(imm << 8); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*SUBB host_reg, imm*/ - addbyte(0xE8 | (host_reg & 7)); - addbyte(imm); - } -} -static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - addbyte(0x66); /*SUBW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xE8 | (host_reg & 7)); - addword(imm); -} -static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*SUBL host_reg, imm*/ - addbyte(0xE8 | (host_reg & 7)); - addlong(imm); -} - -static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = (host_reg & 0x10) | REG_EDX; - } - - SUB_HOST_REG_IMM_B(host_reg, imm); - - return host_reg;// & ~0x10; -} -static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = REG_EDX; - } - - SUB_HOST_REG_IMM_W(host_reg, imm); - - return host_reg; -} -static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = REG_EDX; - } - - SUB_HOST_REG_IMM(host_reg, imm); - - return host_reg; -} - -static inline void LOAD_STACK_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[ESP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} -static inline void LOAD_EBP_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[EBP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_EBP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_BP].l)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static inline void SP_MODIFY(int off) -{ - if (stack32) - { - if (off < 0x80) - { - addbyte(0x83); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addbyte(off); - } - else - { - addbyte(0x81); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addlong(off); - } - } - else - { - if (off < 0x80) - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x83); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addbyte(off); - } - else - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x81); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addword(off); - } - } -} - -static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - uint8_t *jump1; - - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - CALL_FUNC((uintptr_t)CF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(timing_bt ? 4 : 0)); - - if (!not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - if (not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; -} - -static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - uint8_t *jump1; - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(timing_bt ? 4 : 0)); - if (!not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - if (not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; -} - -static inline int LOAD_VAR_W(uintptr_t addr) -{ - int host_reg = REG_EBX; - - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x0f); /*MOVZX host_reg, offset[cpu_state]*/ - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte(addr - (uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x0f); /*MOVZX host_reg,[reg]*/ - addbyte(0xb7); - addbyte(0x04 | (host_reg << 3)); - addbyte(0x25); - addlong((uint32_t)addr); - } - else - { - addbyte(0x48); /*MOV host_reg, &addr*/ - addbyte(0xb8 | host_reg); - addquad(addr); - addbyte(0x0f); /*MOVZX host_reg, [host_reg]*/ - addbyte(0xb7); - addbyte(host_reg | (host_reg << 3)); - } - - return host_reg; -} -static inline int LOAD_VAR_WL(uintptr_t addr) -{ - return LOAD_VAR_W(addr); -} -static inline int LOAD_VAR_L(uintptr_t addr) -{ - int host_reg = REG_EBX; - - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x8b); /*MOVL host_reg, offset[cpu_state]*/ - addbyte(0x45 | (host_reg << 3)); - addbyte(addr - (uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(0x25); - addlong((uint32_t)addr); - } - else - { - addbyte(0x48); /*MOV host_reg, &addr*/ - addbyte(0xb8 | host_reg); - addquad(addr); - addbyte(0x8b); /*MOVL host_reg, [host_reg]*/ - addbyte(host_reg | (host_reg << 3)); - } - - return host_reg; -} - -static inline int COPY_REG(int src_reg) -{ - if (src_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | REG_ECX | ((src_reg & 7) << 3)); - - return REG_ECX | (src_reg & 0x10); -} - -static inline int LOAD_HOST_REG(int host_reg) -{ - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | REG_EBX | ((host_reg & 7) << 3)); - - return REG_EBX | (host_reg & 0x10); -} - -static inline int ZERO_EXTEND_W_B(int reg) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVZX EAX, AH*/ - addbyte(0xb6); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int ZERO_EXTEND_L_B(int reg) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVZX EAX, AH*/ - addbyte(0xb6); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int ZERO_EXTEND_L_W(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regw*/ - addbyte(0xb7); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} - -static inline int SIGN_EXTEND_W_B(int reg) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVSX EAX, AH*/ - addbyte(0xbe); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int SIGN_EXTEND_L_B(int reg) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVSX EAX, AH*/ - addbyte(0xbe); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int SIGN_EXTEND_L_W(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regw*/ - addbyte(0xbf); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} - -static inline void SHL_B_IMM(int reg, int count) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SHL AH, count*/ - addbyte(0xe0 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); - } -} -static inline void SHL_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHL reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); -} -static inline void SHL_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); -} -static inline void SHR_B_IMM(int reg, int count) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SHR AH, count*/ - addbyte(0xe8 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); - } -} -static inline void SHR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHR reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); -} -static inline void SHR_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SHR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); -} -static inline void SAR_B_IMM(int reg, int count) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SAR AH, count*/ - addbyte(0xf8 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SAR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); - } -} -static inline void SAR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SAR reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); -} -static inline void SAR_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SAR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); -} - -static inline void NEG_HOST_REG_B(int reg) -{ - if (reg & 0x10) - { - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV BX, reg*/ - addbyte(0xc3 | ((reg & 7) << 3)); - addbyte(0xf6); /*NEG BH*/ - addbyte(0xdf); - if (reg & 8) - addbyte(0x41); - addbyte(0x89); /*MOV reg, BX*/ - addbyte(0xd8 | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xf6); - addbyte(0xd8 | (reg & 7)); - } -} -static inline void NEG_HOST_REG_W(int reg) -{ - addbyte(0x66); - if (reg & 8) - addbyte(0x41); - addbyte(0xf7); - addbyte(0xd8 | (reg & 7)); -} -static inline void NEG_HOST_REG_L(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xf7); - addbyte(0xd8 | (reg & 7)); -} - - -static inline void FP_ENTER() -{ - if (codegen_fpu_entered) - return; - if (IS_32_ADDR(&cr0)) - { - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x04); - addbyte(0x25); - addlong((uintptr_t)&cr0); - addbyte(0x0c); - } - else - { - addbyte(0x48); /*MOV RAX, &cr0*/ - addbyte(0xb8 | REG_EAX); - addquad((uint64_t)&cr0); - addbyte(0xf6); /*TEST [RAX], 0xc*/ - addbyte(0 | (REG_EAX << 3)); - addbyte(0x0c); - } - addbyte(0x74); /*JZ +*/ - addbyte(7+5+12+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - load_param_1_32(&codeblock[block_current], 7); - CALL_FUNC((uintptr_t)x86_int); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - codegen_fpu_entered = 1; -} - -static inline void FP_FXCH(int reg) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - - addbyte(0x48); /*MOV RDX, ST[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0x48); /*MOV RCX, ST[RAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST[RAX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST[RBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - - addbyte(0x48); /*MOV RDX, MM[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x48); /*MOV RCX, MM[RAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x48); /*MOV MM[RAX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x48); /*MOV MM[RBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - reg = reg; -} - - - -static inline void FP_FLD(int reg) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - else - { - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - } - - addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(0x07); - addbyte(0x48); /*MOV RDX, ST_i64[EAX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x48); /*MOV ST[EBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST_i64[EBX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); -} - -static inline void FP_FST(int reg) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [tag+EAX]*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - - addbyte(0x48); /*MOV ST[EAX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EAX], BL*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); -} - -static inline void FP_POP() -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(3); - addbyte(0x83); /*ADD AL, 1*/ - addbyte(0xc0); - addbyte(1); - addbyte(0x83); /*AND AL, 7*/ - addbyte(0xe0); - addbyte(7); - addbyte(0x89); /*MOV [TOP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); -} -static inline void FP_POP2() -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(3); - addbyte(0x83); /*ADD AL, 2*/ - addbyte(0xc0); - addbyte(2); - addbyte(0x83); /*AND AL, 7*/ - addbyte(0xe0); - addbyte(7); - addbyte(0x89); /*MOV [TOP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); -} - -static inline void FP_LOAD_S() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf3); /*CVTSS2SD XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} -static inline void FP_LOAD_D() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x48); /*TEST RAX, RAX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x48); /*MOVQ [ST+EBX*8], RAX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} - -static inline void FP_LOAD_IW() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} -static inline void FP_LOAD_IL() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} -static inline void FP_LOAD_IQ() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SDQ XMM0, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x48); /*TEST RAX, RAX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0x48); /*MOV [ST_i64+EBX*8], RAX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} - -static inline void FP_LOAD_IMM_Q(uint64_t v) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST) + 4); - addlong(v >> 32); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOV [tag+EBX], (v ? 0 : 1)*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(v ? 0 : 1); -} - -static inline void FP_FCHS() -{ - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xf2); /*SUBSD XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc0); - addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0x11); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); -} - -static inline int FP_LOAD_REG(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xf2); /*CVTSD2SS XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc0); - addbyte(0x66); /*MOVD EBX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0 | REG_EBX); - - return REG_EBX; -} -static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0x48); /*MOV RBX, ST[EBX*8]*/ - addbyte(0x8b); - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - *host_reg1 = REG_EBX; -} -static inline int64_t x87_fround(double b) -{ - int64_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int64_t)floor(b); - c = (int64_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t)floor(b); - case 2: /*Up*/ - return (int64_t)ceil(b); - case 3: /*Chop*/ - return (int64_t)b; - } - - return 0; -} -static inline int FP_LOAD_REG_INT_W(int reg) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t)x87_fround); - - addbyte(0x93); /*XCHG EBX, EAX*/ - - return REG_EBX; -} -static inline int FP_LOAD_REG_INT(int reg) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t)x87_fround); - - addbyte(0x93); /*XCHG EBX, EAX*/ - - return REG_EBX; -} -static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) - { - /*If we know the register was loaded with FILDq in this block and - has not been modified, then we can skip most of the conversion - and just load the 64-bit integer representation directly */ - addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ - addbyte(0x8b); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - - addbyte(0x48); /*XCHG RBX, RAX*/ - addbyte(0x93); - - *host_reg1 = REG_EBX; - - return; - } - - addbyte(0xf6); /*TEST TAG[EAX], TAG_UINT64*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(TAG_UINT64); - - addbyte(0x74); /*JZ +*/ - addbyte(5+2); - - addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ - addbyte(0x8b); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - - addbyte(0xeb); /*JMP done*/ - addbyte(6+12); - - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t)x87_fround); - - addbyte(0x48); /*XCHG RBX, RAX*/ - addbyte(0x93); - - *host_reg1 = REG_EBX; -} - -#define FPU_ADD 0 -#define FPU_DIV 4 -#define FPU_DIVR 5 -#define FPU_MUL 1 -#define FPU_SUB 2 -#define FPU_SUBR 3 - -static inline void FP_OP_REG(int op, int dst, int src) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (dst) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - if (src) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(src); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(~TAG_UINT64); - if (op == FPU_DIVR || op == FPU_SUBR) - { - addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - switch (op) - { - case FPU_ADD: - addbyte(0xf2); /*ADDSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x58); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_DIV: - addbyte(0xf2); /*DIVSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_DIVR: - addbyte(0xf2); /*DIVSD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_MUL: - addbyte(0xf2); /*MULSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x59); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_SUB: - addbyte(0xf2); /*SUBSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_SUBR: - addbyte(0xf2); /*SUBSD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - } - addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); -} - -static inline void FP_OP_MEM(int op) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(~TAG_UINT64); - - switch (op) - { - case FPU_ADD: - addbyte(0xf2); /*ADDSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x58); - addbyte(0xc1); - break; - case FPU_DIV: - addbyte(0xf2); /*DIVSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0xc1); - break; - case FPU_DIVR: - addbyte(0xf2); /*DIVSD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0xc8); - break; - case FPU_MUL: - addbyte(0xf2); /*MULSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x59); - addbyte(0xc1); - break; - case FPU_SUB: - addbyte(0xf2); /*SUBSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc1); - break; - case FPU_SUBR: - addbyte(0xf2); /*SUBSD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc8); - break; - } - if (op == FPU_DIVR || op == FPU_SUBR) - { - addbyte(0x66); /*MOVQ ST[RAX*8], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0x66); /*MOVQ ST[RAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} - -static inline void FP_OP_S(int op) -{ - addbyte(0x66); /*MOVD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc9); - FP_OP_MEM(op); -} -static inline void FP_OP_D(int op) -{ - addbyte(0x66); /*MOVQ XMM1, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0x0f); /*STMXCSR [ESP+8]*/ - addbyte(0xae); - addbyte(0x5c); - addbyte(0x24); - addbyte(0x08); - addbyte(0x8b); /*MOV EAX, [ESP+8]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x08); - addbyte(0x25); /*AND EAX, ~(3 << 13)*/ - addlong(~(3 << 10)); - addbyte(0x0d); /*OR EAX, (npxc & (3 << 10)) << 3*/ - addlong((cpu_state.npxc & (3 << 10)) << 3); - addbyte(0x89); /*MOV [RSP+12], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x0c); - addbyte(0x0f); /*LDMXCSR [RSP+12]*/ - addbyte(0xae); - addbyte(0x54); - addbyte(0x24); - addbyte(0x0c); - } - FP_OP_MEM(op); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0x0f); /*LDMXCSR [RSP+8]*/ - addbyte(0xae); - addbyte(0x54); - addbyte(0x24); - addbyte(0x08); - } -} -static inline void FP_OP_IW(int op) -{ - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_OP_MEM(op); -} -static inline void FP_OP_IL(int op) -{ - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_OP_MEM(op); -} - -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) - -static inline void FP_COMPARE_REG(int dst, int src) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); -// addbyte(0xdb); /*FCLEX*/ -// addbyte(0xe2); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - - if (src) - { - addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x66); /*COMISD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x66); /*COMISD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - - addbyte(0x9f); /*LAHF*/ - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); -} - -static inline void FP_COMPARE_MEM() -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); -// addbyte(0xdb); /*FCLEX*/ -// addbyte(0xe2); - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0x66); /*COMISD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0xc1); - addbyte(0x9f); /*LAHF*/ - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); -} -static inline void FP_COMPARE_S() -{ - addbyte(0x66); /*MOVD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc9); - FP_COMPARE_MEM(); -} -static inline void FP_COMPARE_D() -{ - addbyte(0x66); /*MOVQ XMM1, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - FP_COMPARE_MEM(); -} -static inline void FP_COMPARE_IW() -{ - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_COMPARE_MEM(); -} -static inline void FP_COMPARE_IL() -{ - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_COMPARE_MEM(); -} - -static inline void UPDATE_NPXC(int reg) -{ -} - -static inline void SET_BITS(uintptr_t addr, uint32_t val) -{ - if (IS_32_ADDR(addr)) - { - if (val & ~0xff) - { - addbyte(0x81); /*OR [addr], val*/ - addbyte(0x0c); - addbyte(0x25); - addlong(addr); - addlong(val); - } - else - { - addbyte(0x80); /*OR [addr], val*/ - addbyte(0x0c); - addbyte(0x25); - addlong(addr); - addbyte(val); - } - } - else - { - addbyte(0x48); /*MOV RAX, &addr*/ - addbyte(0xb8 | REG_EAX); - addquad(addr); - if (val & ~0xff) - { - addbyte(0x81); /*OR [RAX], val*/ - addbyte(0x08); - addlong(val); - } - else - { - addbyte(0x80); /*OR [RAX], val*/ - addbyte(0x08); - addbyte(val); - } - } -} - -static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) -{ - if (IS_32_ADDR(addr)) - { - if (val & ~0xff) - { - addbyte(0x81); /*AND [addr], val*/ - addbyte(0x24); - addbyte(0x25); - addlong(addr); - addlong(~val); - } - else - { - addbyte(0x80); /*AND [addr], val*/ - addbyte(0x24); - addbyte(0x25); - addlong(addr); - addbyte(~val); - } - } - else - { - addbyte(0x48); /*MOV RAX, &addr*/ - addbyte(0xb8 | REG_EAX); - addquad(addr); - if (val & ~0xff) - { - addbyte(0x81); /*AND [RAX], val*/ - addbyte(0x20); - addlong(~val); - } - else - { - addbyte(0x80); /*AND [RAX], val*/ - addbyte(0x20); - addbyte(~val); - } - } -} - -#define LOAD_Q_REG_1 REG_EAX -#define LOAD_Q_REG_2 REG_EDX - -static inline void MMX_ENTER() -{ - if (codegen_mmx_entered) - return; - - if (IS_32_ADDR(&cr0)) - { - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x04); - addbyte(0x25); - addlong((uintptr_t)&cr0); - addbyte(0x0c); - } - else - { - addbyte(0x48); /*MOV RAX, &cr0*/ - addbyte(0xb8 | REG_EAX); - addquad((uint64_t)&cr0); - addbyte(0xf6); /*TEST [RAX], 0xc*/ - addbyte(0 | (REG_EAX << 3)); - addbyte(0x0c); - } - addbyte(0x74); /*JZ +*/ - addbyte(7+5+12+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - load_param_1_32(&codeblock[block_current], 7); - CALL_FUNC((uintptr_t)x86_int); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xc6); /*MOV ISMMX, 1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ismmx)); - addbyte(1); - addbyte(0x89); /*MOV TOP, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV tag, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV tag+4, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[4])); - - codegen_mmx_entered = 1; -} - -extern int mmx_ebx_ecx_loaded; - -static inline int LOAD_MMX_D(int guest_reg) -{ - int host_reg = REG_EBX; - - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x44 | (host_reg << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - - return host_reg; -} -static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) -{ - int host_reg = REG_EBX; - - if (host_reg & 8) - addbyte(0x4c); - else - addbyte(0x48); - addbyte(0x8b); /*MOV RBX, reg*/ - addbyte(0x44 | ((host_reg & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); - - *host_reg1 = host_reg; -} -static inline int LOAD_MMX_Q_MMX(int guest_reg) -{ - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0xf3); /*MOV XMMx, reg*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44 | ((dst_reg & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); - - return dst_reg; -} - -static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) -{ - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0x66); /*MOVQ host_reg, src_reg1*/ - if (src_reg1 & 8) - addbyte(0x49); - else - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (dst_reg << 3) | (src_reg1 & 7)); - - return dst_reg; -} - -static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) -{ - addbyte(0xC7); /*MOVL [reg],0*/ - addbyte(0x44); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); - addlong(0); - if (host_reg1 & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x44 | ((host_reg1 & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); -} -static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) -{ - if (host_reg1 & 8) - addbyte(0x4c); - else - addbyte(0x48); - addbyte(0x89); /*MOV [reg],host_reg*/ - addbyte(0x44 | ((host_reg1 & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); -} -static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) -{ - addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44 | (host_reg << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); -} - -#define MMX_x86_OP(name, opcode) \ -static inline void MMX_ ## name(int dst_reg, int src_reg) \ -{ \ - addbyte(0x66); /*op dst_reg, src_reg*/ \ - addbyte(0x0f); \ - addbyte(opcode); \ - addbyte(0xc0 | (dst_reg << 3) | src_reg); \ -} - -MMX_x86_OP(AND, 0xdb) -MMX_x86_OP(ANDN, 0xdf) -MMX_x86_OP(OR, 0xeb) -MMX_x86_OP(XOR, 0xef) - -MMX_x86_OP(ADDB, 0xfc) -MMX_x86_OP(ADDW, 0xfd) -MMX_x86_OP(ADDD, 0xfe) -MMX_x86_OP(ADDSB, 0xec) -MMX_x86_OP(ADDSW, 0xed) -MMX_x86_OP(ADDUSB, 0xdc) -MMX_x86_OP(ADDUSW, 0xdd) - -MMX_x86_OP(SUBB, 0xf8) -MMX_x86_OP(SUBW, 0xf9) -MMX_x86_OP(SUBD, 0xfa) -MMX_x86_OP(SUBSB, 0xe8) -MMX_x86_OP(SUBSW, 0xe9) -MMX_x86_OP(SUBUSB, 0xd8) -MMX_x86_OP(SUBUSW, 0xd9) - -MMX_x86_OP(PUNPCKLBW, 0x60); -MMX_x86_OP(PUNPCKLWD, 0x61); -MMX_x86_OP(PUNPCKLDQ, 0x62); -MMX_x86_OP(PCMPGTB, 0x64); -MMX_x86_OP(PCMPGTW, 0x65); -MMX_x86_OP(PCMPGTD, 0x66); - -MMX_x86_OP(PCMPEQB, 0x74); -MMX_x86_OP(PCMPEQW, 0x75); -MMX_x86_OP(PCMPEQD, 0x76); - -MMX_x86_OP(PSRLW, 0xd1); -MMX_x86_OP(PSRLD, 0xd2); -MMX_x86_OP(PSRLQ, 0xd3); -MMX_x86_OP(PSRAW, 0xe1); -MMX_x86_OP(PSRAD, 0xe2); -MMX_x86_OP(PSLLW, 0xf1); -MMX_x86_OP(PSLLD, 0xf2); -MMX_x86_OP(PSLLQ, 0xf3); - -MMX_x86_OP(PMULLW, 0xd5); -MMX_x86_OP(PMULHW, 0xe5); -MMX_x86_OP(PMADDWD, 0xf5); - -static inline void MMX_PACKSSWB(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x63); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static inline void MMX_PACKUSWB(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static inline void MMX_PACKSSDW(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} -static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} -static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} - -static inline void MMX_PSRLW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static inline void MMX_PSRAW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static inline void MMX_PSLLW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static inline void MMX_PSRLD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static inline void MMX_PSRAD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static inline void MMX_PSLLD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static inline void MMX_PSRLQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static inline void MMX_PSRAQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static inline void MMX_PSLLQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - - -static inline void SAVE_EA() -{ - addbyte(0x89); /*MOV [ESP+0x24], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); -} -static inline void LOAD_EA() -{ - addbyte(0x8b); /*MOV EAX, [ESP+0x24]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); -} - -#define MEM_CHECK_WRITE_B MEM_CHECK_WRITE - -static inline void MEM_CHECK_WRITE(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3 = NULL; - - CHECK_SEG_WRITE(seg); - - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) - { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&cr0); - addbyte(0); - } - else - { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t)&cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); -// addbyte(0xc3); /*RET*/ - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RCX, writelookup2*/ - addbyte(0xb9); - addquad((uint64_t)writelookup2); - addbyte(0x83); /*CMP [RCX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf9); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); -// addbyte(0xc3); /*RET*/ - - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; - /*slowpath:*/ - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - - - load_param_1_reg_32(REG_EDI); - load_param_2_32(&codeblock[block_current], 1); - - -// addbyte(0x6a); /*PUSH 1*/ -// addbyte(1); -// addbyte(0x57); /*PUSH EDI*/ - call(&codeblock[block_current], (uintptr_t)mmutranslatereal); -// addbyte(0x48); /*ADD ESP, 8*/ -// addbyte(0x83); -// addbyte(0xc4); -// addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t)&codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t)(&codeblock[block_current].data[block_pos]) + 4)); -// addbyte(0xc3); /*RET*/ - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - *jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1; - - - -// addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ -// addlong(mem_check_write - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); -} - -static inline void MEM_CHECK_WRITE_W(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; - int jump_pos; - - CHECK_SEG_WRITE(seg); - - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) - { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&cr0); - addbyte(0); - } - else - { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t)&cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - } - addbyte(0x8d); /*LEA ESI, 1[EDI]*/ - addbyte(0x77); - addbyte(0x01); - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x74); /*JE slowpath*/ - jump4 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - addbyte(0x89); /*MOV EBX, EDI*/ - addbyte(0xfb); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RAX, writelookup2*/ - addbyte(0xb8); - addquad((uint64_t)writelookup2); - addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf8); - addbyte(-1); - } - addbyte(0x74); /*JE +*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ - addbyte(0x3c); - addbyte(0xf0); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - /*slowpath:*/ - *jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1; - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1; - jump_pos = block_pos; - load_param_1_reg_32(REG_EBX); - load_param_2_32(&codeblock[block_current], 1); - call(&codeblock[block_current], (uintptr_t)mmutranslatereal); - addbyte(0x83); /*ADD EBX, 1*/ - addbyte(0xc3); - addbyte(1); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t)&codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $fff, EBX*/ - addbyte(0xc3); - addlong(0xfff); - addbyte(0x74); /*JNE slowpath*/ - addbyte(jump_pos - block_pos - 1); - - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; - - LOAD_EA(); -} - -static inline void MEM_CHECK_WRITE_L(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; - int jump_pos; - - CHECK_SEG_WRITE(seg); - - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) - { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&cr0); - addbyte(0); - } - else - { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t)&cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - } - addbyte(0x8d); /*LEA ESI, 3[EDI]*/ - addbyte(0x77); - addbyte(0x03); - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x74); /*JE slowpath*/ - jump4 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - addbyte(0x89); /*MOV EBX, EDI*/ - addbyte(0xfb); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RAX, writelookup2*/ - addbyte(0xb8); - addquad((uint64_t)writelookup2); - addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf8); - addbyte(-1); - } - addbyte(0x74); /*JE slowpath*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ - addbyte(0x3c); - addbyte(0xf0); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - /*slowpath:*/ - *jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1; - if (!(seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1; - jump_pos = block_pos; - load_param_1_reg_32(REG_EBX); - load_param_2_32(&codeblock[block_current], 1); - call(&codeblock[block_current], (uintptr_t)mmutranslatereal); - addbyte(0x83); /*ADD EBX, 3*/ - addbyte(0xc3); - addbyte(3); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t)&codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $ffc, EBX*/ - addbyte(0xc3); - addlong(0xffc); - addbyte(0x74); /*JE slowpath*/ - addbyte(jump_pos - block_pos - 1); - - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; - - LOAD_EA(); -} - -static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemb386l); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemwl); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12); - /*slowpath:*/ - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)readmemll); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} - -static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) -{ - if (host_reg & 0x10) - { - /*Handle high byte of register*/ - if (host_reg & 8) - { - addbyte(0x45); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - addbyte(0x66); /*SHR R8, 8*/ - addbyte(0x41); - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - host_reg = 8; - } - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x88); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12); - /*slowpath:*/ - load_param_3_reg_32(host_reg); - load_param_1_reg_32(REG_EBX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)writememb386l); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 5:4)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 5:4)+2); - if (host_reg & 8) - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12); - /*slowpath:*/ - load_param_3_reg_32(host_reg); - load_param_1_reg_32(REG_EBX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)writememwl); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 4:3)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x89); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12); - /*slowpath:*/ - load_param_3_reg_32(host_reg); - load_param_1_reg_32(REG_EBX); - load_param_2_reg_32(REG_EAX); - call_long((uintptr_t)writememll); - /*done:*/ -} - -static inline void LOAD_SEG(int host_reg, void *seg) -{ - load_param_2_64(&codeblock[block_current], (uint64_t)seg); - load_param_1_reg_32(host_reg); - CALL_FUNC((uintptr_t)loadseg); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h deleted file mode 100644 index 4066482..0000000 --- a/src/codegen_ops_x86.h +++ /dev/null @@ -1,3995 +0,0 @@ -/*Register allocation : - EBX, ECX, EDX - emulated registers - EAX - work register, EA storage - ESI, EDI - work registers - EBP - points at emulated register array -*/ -#define HOST_REG_START 1 -#define HOST_REG_END 4 -#define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 -static inline int find_host_reg() -{ - int c; - for (c = HOST_REG_START; c < HOST_REG_END; c++) - { - if (host_reg_mapping[c] == -1) - break; - } - - if (c == NR_HOST_REGS) - fatal("Out of host regs!\n"); - return c; -} -static inline int find_host_xmm_reg() -{ - int c; - for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) - { - if (host_reg_xmm_mapping[c] == -1) - break; - } - - if (c == HOST_REG_XMM_END) - fatal("Out of host XMM regs!\n"); - return c; -} - -#if 0 -static inline void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val) -{ - addbyte(0xC6); /*MOVB [addr],val*/ - addbyte(0x05); - addlong(addr); - addbyte(val); -} -static inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) -{ - addbyte(0x66); /*MOVW [addr],val*/ - addbyte(0xC7); - addbyte(0x05); - addlong(addr); - addword(val); -} -#endif -static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x45); - addbyte(addr - (uint32_t)&cpu_state - 128); - addlong(val); - } - else - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x05); - addlong(addr); - addlong(val); - } -} - -static inline void STORE_IMM_REG_B(int reg, uint8_t val) -{ - addbyte(0xC6); /*MOVB [addr],val*/ - addbyte(0x45); - if (reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); - addbyte(val); -} -static inline void STORE_IMM_REG_W(int reg, uint16_t val) -{ - addbyte(0x66); /*MOVW [addr],val*/ - addbyte(0xC7); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); - addword(val); -} -static inline void STORE_IMM_REG_L(int reg, uint32_t val) -{ - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].l)); - addlong(val); -} - -static inline int LOAD_REG_B(int reg) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x0f); /*MOVZX B[reg],host_reg*/ - addbyte(0xb6); - addbyte(0x45 | (host_reg << 3)); - if (reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); - - return host_reg; -} -static inline int LOAD_REG_W(int reg) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x0f); /*MOVZX W[reg],host_reg*/ - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); - - return host_reg; -} -static inline int LOAD_REG_L(int reg) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].l)); - - return host_reg; -} - -static inline int LOAD_VAR_W(uintptr_t addr) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; - - addbyte(0x66); /*MOVL host_reg,[reg]*/ - addbyte(0x8b); - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); - - return host_reg; -} -static inline int LOAD_VAR_WL(uintptr_t addr) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; - - addbyte(0x0f); /*MOVZX host_reg, [addr]*/ - addbyte(0xb7); - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); - - return host_reg; -} -static inline int LOAD_VAR_L(uintptr_t addr) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; - - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); - - return host_reg; -} - -static inline int LOAD_REG_IMM(uint32_t imm) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; - - addbyte(0xc7); /*MOVL host_reg, imm*/ - addbyte(0xc0 | host_reg); - addlong(imm); - - return host_reg; -} - -static inline int LOAD_HOST_REG(int host_reg) -{ - int new_host_reg = find_host_reg(); - host_reg_mapping[new_host_reg] = 0; - - addbyte(0x89); /*MOV new_host_reg, host_reg*/ - addbyte(0xc0 | (host_reg << 3) | new_host_reg); - - return new_host_reg; -} - -static inline void STORE_REG_B_RELEASE(int host_reg) -{ - addbyte(0x88); /*MOVB [reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - if (host_reg_mapping[host_reg] & 4) - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.l)); - host_reg_mapping[host_reg] = -1; -} -static inline void STORE_REG_W_RELEASE(int host_reg) -{ - addbyte(0x66); /*MOVW [reg],host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].w)); - host_reg_mapping[host_reg] = -1; -} -static inline void STORE_REG_L_RELEASE(int host_reg) -{ - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].l)); - host_reg_mapping[host_reg] = -1; -} - -static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x88); /*MOVB [guest_reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - if (guest_reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.l)); - host_reg_mapping[host_reg] = -1; -} -static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x66); /*MOVW [guest_reg],host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].w)); - host_reg_mapping[host_reg] = -1; -} -static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x89); /*MOVL [guest_reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].l)); - host_reg_mapping[host_reg] = -1; -} - -static inline void RELEASE_REG(int host_reg) -{ - host_reg_mapping[host_reg] = -1; -} - -static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x66); /*MOVW [addr],host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128); - } - else - { - addbyte(0x66); /*MOVL [reg],host_reg*/ - addbyte(0x89); - addbyte(0x05 | (host_reg << 3)); - addlong(addr); - } -} -static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x89); /*MOVL [addr],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128); - } - else - { - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x05 | (host_reg << 3)); - addlong(addr); - } -} -#define STORE_HOST_REG_ADDR_BL STORE_HOST_REG_ADDR -#define STORE_HOST_REG_ADDR_WL STORE_HOST_REG_ADDR - -static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) -{ - addbyte(0x00); /*ADDB dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) -{ - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) -{ - addbyte(0x01); /*ADDL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - addbyte(0x80); /*ADDB host_reg, imm*/ - addbyte(0xC0 | host_reg); - addbyte(imm); -} -static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (imm < 0x80 || imm >= 0xff80) - { - addbyte(0x66); /*ADDW host_reg, imm*/ - addbyte(0x83); - addbyte(0xC0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x66); /*ADDW host_reg, imm*/ - addbyte(0x81); - addbyte(0xC0 | host_reg); - addword(imm); - } -} -static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ADDL host_reg, imm*/ - addbyte(0xC0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ADDL host_reg, imm*/ - addbyte(0xC0 | host_reg); - addlong(imm); - } -} - -#define AND_HOST_REG_B AND_HOST_REG_L -#define AND_HOST_REG_W AND_HOST_REG_L -static inline void AND_HOST_REG_L(int dst_reg, int src_reg) -{ - addbyte(0x21); /*ANDL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ANDL host_reg, imm*/ - addbyte(0xE0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xE0 | host_reg); - addlong(imm); - } -} -static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) -{ - AND_HOST_REG_B(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) -{ - AND_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) -{ - AND_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - AND_HOST_REG_IMM(host_reg, imm); - - return host_reg; -} - -#define OR_HOST_REG_B OR_HOST_REG_L -#define OR_HOST_REG_W OR_HOST_REG_L -static inline void OR_HOST_REG_L(int dst_reg, int src_reg) -{ - addbyte(0x09); /*ORL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ORL host_reg, imm*/ - addbyte(0xC8 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xC8 | host_reg); - addlong(imm); - } -} - -static inline void NEG_HOST_REG_B(int reg) -{ - addbyte(0xf6); - addbyte(0xd8 | reg); -} -static inline void NEG_HOST_REG_W(int reg) -{ - addbyte(0x66); - addbyte(0xf7); - addbyte(0xd8 | reg); -} -static inline void NEG_HOST_REG_L(int reg) -{ - addbyte(0xf7); - addbyte(0xd8 | reg); -} - -static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) -{ - addbyte(0x28); /*SUBB dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) -{ - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) -{ - addbyte(0x29); /*SUBL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - addbyte(0x80); /*SUBB host_reg, imm*/ - addbyte(0xE8 | host_reg); - addbyte(imm); -} -static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (imm < 0x80 || imm >= 0xff80) - { - addbyte(0x66); /*SUBW host_reg, imm*/ - addbyte(0x83); - addbyte(0xE8 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x66); /*SUBW host_reg, imm*/ - addbyte(0x81); - addbyte(0xE8 | host_reg); - addword(imm); - } -} -static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*SUBL host_reg, imm*/ - addbyte(0xE8 | host_reg); - addbyte(imm); - } - else - { - addbyte(0x81); /*SUBL host_reg, imm*/ - addbyte(0xE8 | host_reg); - addlong(imm); - } -} - -static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) -{ - SUB_HOST_REG_B(dst_reg, src_reg); - - return dst_reg; -} -static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) -{ - SUB_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) -{ - SUB_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} -static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - SUB_HOST_REG_IMM_B(host_reg, imm); - - return host_reg; -} -static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - SUB_HOST_REG_IMM_W(host_reg, imm); - - return host_reg; -} -static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) -{ - SUB_HOST_REG_IMM(host_reg, imm); - - return host_reg; -} - -#define XOR_HOST_REG_B XOR_HOST_REG_L -#define XOR_HOST_REG_W XOR_HOST_REG_L -static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) -{ - addbyte(0x31); /*XORL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); -} -static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*XORL host_reg, imm*/ - addbyte(0xF0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*XORL host_reg, imm*/ - addbyte(0xF0 | host_reg); - addlong(imm); - } -} - -static inline void CALL_FUNC(uintptr_t dest) -{ - addbyte(0xE8); /*CALL*/ - addlong(((uintptr_t)dest - (uintptr_t)(&codeblock[block_current].data[block_pos + 4]))); -} - -static inline void SHL_B_IMM(int reg, int count) -{ - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | reg | 0x20); - addbyte(count); -} -static inline void SHL_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHL reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x20); - addbyte(count); -} -static inline void SHL_L_IMM(int reg, int count) -{ - addbyte(0xc1); /*SHL reg, count*/ - addbyte(0xc0 | reg | 0x20); - addbyte(count); -} -static inline void SHR_B_IMM(int reg, int count) -{ - addbyte(0xc0); /*SHR reg, count*/ - addbyte(0xc0 | reg | 0x28); - addbyte(count); -} -static inline void SHR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHR reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x28); - addbyte(count); -} -static inline void SHR_L_IMM(int reg, int count) -{ - addbyte(0xc1); /*SHR reg, count*/ - addbyte(0xc0 | reg | 0x28); - addbyte(count); -} -static inline void SAR_B_IMM(int reg, int count) -{ - addbyte(0xc0); /*SAR reg, count*/ - addbyte(0xc0 | reg | 0x38); - addbyte(count); -} -static inline void SAR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SAR reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x38); - addbyte(count); -} -static inline void SAR_L_IMM(int reg, int count) -{ - addbyte(0xc1); /*SAR reg, count*/ - addbyte(0xc0 | reg | 0x38); - addbyte(count); -} - - -static inline void CHECK_SEG_READ(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &_cs || seg == &_ss) - return; - if (seg->checked) - return; - if (seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x05|0x38); - addlong((uint32_t)&seg->base); - addbyte(-1); - addbyte(0x0f); - addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static inline void CHECK_SEG_WRITE(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &_cs || seg == &_ss) - return; - if (seg->checked) - return; - if (seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x05|0x38); - addlong((uint32_t)&seg->base); - addbyte(-1); - addbyte(0x0f); - addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - return; - - addbyte(0x3b); /*CMP EAX, seg->limit_low*/ - addbyte(0x05); - addlong((uint32_t)&seg->limit_low); - addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ - addbyte(0x82); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - if (end_offset) - { - addbyte(0x83); /*ADD EAX, end_offset*/ - addbyte(0xc0); - addbyte(end_offset); - addbyte(0x3b); /*CMP EAX, seg->limit_high*/ - addbyte(0x05); - addlong((uint32_t)&seg->limit_high); - addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ - addbyte(0x87); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - addbyte(0x83); /*SUB EAX, end_offset*/ - addbyte(0xe8); - addbyte(end_offset); - } -} - -static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_b*/ - addlong(mem_load_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_b_no_abrt*/ - addlong(mem_load_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ - addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0x83); /*ADD EAX, offset*/ - addbyte(0xc0); - addbyte(offset); - addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ - addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_w_no_abrt*/ - addlong(mem_load_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_l*/ - addlong(mem_load_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - - host_reg_mapping[0] = 8; -} -static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_l_no_abrt*/ - addlong(mem_load_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} - -static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_q*/ - addlong(mem_load_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} - -static inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_B(seg); -} -static inline void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_W(seg); -} -static inline void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_L(seg); -} - -static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ - addlong(mem_store_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_b_no_abrt*/ - addlong(mem_store_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_w*/ - addlong(mem_store_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_w_no_abrt*/ - addlong(mem_store_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_l*/ - addlong(mem_store_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_l_no_abrt*/ - addlong(mem_store_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) -{ - if (host_reg != REG_EBX) - { - addbyte(0x89); /*MOV EBX, host_reg*/ - addbyte(0xc0 | REG_EBX | (host_reg << 3)); - } - if (host_reg2 != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg2*/ - addbyte(0xc0 | REG_ECX | (host_reg2 << 3)); - } - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_q*/ - addlong(mem_store_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} - -static inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_B(seg, host_reg); -} -static inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_L(seg, host_reg); -} -static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_W(seg, host_reg); -} - - -static inline x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - int mod = (fetchdat >> 6) & 3; -// int reg = (fetchdat >> 3) & 7; - int rm = fetchdat & 7; - if (!mod && rm == 6) - { - addbyte(0xb8); /*MOVL EAX, imm16*/ - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } - else - { - switch (mod) - { - case 0: - addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ - addlong((uint32_t)mod1add[0][rm]); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - break; - case 1: - addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ - addlong((uint32_t)mod1add[0][rm]); - addbyte(0x83); /*ADDL EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(rmdat >> 8)); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - (*op_pc)++; - break; - case 2: - addbyte(0xb8); /*MOVL EAX, imm16*/ - addlong((fetchdat >> 8) & 0xffff);// pc++; - addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][rm]); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - (*op_pc) += 2; - break; - } - addbyte(0x25); /*ANDL EAX, 0xffff*/ - addlong(0xffff); - - if (mod1seg[rm] == &ss && !op_ssegs) - op_ea_seg = &_ss; - } - return op_ea_seg; -} - -static inline x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - uint32_t new_eaaddr; - int mod = (fetchdat >> 6) & 3; -// int reg = (fetchdat >> 3) & 7; - int rm = fetchdat & 7; - - if (rm == 4) - { - uint8_t sib = fetchdat >> 8; - (*op_pc)++; - - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, imm32*/ - addlong(new_eaaddr);// pc++; - (*op_pc) += 4; - } - else - { - addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - } - break; - case 1: - addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - addbyte(0x83); /*ADDL EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(rmdat >> 16)); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc) += 4; - break; - } - if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ - { - if (stack_offset < 0x80 || stack_offset >= 0xffffff80) - { - addbyte(0x83); - addbyte(0xc0 | REG_EAX); - addbyte(stack_offset); - } - else - { - addbyte(0x05); /*ADDL EAX, stack_offset*/ - addlong(stack_offset); - } - } - if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); - break; - case 1: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - case 2: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ - addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(2); /*SHL EDI, 2*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - case 3: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI reg*/ - addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(3); /*SHL EDI, 3*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - } - } - } - else - { - if (!mod && rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - addbyte(0x8b); /*MOVL EAX, regs[rm].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[rm].l)); - cpu_state.eaaddr = cpu_state.regs[rm].l; - if (mod) - { - if (rm == 5 && !op_ssegs) - op_ea_seg = &_ss; - if (mod == 1) - { - addbyte(0x83); /*ADD EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(fetchdat >> 8)); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x05); /*ADD EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - } - return op_ea_seg; -} - -static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) -{ - if (op_32 & 0x200) - return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); - return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); -} - - -static inline void LOAD_STACK_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[ESP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static inline void LOAD_EBP_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[EBP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_EBP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_EBP].w)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static inline void SP_MODIFY(int off) -{ - if (stack32) - { - if (off < 0x80) - { - addbyte(0x83); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addbyte(off); - } - else - { - addbyte(0x81); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addlong(off); - } - } - else - { - if (off < 0x80) - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x83); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addbyte(off); - } - else - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x81); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addword(off); - } - } -} - - -static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - addbyte(0x83); - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - addbyte(0x83); - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ - break; - - default: - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - if (not) - addbyte(5+2+2+7+5+(timing_bt ? 4 : 0)); - else - addbyte(5+2+2); - CALL_FUNC((uintptr_t)CF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - - default: - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - - default: - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - if (not) - addbyte(5+2+3+5+2+3+2+2+7+5+(timing_bt ? 4 : 0)); - else - addbyte(5+2+3+5+2+3+2+2); - - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - - -static inline void FP_ENTER() -{ - if (codegen_fpu_entered) - return; - - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x05); - addlong((uintptr_t)&cr0); - addbyte(0xc); - addbyte(0x74); /*JZ +*/ - addbyte(7+7+5+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - addbyte(0xc7); /*MOV [ESP], 7*/ - addbyte(0x04); - addbyte(0x24); - addlong(7); - addbyte(0xe8); /*CALL x86_int*/ - addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - codegen_fpu_entered = 1; -} - -static inline void FP_FLD(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x88); /*MOV tag[-1][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - else - { - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - } - - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(0x07); - addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -static inline void FP_FST(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [tag+EAX]*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EAX], BL*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} - -static inline void FP_FXCH(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[cpu_state.TOP].q)); - addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(MM[cpu_state.TOP].q)); - addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[0][EBP], AH*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - - addbyte(0xdd); /*FLD [ST+EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0xbe); /*MOVL ESI, ST_int64*/ - addlong((uintptr_t)cpu_state.MM); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ - addbyte(0x0c); - addbyte(0xc6); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ - addbyte(0x14); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ - addbyte(0x0c); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ - addbyte(0x14); - addbyte(0xc6); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ - addbyte(0x4c); - addbyte(0xc6); - addbyte(0x04); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ - addbyte(0x54); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ - addbyte(0x4c); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ - addbyte(0x54); - addbyte(0xc6); - addbyte(0x04); - } -} - - -static inline void FP_LOAD_S() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - block_current = block_current; - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_D() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV ST[reg][EBP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/ - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0xdd); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_IW() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0x66); /*TEST AX, AX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_IL() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_IQ() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV MM[reg][EBP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/ - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdf); /*FILDq MM[reg][EBP]*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ - addbyte(0x6c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} - -static inline void FP_LOAD_IMM_Q(uint64_t v) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc7); /*MOV ST[reg][EBP], v*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); - addlong(v >> 32); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(v ? 0 : 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST) + 4); - addlong(v >> 32); - addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(v ? 0 : 1); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -static inline int FP_LOAD_REG(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - addbyte(0xd9); /*FSTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV EAX, [ESP]*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(0x24); - - return REG_EBX; -} - -static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - addbyte(0xdd); /*FSTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(0x24); - addbyte(0x8b); /*MOV ECX, [ESP+4]*/ - addbyte(0x44 | (REG_ECX << 3)); - addbyte(0x24); - addbyte(0x04); - - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; -} - -static inline int FP_LOAD_REG_INT_W(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdb); /*FISTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - - return REG_EBX; -} -static inline int FP_LOAD_REG_INT(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdb); /*FISTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - - return REG_EBX; -} -static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) - { - /*If we know the register was loaded with FILDq in this block and - has not been modified, then we can skip most of the conversion - and just load the 64-bit integer representation directly */ - addbyte(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - - return; - } - - addbyte(0xf6); /*TEST TAG[EBX], TAG_UINT64*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_UINT64); - addbyte(0x74); /*JZ +*/ - addbyte(4+4+2); - - addbyte(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - - addbyte(0xeb); /*JMP done*/ - addbyte(4+3+3+3+3+4); - - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdf); /*FISTPQ [ESP]*/ - addbyte(0x3c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV ECX, 4[ESP]*/ - addbyte(0x4c); - addbyte(0x24); - addbyte(4); - - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; -} - -static inline void FP_POP() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(3); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP + 1) & 7); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 1*/ - addbyte(1); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} -static inline void FP_POP2() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(3); - addbyte(0xc6); /*MOVB tag[1][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP+1)&7])); - addbyte(3); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP+2) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP + 2) & 7); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 2*/ - addbyte(2); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -#define FPU_ADD 0x00 -#define FPU_DIV 0x30 -#define FPU_DIVR 0x38 -#define FPU_MUL 0x08 -#define FPU_SUB 0x20 -#define FPU_SUBR 0x28 - -static inline void FP_OP_S(int op) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(~TAG_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} -static inline void FP_OP_D(int op) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - } - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - } - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - } - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - } - } -} -static inline void FP_OP_IW(int op) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(~TAG_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} -static inline void FP_OP_IL(int op) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(~TAG_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} -#if 0 -static inline void FP_OP_IQ(int op) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} -#endif -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) - -static inline void FP_COMPARE_S() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } -} -static inline void FP_COMPARE_D() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } -} -static inline void FP_COMPARE_IW() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } -} -static inline void FP_COMPARE_IL() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } -} - -static inline void FP_OP_REG(int op, int dst, int src) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - addbyte(0xdc); /*FADD ST[src][EBP]*/ - addbyte(0x45 | op); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); - addbyte(~TAG_UINT64); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD ST[EAX*8]*/ - addbyte(0x44 | op); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD ST[EBX*8]*/ - addbyte(0x44 | op); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - } -} - -static inline void FP_COMPARE_REG(int dst, int src) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP ST[src][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EAX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EBX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } -} - -static inline void FP_FCHS() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xd9); /*FCHS*/ - addbyte(0xe0); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(~TAG_UINT64); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xd9); /*FCHS*/ - addbyte(0xe0); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} - -static inline void UPDATE_NPXC(int reg) -{ - addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ - addbyte(0x81); - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addword(~0xc00); - if (reg) - { - addbyte(0x66); /*AND reg, 0xc00*/ - addbyte(0x81); - addbyte(0xe0 | reg); - addword(0xc00); - } - else - { - addbyte(0x66); /*AND AX, 0xc00*/ - addbyte(0x25); - addword(0xc00); - } - addbyte(0x66); /*OR cpu_state.new_npxc, reg*/ - addbyte(0x09); - addbyte(0x45 | (reg << 3)); - addbyte((uint8_t)cpu_state_offset(new_npxc)); -} - -static inline int ZERO_EXTEND_W_B(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int ZERO_EXTEND_L_B(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int ZERO_EXTEND_L_W(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regw*/ - addbyte(0xb7); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} - -static inline int SIGN_EXTEND_W_B(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int SIGN_EXTEND_L_B(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int SIGN_EXTEND_L_W(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regw*/ - addbyte(0xbf); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} - -static inline int COPY_REG(int src_reg) -{ - return src_reg; -} - -static inline void SET_BITS(uintptr_t addr, uint32_t val) -{ - if (val & ~0xff) - { - addbyte(0x81); - addbyte(0x0d); - addlong(addr); - addlong(val); - } - else - { - addbyte(0x80); - addbyte(0x0d); - addlong(addr); - addbyte(val); - } -} -static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) -{ - if (val & ~0xff) - { - addbyte(0x81); - addbyte(0x25); - addlong(addr); - addlong(~val); - } - else - { - addbyte(0x80); - addbyte(0x25); - addlong(addr); - addbyte(~val); - } -} - -#define LOAD_Q_REG_1 REG_EAX -#define LOAD_Q_REG_2 REG_EDX - -static inline void MMX_ENTER() -{ - if (codegen_mmx_entered) - return; - - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x05); - addlong((uintptr_t)&cr0); - addbyte(0xc); - addbyte(0x74); /*JZ +*/ - addbyte(7+7+5+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - addbyte(0xc7); /*MOV [ESP], 7*/ - addbyte(0x04); - addbyte(0x24); - addlong(7); - addbyte(0xe8); /*CALL x86_int*/ - addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xc6); /*MOV ISMMX, 1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ismmx)); - addbyte(1); - addbyte(0x89); /*MOV TOP, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV tag, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV tag+4, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[4])); - - codegen_mmx_entered = 1; -} - -extern int mmx_ebx_ecx_loaded; - -static inline int LOAD_MMX_D(int guest_reg) -{ - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 100; - - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - - return host_reg; -} -static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) -{ - if (!mmx_ebx_ecx_loaded) - { - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; - mmx_ebx_ecx_loaded = 1; - } - else - { - *host_reg1 = REG_EAX; - *host_reg2 = REG_EDX; - } - - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x45 | ((*host_reg1) << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - addbyte(0x8b); /*MOV ECX, reg+4*/ - addbyte(0x45 | ((*host_reg2) << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); -} -static inline int LOAD_MMX_Q_MMX(int guest_reg) -{ - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = guest_reg; - - addbyte(0xf3); /*MOVQ dst_reg,[reg]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45 | (dst_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); - - return dst_reg; -} - -static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) -{ - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0x66); /*MOVD dst_reg, src_reg1*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (dst_reg << 3) | src_reg1); - addbyte(0x66); /*MOVD XMM7, src_reg2*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (7 << 3) | src_reg2); - addbyte(0x66); /*PUNPCKLDQ dst_reg, XMM7*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | 7 | (dst_reg << 3)); - - return dst_reg; -} - -static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) -{ - addbyte(0xC7); /*MOVL [reg],0*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); - addlong(0); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg1 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); -} -static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) -{ - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg1 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg2 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); -} -static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) -{ - addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); -} - -#define MMX_x86_OP(name, opcode) \ -static inline void MMX_ ## name(int dst_reg, int src_reg) \ -{ \ - addbyte(0x66); /*op dst_reg, src_reg*/ \ - addbyte(0x0f); \ - addbyte(opcode); \ - addbyte(0xc0 | (dst_reg << 3) | src_reg); \ -} - -MMX_x86_OP(AND, 0xdb) -MMX_x86_OP(ANDN, 0xdf) -MMX_x86_OP(OR, 0xeb) -MMX_x86_OP(XOR, 0xef) - -MMX_x86_OP(ADDB, 0xfc) -MMX_x86_OP(ADDW, 0xfd) -MMX_x86_OP(ADDD, 0xfe) -MMX_x86_OP(ADDSB, 0xec) -MMX_x86_OP(ADDSW, 0xed) -MMX_x86_OP(ADDUSB, 0xdc) -MMX_x86_OP(ADDUSW, 0xdd) - -MMX_x86_OP(SUBB, 0xf8) -MMX_x86_OP(SUBW, 0xf9) -MMX_x86_OP(SUBD, 0xfa) -MMX_x86_OP(SUBSB, 0xe8) -MMX_x86_OP(SUBSW, 0xe9) -MMX_x86_OP(SUBUSB, 0xd8) -MMX_x86_OP(SUBUSW, 0xd9) - -MMX_x86_OP(PUNPCKLBW, 0x60); -MMX_x86_OP(PUNPCKLWD, 0x61); -MMX_x86_OP(PUNPCKLDQ, 0x62); -MMX_x86_OP(PCMPGTB, 0x64); -MMX_x86_OP(PCMPGTW, 0x65); -MMX_x86_OP(PCMPGTD, 0x66); - -MMX_x86_OP(PCMPEQB, 0x74); -MMX_x86_OP(PCMPEQW, 0x75); -MMX_x86_OP(PCMPEQD, 0x76); - -MMX_x86_OP(PSRLW, 0xd1); -MMX_x86_OP(PSRLD, 0xd2); -MMX_x86_OP(PSRLQ, 0xd3); -MMX_x86_OP(PSRAW, 0xe1); -MMX_x86_OP(PSRAD, 0xe2); -MMX_x86_OP(PSLLW, 0xf1); -MMX_x86_OP(PSLLD, 0xf2); -MMX_x86_OP(PSLLQ, 0xf3); - -MMX_x86_OP(PMULLW, 0xd5); -MMX_x86_OP(PMULHW, 0xe5); -MMX_x86_OP(PMADDWD, 0xf5); - -static inline void MMX_PACKSSWB(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x63); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static inline void MMX_PACKUSWB(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static inline void MMX_PACKSSDW(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} -static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} -static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} - -static inline void MMX_PSRLW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static inline void MMX_PSRAW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static inline void MMX_PSLLW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static inline void MMX_PSRLD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static inline void MMX_PSRAD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static inline void MMX_PSLLD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static inline void MMX_PSRLQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static inline void MMX_PSRAQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static inline void MMX_PSLLQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - - -static inline void SAVE_EA() -{ - addbyte(0x89); /*MOV [ESP+12], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(12); -} -static inline void LOAD_EA() -{ - addbyte(0x8b); /*MOV EAX, [ESP+12]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(12); -} - -#define MEM_CHECK_WRITE_B MEM_CHECK_WRITE -static inline void MEM_CHECK_WRITE(x86seg *seg) -{ - CHECK_SEG_WRITE(seg); - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write*/ - addlong(mem_check_write - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); -} -static inline void MEM_CHECK_WRITE_W(x86seg *seg) -{ - CHECK_SEG_WRITE(seg); - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write_w*/ - addlong(mem_check_write_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); -} -static inline void MEM_CHECK_WRITE_L(x86seg *seg) -{ - CHECK_SEG_WRITE(seg); - if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write_l*/ - addlong(mem_check_write_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); -} - -static inline void LOAD_SEG(int host_reg, void *seg) -{ - addbyte(0xc7); /*MOV [ESP+4], seg*/ - addbyte(0x44); - addbyte(0x24); - addbyte(4); - addlong((uint32_t)seg); - addbyte(0x89); /*MOV [ESP], host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(0x24); - CALL_FUNC((uintptr_t)loadseg); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} diff --git a/src/codegen_ops_xchg.h b/src/codegen_ops_xchg.h deleted file mode 100644 index 25ff4c7..0000000 --- a/src/codegen_ops_xchg.h +++ /dev/null @@ -1,93 +0,0 @@ -#define OP_XCHG_AX_(reg) \ - static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int ax_reg, host_reg, temp_reg; \ - \ - ax_reg = LOAD_REG_W(REG_AX); \ - host_reg = LOAD_REG_W(REG_ ## reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \ - STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ - \ - return op_pc; \ - } - -OP_XCHG_AX_(BX) -OP_XCHG_AX_(CX) -OP_XCHG_AX_(DX) -OP_XCHG_AX_(SI) -OP_XCHG_AX_(DI) -OP_XCHG_AX_(SP) -OP_XCHG_AX_(BP) - -#define OP_XCHG_EAX_(reg) \ - static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int eax_reg, host_reg, temp_reg; \ - \ - eax_reg = LOAD_REG_L(REG_EAX); \ - host_reg = LOAD_REG_L(REG_ ## reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \ - STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ - \ - return op_pc; \ - } - -OP_XCHG_EAX_(EBX) -OP_XCHG_EAX_(ECX) -OP_XCHG_EAX_(EDX) -OP_XCHG_EAX_(ESI) -OP_XCHG_EAX_(EDI) -OP_XCHG_EAX_(ESP) -OP_XCHG_EAX_(EBP) - -static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ -#ifdef __amd64__ - return 0; -#else - int src_reg, dst_reg, temp_reg; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - - dst_reg = LOAD_REG_B(fetchdat & 7); - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7); - - return op_pc + 1; -#endif -} -static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg, temp_reg; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - - dst_reg = LOAD_REG_W(fetchdat & 7); - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7); - - return op_pc + 1; -} -static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg, temp_reg; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - - dst_reg = LOAD_REG_L(fetchdat & 7); - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7); - - return op_pc + 1; -} diff --git a/src/codegen_x86.c b/src/codegen_x86.c deleted file mode 100644 index b61008c..0000000 --- a/src/codegen_x86.c +++ /dev/null @@ -1,2180 +0,0 @@ -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 - -#include -#include "ibm.h" -#include "cpu.h" -#include "x86.h" -#include "x86_flags.h" -#include "x86_ops.h" -#include "x87.h" -#include "mem.h" - -#include "386_common.h" - -#include "codegen.h" -#include "codegen_ops.h" -#include "codegen_ops_x86.h" - -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif - -int codegen_flat_ds, codegen_flat_ss; -int mmx_ebx_ecx_loaded; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_mmx_entered = 0; -int codegen_fpu_loaded_iq[8]; -x86seg *op_ea_seg; -int op_ssegs; -uint32_t op_old_pc; - -uint32_t recomp_page = -1; - -int host_reg_mapping[NR_HOST_REGS]; -int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; -codeblock_t *codeblock; -codeblock_t **codeblock_hash; - - -int block_current = 0; -static int block_num; -int block_pos; - -int cpu_recomp_flushes, cpu_recomp_flushes_latched; -int cpu_recomp_evicted, cpu_recomp_evicted_latched; -int cpu_recomp_reuse, cpu_recomp_reuse_latched; -int cpu_recomp_removed, cpu_recomp_removed_latched; - -uint32_t codegen_endpc; - -int codegen_block_cycles; -static int codegen_block_ins; -static int codegen_block_full_ins; - -static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; - -static uint32_t mem_abrt_rout; -uint32_t mem_load_addr_ea_b; -uint32_t mem_load_addr_ea_w; -uint32_t mem_load_addr_ea_l; -uint32_t mem_load_addr_ea_q; -uint32_t mem_store_addr_ea_b; -uint32_t mem_store_addr_ea_w; -uint32_t mem_store_addr_ea_l; -uint32_t mem_store_addr_ea_q; -uint32_t mem_load_addr_ea_b_no_abrt; -uint32_t mem_store_addr_ea_b_no_abrt; -uint32_t mem_load_addr_ea_w_no_abrt; -uint32_t mem_store_addr_ea_w_no_abrt; -uint32_t mem_load_addr_ea_l_no_abrt; -uint32_t mem_store_addr_ea_l_no_abrt; -uint32_t mem_check_write; -uint32_t mem_check_write_w; -uint32_t mem_check_write_l; - -static uint32_t gen_MEM_LOAD_ADDR_EA_B() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX EAX, B[EDX+EDI]*/ - addbyte(0xb6); - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmembl*/ - addlong((uint32_t)readmemb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*MOVZX EAX, AL*/ - addbyte(0xb6); - addbyte(0xc0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_LOAD_ADDR_EA_W() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/ - addbyte(0xb7); - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemwl*/ - addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*MOVZX EAX, AX*/ - addbyte(0xb7); - addbyte(0xc0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_LOAD_ADDR_EA_L() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemll*/ - addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_LOAD_ADDR_EA_Q() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+4+1); - addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ - addbyte(0x04); - addbyte(0x3a); - addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/ - addbyte(0x54); - addbyte(0x3a); - addbyte(4); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemql*/ - addlong((uint32_t)readmemql - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_B() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x88); /*MOV [EDI+ESI],CL*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememb386l*/ - addlong((uint32_t)writememb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_W() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x66); /*MOV [EDI+ESI],CX*/ - addbyte(0x89); - addbyte(0x04 | (REG_CX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememwl*/ - addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_L() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x89); /*MOV [EDI+ESI],ECX*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememll*/ - addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_Q() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = EBX/ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EDX, ESI*/ - addbyte(0xf2); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+4+1); - addbyte(0x89); /*MOV [EDI+ESI],EBX*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/ - addbyte(0x44 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(4); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x52); /*PUSH EDX*/ - addbyte(0xe8); /*CALL writememql*/ - addlong((uint32_t)writememql - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 16*/ - addbyte(0xc4); - addbyte(16); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_B_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX ECX, B[EDX+EDI]*/ - addbyte(0xb6); - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmembl*/ - addlong((uint32_t)readmemb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); -#endif - addbyte(0x0f); /*MOVZX ECX, AL*/ - addbyte(0xb6); - addbyte(0xc8); -#ifndef RELEASE_BUILD - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_W_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/ - addbyte(0xb7); - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemwl*/ - addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); -#endif - addbyte(0x0f); /*MOVZX ECX, AX*/ - addbyte(0xb7); - addbyte(0xc8); -#ifndef RELEASE_BUILD - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_L_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/ - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x50); /*slowpath: PUSH EAX*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemll*/ - addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0x83); /*SUBL 4,%esp*/ - addbyte(0xEC); - addbyte(4); - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_B_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x88); /*MOV [EDI+ESI],CL*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememb386l*/ - addlong((uint32_t)writememb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_W_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x66); /*MOV [EDI+ESI],CX*/ - addbyte(0x89); - addbyte(0x04 | (REG_CX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememwl*/ - addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_L_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x89); /*MOV [EDI+ESI],ECX*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x50); /*PUSH EAX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememll*/ - addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -static uint32_t gen_MEM_CHECK_WRITE() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal*/ - addlong((uint32_t)mmutranslatereal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -/*static void checkdebug(uint32_t a) -{ - pclog("checkdebug %08x\n", a); -}*/ - -static uint32_t gen_MEM_CHECK_WRITE_W() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x8d); /*LEA ESI, 1[EDI]*/ - addbyte(0x77); - addbyte(0x01); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x89); /*MOV EAX, EDI*/ - addbyte(0xf8); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ - addbyte(0x3c); - addbyte(0xb5); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc7); - /*slowpath_lp:*/ - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal*/ - addlong((uint32_t)mmutranslatereal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x83); /*ADD EDI, 1*/ - addbyte(0xc7); - addbyte(1); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $fff, EDI*/ - addbyte(0xc7); - addlong(0xfff); - addbyte(0x74); /*JE slowpath_lp*/ - addbyte(-33); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_CHECK_WRITE_L() -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x8d); /*LEA ESI, 3[EDI]*/ - addbyte(0x77); - addbyte(0x03); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x89); /*MOV EAX, EDI*/ - addbyte(0xf8); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ - addbyte(0x3c); - addbyte(0xb5); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc7); - /*slowpath_lp:*/ - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal*/ - addlong((uint32_t)mmutranslatereal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x83); /*ADD EDI, 3*/ - addbyte(0xc7); - addbyte(3); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 2-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST EDI, FFC*/ - addbyte(0xc7); - addlong(0xffc); - addbyte(0x74); /*JE slowpath_lp*/ - addbyte(-33); - addbyte(0xc3); /*RET*/ - - return addr; -} - -void codegen_init() -{ - int c; -#if defined(__linux__) || defined(__APPLE__) - void *start; - size_t len; - long pagesize = sysconf(_SC_PAGESIZE); - long pagemask = ~(pagesize - 1); -#endif - -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); -#endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; - -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock & pagemask); - len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif -// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); - - block_current = BLOCK_SIZE; - block_pos = 0; - mem_abrt_rout = (uint32_t)&codeblock[block_current].data[block_pos]; - addbyte(0x83); /*ADDL $16+4,%esp*/ - addbyte(0xC4); - addbyte(0x10+4); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_l = (uint32_t)gen_MEM_LOAD_ADDR_EA_L(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_w = (uint32_t)gen_MEM_LOAD_ADDR_EA_W(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_b = (uint32_t)gen_MEM_LOAD_ADDR_EA_B(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_q = (uint32_t)gen_MEM_LOAD_ADDR_EA_Q(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_l = (uint32_t)gen_MEM_STORE_ADDR_EA_L(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_w = (uint32_t)gen_MEM_STORE_ADDR_EA_W(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_b = (uint32_t)gen_MEM_STORE_ADDR_EA_B(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_q = (uint32_t)gen_MEM_STORE_ADDR_EA_Q(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_b_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_b_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_w_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_w_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_l_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_l_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_check_write = (uint32_t)gen_MEM_CHECK_WRITE(); - block_pos = (block_pos + 15) & ~15; - mem_check_write_w = (uint32_t)gen_MEM_CHECK_WRITE_W(); - block_pos = (block_pos + 15) & ~15; - mem_check_write_l = (uint32_t)gen_MEM_CHECK_WRITE_L(); - - asm( - "fstcw %0\n" - : "=m" (cpu_state.old_npxc) - ); -} - -void codegen_reset() -{ - int c; - - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - mem_reset_page_blocks(); - - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; -} - -void dump_block() -{ -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ -} - -static void add_to_block_list(codeblock_t *block) -{ - codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; - - if (!block->page_mask) - fatal("add_to_block_list - mask = 0\n"); - - if (block_prev) - { - block->next = block_prev; - block_prev->prev = block; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - else - { - block->next = NULL; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - - if (block->next) - { - if (block->next->pc == BLOCK_PC_INVALID) - fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); - } - - if (block->page_mask2) - { - block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; - - if (block_prev) - { - block->next_2 = block_prev; - block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - else - { - block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - } -} - -static void remove_from_block_list(codeblock_t *block, uint32_t pc) -{ - if (!block->page_mask) - return; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; - if (block->next) - block->next->prev = NULL; - else - mem_flush_write_page(block->phys, 0); - } - if (!block->page_mask2) - { - if (block->prev_2 || block->next_2) - fatal("Invalid block_2\n"); - return; - } - - if (block->prev_2) - { - block->prev_2->next_2 = block->next_2; - if (block->next_2) - block->next_2->prev_2 = block->prev_2; - } - else - { -// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; - if (block->next_2) - block->next_2->prev_2 = NULL; - else - mem_flush_write_page(block->phys_2, 0); - } -} - -static void delete_block(codeblock_t *block) -{ - uint32_t old_pc = block->pc; - - if (block == codeblock_hash[HASH(block->phys)]) - codeblock_hash[HASH(block->phys)] = NULL; - - if (block->pc == BLOCK_PC_INVALID) - fatal("Deleting deleted block\n"); - block->pc = BLOCK_PC_INVALID; - - codeblock_tree_delete(block); - remove_from_block_list(block, old_pc); -} - -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) -{ - struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask) - { - delete_block(block); - cpu_recomp_evicted++; - } - if (block == block->next) - fatal("Broken 1\n"); - block = block->next; - } - - block = page->block_2[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask2) - { - delete_block(block); - cpu_recomp_evicted++; - } - if (block == block->next_2) - fatal("Broken 2\n"); - block = block->next_2; - } -} - -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block[(phys_addr >> 10) & 3]) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - - block_current = (block_current + 1) & BLOCK_MASK; - block = &codeblock[block_current]; - -// if (block->pc == 0xb00b4ff5) -// pclog("Init target block\n"); - if (block->pc != BLOCK_PC_INVALID) - { -// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); - delete_block(block); - cpu_recomp_reuse++; - } - block_num = HASH(phys_addr); - codeblock_hash[block_num] = &codeblock[block_current]; - - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->pnt = block_current; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - block->dirty_mask2 = NULL; - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - block->page_mask = 0; - block->flags = CODEBLOCK_STATIC_TOP; - block->status = cpu_cur_status; - - block->was_recompiled = 0; - - recomp_page = block->phys & ~0xfff; - - codeblock_tree_add(block); -} - -void codegen_block_start_recompile(codeblock_t *block) -{ - page_t *page = &pages[block->phys >> 12]; - - if (!page->block[(block->phys >> 10) & 3]) - mem_flush_write_page(block->phys, cs+cpu_state.pc); - - block_num = HASH(block->phys); - block_current = block->pnt; - - if (block->pc != cs + cpu_state.pc || block->was_recompiled) - fatal("Recompile to used block!\n"); - - block->status = cpu_cur_status; - - block_pos = BLOCK_GPF_OFFSET; - addbyte(0xc7); /*MOV [ESP],0*/ - addbyte(0x04); - addbyte(0x24); - addlong(0); - addbyte(0xc7); /*MOV [ESP+4],0*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x04); - addlong(0); - addbyte(0xe8); /*CALL x86gpf*/ - addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $16,%esp*/ - addbyte(0xC4); - addbyte(0x10); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - cpu_block_end = 0; - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x55); /*PUSH EBP*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $16,%esp*/ - addbyte(0xEC); - addbyte(0x10); - addbyte(0xBD); /*MOVL EBP, &cpu_state*/ - addlong(((uintptr_t)&cpu_state) + 128); - -// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num); - - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; - - codegen_block_cycles = 0; - codegen_timing_block_start(); - - codegen_block_ins = 0; - codegen_block_full_ins = 0; - - recomp_page = block->phys & ~0xfff; - - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; - - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - - _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; - - block->TOP = cpu_state.TOP; - block->was_recompiled = 1; - - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); -} - -void codegen_block_remove() -{ - codeblock_t *block = &codeblock[block_current]; - - delete_block(block); - cpu_recomp_removed++; - - recomp_page = -1; -} - -void codegen_block_generate_end_mask() -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; - - block->endpc = codegen_endpc; - - block->page_mask = 0; - start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ block->endpc) & ~0x3ff) - end_pc = 0x3ff & ~15; - else - end_pc = (block->endpc & 0x3ff) & ~15; - if (end_pc < start_pc) - end_pc = 0x3ff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; - -// pclog("block_end: %08x %08x\n", start_pc, end_pc); - for (; start_pc <= end_pc; start_pc++) - { - block->page_mask |= ((uint64_t)1 << start_pc); -// pclog(" %08x %llx\n", start_pc, block->page_mask); - } - - pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; - - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0x3ff) - { - block->phys_2 = get_phys_noabrt(block->endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - start_pc = 0; - end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); - page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - - if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) - mem_flush_write_page(block->phys_2, block->endpc); - - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { -// pclog(" next_2->pc=%08x\n", block->next_2->pc); - if (block->next_2->pc == BLOCK_PC_INVALID) - fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)block->next_2); - } - - block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - } - } - -// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); - recomp_page = -1; -} - -void codegen_block_end() -{ - codeblock_t *block = &codeblock[block_current]; - - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - - if (codegen_block_cycles) - { - addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addlong(codegen_block_cycles); - } - if (codegen_block_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(cpu_recomp_ins)); - addlong(codegen_block_ins); - } -#if 0 - if (codegen_block_full_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x05); - addlong((uint32_t)&cpu_recomp_full_ins); - addlong(codegen_block_full_ins); - } -#endif - addbyte(0x83); /*ADDL $16,%esp*/ - addbyte(0xC4); - addbyte(0x10); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - remove_from_block_list(block, block->pc); - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - codegen_block_generate_end_mask(); - add_to_block_list(block); -// pclog("End block %i\n", block_num); - - if (!(block->flags & CODEBLOCK_HAS_FPU)) - block->flags &= ~CODEBLOCK_STATIC_TOP; -} - -void codegen_flush() -{ - return; -} - -static int opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ -}; -int opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ -}; - -void codegen_debug() -{ - if (output) - { - pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, cpu_state.pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); - } -} - -static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - if (!cpu_mod && cpu_rm == 6) - { - addbyte(0xC7); /*MOVL $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } - else - { - switch (cpu_mod) - { - case 0: - addbyte(0xa1); /*MOVL *mod1add[0][cpu_rm], %eax*/ - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - break; - case 1: - addbyte(0xb8); /*MOVL ,%eax*/ - addlong((uint32_t)(int8_t)(rmdat >> 8));// pc++; - addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - (*op_pc)++; - break; - case 2: - addbyte(0xb8); /*MOVL ,%eax*/ - addlong((fetchdat >> 8) & 0xffff);// pc++; - addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - (*op_pc) += 2; - break; - } - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); - - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - op_ea_seg = &_ss; - } - return op_ea_seg; -} - -static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - uint32_t new_eaaddr; - - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; - (*op_pc)++; - - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL ,%eax*/ - addlong(new_eaaddr);// pc++; - (*op_pc) += 4; - } - else - { - addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - } - break; - case 1: - new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); - addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc) += 4; - break; - } - if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); - break; - case 1: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - case 2: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0xC1); addbyte(0xE3); addbyte(2); /*SHL $2,%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - case 3: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0xC1); addbyte(0xE3); addbyte(3); /*SHL $2,%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - } - } - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); - } - else - { - if (!cpu_mod && cpu_rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[cpu_rm].l)); -// addbyte(0xa1); /*MOVL regs[cpu_rm].l, %eax*/ -// addlong((uint32_t)&cpu_state.regs[cpu_rm].l); - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &_ss; - if (cpu_mod == 1) - { - addbyte(0x05); - addlong((uint32_t)(int8_t)(fetchdat >> 8)); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x05); - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); - } - return op_ea_seg; -} - -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t op_32 = use32; - uint32_t op_pc = new_pc; - OpFn *op_table = x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - int over = 0; - int pc_off = 0; - int test_modrm = 1; - int c; - - op_ea_seg = &_ds; - op_ssegs = 0; - op_old_pc = old_pc; - - for (c = 0; c < NR_HOST_REGS; c++) - host_reg_mapping[c] = -1; - mmx_ebx_ecx_loaded = 0; - for (c = 0; c < NR_HOST_XMM_REGS; c++) - host_reg_xmm_mapping[c] = -1; - - codegen_timing_start(); - - while (!over) - { - switch (opcode) - { - case 0x0f: - op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; - - case 0x26: /*ES:*/ - op_ea_seg = &_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &_gs; - op_ssegs = 1; - break; - - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; - - case 0xd8: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - - case 0xf0: /*LOCK*/ - break; - - case 0xf2: /*REPNE*/ - op_table = x86_dynarec_opcodes_REPNE; - recomp_op_table = recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ - op_table = x86_dynarec_opcodes_REPE; - recomp_op_table = recomp_opcodes_REPE; - break; - - default: - goto generate_call; - } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - - op_pc++; - } - -generate_call: - codegen_timing_opcode(opcode, fetchdat, op_32); - - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*Opcode is likely to cause block to exit, update cycle count*/ - if (codegen_block_cycles) - { - addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addlong(codegen_block_cycles); - codegen_block_cycles = 0; - } - if (codegen_block_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(cpu_recomp_ins)); - addlong(codegen_block_ins); - codegen_block_ins = 0; - } -#if 0 - if (codegen_block_full_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x05); - addlong((uint32_t)&cpu_recomp_full_ins); - addlong(codegen_block_full_ins); - codegen_block_full_ins = 0; - } -#endif - } - - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; - } - - if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); - if (new_pc) - { - if (new_pc != -1) - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, new_pc); - - codegen_block_ins++; - block->ins++; - codegen_block_full_ins++; - codegen_endpc = (cs + cpu_state.pc) + 8; - - return; - } - } - - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; -// if (output) -// pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); - if (op_ssegs != last_ssegs) - { - last_ssegs = op_ssegs; - - addbyte(0xC6); /*MOVB [ssegs],op_ssegs*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ssegs)); - addbyte(op_pc + pc_off); - } - - if (!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(rm_data.rm_mod_reg_data)); - addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); - if (cpu_mod != 3 && (op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - op_pc -= pc_off; - } - - if (op_ea_seg != last_ea_seg) - { - last_ea_seg = op_ea_seg; - addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ea_seg)); - addlong((uint32_t)op_ea_seg); - } - - addbyte(0xC7); /*MOVL pc,new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc + pc_off); - - addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(old_pc); - - if (op_32 != last_op32) - { - last_op32 = op_32; - addbyte(0xC7); /*MOVL $use32,(op32)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(op32)); - addlong(op_32); - } - - addbyte(0xC7); /*MOVL $fetchdat,(%esp)*/ - addbyte(0x04); - addbyte(0x24); - addlong(fetchdat); - - addbyte(0xE8); /*CALL*/ - addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4]))); - - codegen_block_ins++; - - block->ins++; - - addbyte(0x09); /*OR %eax, %eax*/ - addbyte(0xc0); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); - -// addbyte(0xE8); /*CALL*/ -// addlong(((uint8_t *)codegen_debug - (uint8_t *)(&block->data[block_pos + 4]))); - - codegen_endpc = (cs + cpu_state.pc) + 8; -} - -#endif diff --git a/src/codegen_x86.h b/src/codegen_x86.h deleted file mode 100644 index c01608e..0000000 --- a/src/codegen_x86.h +++ /dev/null @@ -1,42 +0,0 @@ -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff -#define BLOCK_START 0 - -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff - -#define HASH(l) ((l) & 0x1ffff) - -#define BLOCK_EXIT_OFFSET 0x7f0 -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) - -#define BLOCK_MAX 1720 - -enum -{ - OP_RET = 0xc3 -}; - -#define NR_HOST_REGS 4 -extern int host_reg_mapping[NR_HOST_REGS]; -#define NR_HOST_XMM_REGS 7 -extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; - -extern uint32_t mem_load_addr_ea_b; -extern uint32_t mem_load_addr_ea_w; -extern uint32_t mem_load_addr_ea_l; -extern uint32_t mem_load_addr_ea_q; -extern uint32_t mem_store_addr_ea_b; -extern uint32_t mem_store_addr_ea_w; -extern uint32_t mem_store_addr_ea_l; -extern uint32_t mem_store_addr_ea_q; - -extern uint32_t mem_load_addr_ea_b_no_abrt; -extern uint32_t mem_store_addr_ea_b_no_abrt; -extern uint32_t mem_load_addr_ea_w_no_abrt; -extern uint32_t mem_store_addr_ea_w_no_abrt; -extern uint32_t mem_load_addr_ea_l_no_abrt; -extern uint32_t mem_store_addr_ea_l_no_abrt; -extern uint32_t mem_check_write; -extern uint32_t mem_check_write_w; -extern uint32_t mem_check_write_l; diff --git a/src/wx-utils.cc b/src/wx-utils.cc index db4c624..561eeea 100644 --- a/src/wx-utils.cc +++ b/src/wx-utils.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include "wx-dialogbox.h" #include "wx-app.h" From ee3f9210dc02e30f75f057ec48fa5bc8fdea5f10 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 23 Jun 2018 19:04:36 +0100 Subject: [PATCH 002/181] Implemented basic register allocation. Mainly handles 'virtual' registers at the moment (eg current and last PC values, segment override status, etc). --- src/Makefile.am | 2 +- src/codegen.c | 105 ++++++++++++++++++++-- src/codegen.h | 1 + src/codegen_backend.c | 3 + src/codegen_backend.h | 2 + src/codegen_backend_arm.c | 9 ++ src/codegen_backend_arm.h | 2 + src/codegen_backend_arm64.c | 9 ++ src/codegen_backend_arm64.h | 2 + src/codegen_backend_arm64_defs.h | 4 +- src/codegen_backend_arm64_uops.c | 52 ++++++++++- src/codegen_backend_arm_defs.h | 2 + src/codegen_backend_arm_uops.c | 51 ++++++++++- src/codegen_backend_x86-64.c | 7 ++ src/codegen_backend_x86-64_uops.c | 135 ++++++++++++++++++++++++++--- src/codegen_backend_x86.c | 7 ++ src/codegen_backend_x86.h | 2 + src/codegen_backend_x86_defs.h | 7 ++ src/codegen_backend_x86_uops.c | 119 ++++++++++++++++++++++--- src/codegen_ir.c | 14 ++- src/codegen_ir_defs.h | 87 +++++++++---------- src/codegen_reg.c | 139 ++++++++++++++++++++++++++++++ src/codegen_reg.h | 99 +++++++++++++++++++++ 23 files changed, 780 insertions(+), 80 deletions(-) create mode 100644 src/codegen_reg.c create mode 100644 src/codegen_reg.h diff --git a/src/Makefile.am b/src/Makefile.am index ff90dfa..c672b74 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_backend.c codegen_ir.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ +cmd640.c codegen.c codegen_backend.c codegen_ir.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ diff --git a/src/codegen.c b/src/codegen.c index 7e0dc9f..238f4f6 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -4,6 +4,8 @@ #include "codegen.h" #include "x86.h" +#include "386_common.h" + #include "codegen_backend.h" #include "codegen_ir.h" @@ -27,6 +29,16 @@ void codegen_timing_set(codegen_timing_t *timing) int codegen_in_recompile; +static int last_op_ssegs; +static x86seg *last_op_ea_seg; +static uint32_t last_op_32; + +void codegen_generate_reset() +{ + last_op_ssegs = -1; + last_op_ea_seg = NULL; + last_op_32 = -1; +} void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { @@ -37,19 +49,99 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t int opcode_shift = 0; int opcode_mask = 0x3ff; uint32_t op_32 = use32; + x86seg *op_ea_seg = &_ds; + int op_ssegs = 0; + int over = 0; + op_ea_seg = &_ds; + while (!over) + { + switch (opcode) + { + case 0x0f: + op_table = x86_dynarec_opcodes_0f; +// recomp_op_table = recomp_opcodes_0f; + over = 1; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &_gs; + op_ssegs = 1; + break; + + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; + + case 0xf0: /*LOCK*/ + break; + + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; +// recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; +// recomp_op_table = recomp_opcodes_REPE; + break; + + default: + goto generate_call; + } + fetchdat = fastreadl(cs + op_pc); +// codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; +// if (!pc_off) + fetchdat >>= 8; + + op_pc++; + } + +generate_call: //pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - uop_STORE_PTR_IMM(ir, &cpu_state.pc, op_pc); - uop_STORE_PTR_IMM(ir, &cpu_state.oldpc, old_pc); - uop_STORE_PTR_IMM(ir, &cpu_state.op32, op_32); - uop_STORE_PTR_IMM(ir, &cpu_state.ea_seg, (uintptr_t)&_ds); - uop_STORE_PTR_IMM_8(ir, &cpu_state.ssegs, 0); + uop_MOV_IMM(ir, IREG_pc, op_pc); + uop_MOV_IMM(ir, IREG_oldpc, old_pc); + if (op_32 != last_op_32) + uop_MOV_IMM(ir, IREG_op32, op_32); +/*Lazy ea_seg/ssegs updating isn't safe until EA calculation is implemented*/ +// if (op_ea_seg != last_op_ea_seg) + uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg); +// if (op_ssegs != last_op_ssegs) + uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); uop_CALL_INSTRUCTION_FUNC(ir, op); + last_op_32 = op_32; + last_op_ea_seg = op_ea_seg; + last_op_ssegs = op_ssegs; //codegen_block_ins++; block->ins++; @@ -57,8 +149,5 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t if (block->ins >= 50) CPU_BLOCK_END(); -// addbyte(0xE8); /*CALL*/ -// addlong(((uint8_t *)codegen_debug - (uint8_t *)(&block->data[block_pos + 4]))); - codegen_endpc = (cs + cpu_state.pc) + 8; } diff --git a/src/codegen.h b/src/codegen.h index def016c..8106c1c 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -325,4 +325,5 @@ extern int codegen_reg_loaded[8]; extern int codegen_in_recompile; +void codegen_generate_reset(); #endif diff --git a/src/codegen_backend.c b/src/codegen_backend.c index a6ece39..2754f5e 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -12,6 +12,7 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_ir.h" +#include "codegen_reg.h" int codegen_flat_ds, codegen_flat_ss; int mmx_ebx_ecx_loaded; @@ -308,6 +309,8 @@ void codegen_block_start_recompile(codeblock_t *block) codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); ir_data = codegen_ir_init(); + codegen_reg_reset(); + codegen_generate_reset(); } diff --git a/src/codegen_backend.h b/src/codegen_backend.h index f281b75..0f73290 100644 --- a/src/codegen_backend.h +++ b/src/codegen_backend.h @@ -63,3 +63,5 @@ struct ir_data_t *codegen_get_ir_data(); typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop); extern const uOpFn uop_handlers[]; + +extern int codegen_host_reg_list[CODEGEN_HOST_REGS]; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 9f0be91..fa0b57c 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -15,6 +15,15 @@ #include #endif +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_R4, + REG_R5, + REG_R6, +// REG_X22, +// REG_X23 +}; + void codegen_backend_init() { int c; diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index 43b3fad..fd63315 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -1,3 +1,5 @@ +#include "codegen_backend_arm_defs.h" + #define BLOCK_SIZE 0x1000 #define BLOCK_MASK 0x0fff #define BLOCK_START 32 diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 5fb6115..e433f43 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -15,6 +15,15 @@ #include #endif +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_X19, + REG_X20, + REG_X21, + REG_X22, + REG_X23 +}; + void codegen_backend_init() { int c; diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h index 6943eb6..21bef6d 100644 --- a/src/codegen_backend_arm64.h +++ b/src/codegen_backend_arm64.h @@ -1,3 +1,5 @@ +#include "codegen_backend_arm64_defs.h" + #define BLOCK_SIZE 0x1000 #define BLOCK_MASK 0x0fff #define BLOCK_START 64 diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index d70990a..56deb25 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -69,4 +69,6 @@ #define REG_ARG2 REG_X2 #define REG_ARG3 REG_X3 -#define REG_CPUSTATE REG_X29 \ No newline at end of file +#define REG_CPUSTATE REG_X29 + +#define CODEGEN_HOST_REGS 5 \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index ee29eb2..2da9964 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -40,6 +40,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) +#define OPCODE_STR_IMM_Q (0x3e4 << 22) #define OPCODE_STRB_IMM (0x0e4 << 22) #define OPCODE_BLR (0xd63f0000) @@ -55,6 +56,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OFFSET12_B(offset) (offset << 10) #define OFFSET12_W(offset) ((offset >> 2) << 10) +#define OFFSET12_Q(offset) ((offset >> 3) << 10) static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) @@ -75,6 +77,7 @@ static int offset_is_19bit(int offset) #define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) #define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) #define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) +#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7)) int add_literal(codeblock_t *block, uint32_t data) { @@ -201,6 +204,12 @@ void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int of fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); } +void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_q(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); +} void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { if (!in_range12_b(offset)) @@ -261,6 +270,20 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_mov_imm(block, uop->dest_reg_a_real, uop->imm_data); + + return 0; +} +static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + int offset = add_literal_q(block, (uintptr_t)uop->p); + host_arm64_LDR_LITERAL_X(block, uop->dest_reg_a_real, offset); + + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, REG_W16, uop->imm_data); @@ -294,7 +317,34 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + + [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM }; +void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_8 - not in range\n"); +} + +void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_32 - not in range\n"); +} + +void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STR_IMM_Q(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_ptr - not in range\n"); +} + #endif diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index a9253ab..f6fe556 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -42,3 +42,5 @@ #define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \ REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) + +#define CODEGEN_HOST_REGS 3 \ No newline at end of file diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 5152fe4..40d1409 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -269,6 +269,28 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, uop->dest_reg_a_real, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, uop->dest_reg_a_real, REG_LITERAL, offset); + } + + return 0; +} +static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + int offset = add_literal(block, (uintptr_t)uop->p); + host_arm_LDR_IMM(block, uop->dest_reg_a_real, REG_LITERAL, offset); + + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { uint32_t arm_imm; @@ -308,7 +330,34 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + + [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM }; +void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +{ + if (in_range(p, &cpu_state)) + host_arm_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_8 - not in range\n"); +} + +void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +{ + if (in_range(p, &cpu_state)) + host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_32 - not in range\n"); +} + +void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +{ + if (in_range(p, &cpu_state)) + host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_ptr - not in range\n"); +} + #endif diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index e123823..36b4567 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -13,6 +13,13 @@ #include #endif +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_EAX, + REG_EBX, + REG_EDX +}; + static void *mem_abrt_rout; void codegen_backend_init() diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index f64636f..e5c231a 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -115,18 +115,95 @@ static void host_x86_JNZ(codeblock_t *block, void *p) codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); } -static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addlong(block, imm_data); -} static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { - codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addbyte(block, imm_data); + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ + codegen_addbyte(block, imm_data); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); + codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t)(uintptr_t)p); + codegen_addbyte(block, imm_data); + } } +static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t)(uintptr_t)p); + codegen_addlong(block, imm_data); + } +} + +static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +static void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x48, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); + codegen_addbyte4(block, 0x48, 0x89, 0x04 | (src_reg << 3), 0x25); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} + + static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { @@ -136,6 +213,15 @@ static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_dat codegen_addlong(block, imm_data); } +static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV64_REG_IMM reg & 8\n"); + codegen_addbyte2(block, 0x48, 0xb8 | reg); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); +} + + static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) { if (!offset) @@ -201,6 +287,17 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); + return 0; +} +static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { if (((uintptr_t)uop->p) >> 32) @@ -226,7 +323,25 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + + [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM }; +void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV8_ABS_REG(block, p, host_reg); +} + +void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV32_ABS_REG(block, p, host_reg); +} + +void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV64_ABS_REG(block, p, host_reg); +} + #endif diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 01a27b2..55430e0 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -13,6 +13,13 @@ #include #endif +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_EAX, + REG_EBX, + REG_EDX +}; + static void *mem_abrt_rout; void codegen_backend_init() diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h index 36361ec..5face4e 100644 --- a/src/codegen_backend_x86.h +++ b/src/codegen_backend_x86.h @@ -1,3 +1,5 @@ +#include "codegen_backend_x86_defs.h" + #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff #define BLOCK_START 0 diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index dcb9a58..f28915e 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -1,3 +1,6 @@ +#ifndef _CODEGEN_BACKEND_X86_DEFS_H_ +#define _CODEGEN_BACKEND_X86_DEFS_H_ + #define REG_EAX 0 #define REG_ECX 1 #define REG_EDX 2 @@ -6,3 +9,7 @@ #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 + +#define CODEGEN_HOST_REGS 3 + +#endif diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 365382b..c19df3e 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -98,17 +98,81 @@ static void host_x86_JNZ(codeblock_t *block, void *p) codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); } -static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addlong(block, imm_data); -} static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { - codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addbyte(block, imm_data); + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ + codegen_addbyte(block, imm_data); + } + else + { + codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addbyte(block, imm_data); + } +} +static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addlong(block, imm_data); + } +} + +static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} +static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} + +static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (!imm_data) + { + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } + else + { + codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); + } } static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) @@ -138,11 +202,17 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_ho codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } +/*void codegen_debug() +{ + pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); +}*/ + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); +// host_x86_CALL(block, codegen_debug); return 0; } @@ -168,6 +238,17 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); + return 0; +} +static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); @@ -189,7 +270,25 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8 + [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + + [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM }; +void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV8_ABS_REG(block, p, host_reg); +} + +void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV32_ABS_REG(block, p, host_reg); +} + +void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV32_ABS_REG(block, p, host_reg); +} + #endif diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 4f8e1b4..692b9b4 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -2,6 +2,7 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_ir.h" +#include "codegen_reg.h" static ir_data_t ir_block; @@ -25,10 +26,21 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) //pclog("uOP %i : %08x\n", c, uop->type); + if (uop->type & UOP_TYPE_PARAMS_REGS) + { + if (uop->dest_reg_a.reg != IREG_INVALID) + { + uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); + } + } + + if (uop->type & UOP_TYPE_BARRIER) + codegen_reg_flush(ir, block); + uop_handlers[uop->type & UOP_MASK](block, uop); } codegen_backend_epilogue(block); -// fatal("IR compilation complete\n"); + //fatal("IR compilation complete\n"); } diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 9293447..5bb310a 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -1,45 +1,10 @@ #ifndef _CODEGEN_IR_DEFS_ #define _CODEGEN_IR_DEFS_ -#define IREG_L (0 << 6) -#define IREG_W (1 << 6) -#define IREG_B (2 << 6) -#define IREG_BH (3 << 6) - -enum -{ - ireg_EAX = 0, - ireg_ECX = 1, - ireg_EDX = 2, - ireg_EBX = 3, - ireg_ESP = 4, - ireg_EBP = 5, - ireg_ESI = 6, - ireg_EDI = 7, - - ireg_flags_op = 8, - ireg_flags_reg = 9, - ireg_flags_op1 = 10, - ireg_flags_op2 = 11, - - ireg_flags_pc = 12, - ireg_flags_oldpc = 13, - - ireg_eaaddr = 14, - - /*Temporary registers are stored on the stack, and are not guaranteed to - be preserved across uOPs. They will not be written back if they will - not be read again.*/ - ireg_temp0 = 16, - ireg_temp1 = 17, - ireg_temp2 = 18, - ireg_temp3 = 19 -}; +#include "codegen_reg.h" #define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8)) -#define UOP_REG_UNUSED 0xffff - /*uOP is a barrier. All previous uOPs must have completed before this one executes. All registers must have been written back or discarded*/ #define UOP_TYPE_BARRIER (1 << 31) @@ -65,20 +30,23 @@ enum #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) #define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) +#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) +#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) -#define UOP_MAX 0x14 +#define UOP_MAX 0x22 #define UOP_MASK 0xffff typedef struct uop_t { uint32_t type; - uint16_t dest_reg_a; - uint16_t src_reg_a; - uint16_t src_reg_b; - uint16_t src_reg_c; + ir_reg_t dest_reg_a; + ir_reg_t src_reg_a; + ir_reg_t src_reg_b; + ir_reg_t src_reg_c; uint32_t imm_data; void *p; + ir_host_reg_t dest_reg_a_real; } uop_t; #define UOP_NR_MAX 4096 @@ -98,20 +66,38 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop = &ir->uops[ir->wr_pos++]; - uop->dest_reg_a = UOP_REG_UNUSED; - uop->src_reg_a = UOP_REG_UNUSED; - uop->src_reg_b = UOP_REG_UNUSED; - uop->src_reg_c = UOP_REG_UNUSED; + uop->dest_reg_a = invalid_ir_reg; + uop->src_reg_a = invalid_ir_reg; + uop->src_reg_b = invalid_ir_reg; + uop->src_reg_c = invalid_ir_reg; return uop; } -static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, uint16_t src_reg_a) +static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) { uop_t *uop = uop_alloc(ir); uop->type = uop_type; - uop->src_reg_a = src_reg_a; + uop->src_reg_a = codegen_reg_read(src_reg_a); +} + +static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->imm_data = imm; +} + +static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->p = p; } static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) @@ -146,7 +132,14 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) +#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) + #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) +void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); + #endif diff --git a/src/codegen_reg.c b/src/codegen_reg.c new file mode 100644 index 0000000..f9e3e36 --- /dev/null +++ b/src/codegen_reg.c @@ -0,0 +1,139 @@ +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_ir_defs.h" +#include "codegen_reg.h" + +uint8_t reg_last_version[IREG_COUNT]; +uint8_t reg_version_refcount[IREG_COUNT][256]; + +ir_reg_t invalid_ir_reg = {IREG_INVALID}; + +ir_reg_t host_regs[CODEGEN_HOST_REGS]; + +enum +{ + REG_BYTE, + REG_WORD, + REG_DWORD, + REG_QWORD, + REG_POINTER +}; + +struct +{ + int native_size; + void *p; +} ireg_data[IREG_COUNT] = +{ + [IREG_EAX] = {REG_DWORD, &EAX}, + [IREG_ECX] = {REG_DWORD, &ECX}, + [IREG_EDX] = {REG_DWORD, &EDX}, + [IREG_EBX] = {REG_DWORD, &EBX}, + [IREG_ESP] = {REG_DWORD, &ESP}, + [IREG_EBP] = {REG_DWORD, &EBP}, + [IREG_ESI] = {REG_DWORD, &ESI}, + [IREG_EDI] = {REG_DWORD, &EDI}, + + [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op}, + [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res}, + [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1}, + [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2}, + + [IREG_pc] = {REG_DWORD, &cpu_state.pc}, + [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc}, + + [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr}, + [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg}, + + [IREG_op32] = {REG_DWORD, &cpu_state.op32}, + [IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs}, + + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + [IREG_temp0] = {REG_DWORD, NULL}, + [IREG_temp1] = {REG_DWORD, NULL}, + [IREG_temp2] = {REG_DWORD, NULL}, + [IREG_temp3] = {REG_DWORD, NULL} +}; + +void codegen_reg_reset() +{ + int c; + + for (c = 0; c < IREG_COUNT; c++) + { + reg_last_version[c] = 0; + reg_version_refcount[c][0] = 0; + } + for (c = 0; c < CODEGEN_HOST_REGS; c++) + host_regs[c] = invalid_ir_reg; +} + +static inline int ir_reg_is_invalid(ir_reg_t ir_reg) +{ + return (ir_reg.reg == IREG_INVALID); +} + +static void codegen_reg_writeback(codeblock_t *block, int c) +{ + int ir_reg = host_regs[c].reg; + + switch (ireg_data[ir_reg].native_size) + { + case REG_BYTE: + codegen_direct_write_8(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + break; + + case REG_DWORD: + codegen_direct_write_32(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + break; + + case REG_POINTER: + codegen_direct_write_ptr(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + break; + + default: + fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); + } + + host_regs[c] = invalid_ir_reg; +} + +ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) +{ + int c; + + /*Search for unused registers*/ + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (ir_reg_is_invalid(host_regs[c])) + break; + } + + if (c == CODEGEN_HOST_REGS) + { + c = 0; + codegen_reg_writeback(block, c); +// fatal("codegen_reg_alloc_write_reg - out of registers\n"); + } + + host_regs[c].reg = ir_reg.reg; + host_regs[c].version = ir_reg.version; + + return codegen_host_reg_list[c]; +} + +void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) +{ + int c; + + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (!ir_reg_is_invalid(host_regs[c])) + { + codegen_reg_writeback(block, c); + } + } +} diff --git a/src/codegen_reg.h b/src/codegen_reg.h new file mode 100644 index 0000000..1b8bd06 --- /dev/null +++ b/src/codegen_reg.h @@ -0,0 +1,99 @@ +#ifndef _CODEGEN_REG_H_ +#define _CODEGEN_REG_H_ + +#define IREG_SIZE_L (0 << 6) +#define IREG_SIZE_W (1 << 6) +#define IREG_SIZE_B (2 << 6) +#define IREG_SIZE_BH (3 << 6) + +enum +{ + IREG_EAX = 0, + IREG_ECX = 1, + IREG_EDX = 2, + IREG_EBX = 3, + IREG_ESP = 4, + IREG_EBP = 5, + IREG_ESI = 6, + IREG_EDI = 7, + + IREG_flags_op = 8, + IREG_flags_res = 9, + IREG_flags_op1 = 10, + IREG_flags_op2 = 11, + + IREG_pc = 12, + IREG_oldpc = 13, + + IREG_eaaddr = 14, + IREG_ea_seg = 15, + IREG_op32 = 16, + IREG_ssegs = 17, + + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + IREG_temp0 = 20, + IREG_temp1 = 21, + IREG_temp2 = 22, + IREG_temp3 = 23, + + IREG_COUNT, + + IREG_INVALID = 255 +}; + +extern uint8_t reg_last_version[IREG_COUNT]; +extern uint8_t reg_version_refcount[IREG_COUNT][256]; + +typedef struct +{ + uint8_t reg; + uint8_t version; +} ir_reg_t; + +extern ir_reg_t invalid_ir_reg; + +typedef uint8_t ir_host_reg_t; + +static inline ir_reg_t codegen_reg_read(int reg) +{ + ir_reg_t ireg; + + if (reg == IREG_INVALID) + fatal("codegen_reg_read - IREG_INVALID\n"); + + ireg.reg = reg; + ireg.version = reg_last_version[reg]; + reg_version_refcount[ireg.reg][ireg.version]++; + if (!reg_version_refcount[ireg.reg][ireg.version]) + fatal("codegen_reg_read - refcount overflow\n"); + + return ireg; +} + +static inline ir_reg_t codegen_reg_write(int reg) +{ + ir_reg_t ireg; + + if (reg == IREG_INVALID) + fatal("codegen_reg_write - IREG_INVALID\n"); + + ireg.reg = reg; + ireg.version = reg_last_version[reg] + 1; + reg_last_version[reg]++; + if (!reg_last_version[reg]) + fatal("codegen_reg_write - version overflow\n"); + reg_version_refcount[reg][ireg.version] = 0; + + return ireg; +} + +struct ir_data_t; + +void codegen_reg_reset(); +void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block); + +ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); + +#endif From 94fea237b468b1fe1b4e51978d0b258b32092f64 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 28 Jun 2018 22:06:42 +0100 Subject: [PATCH 003/181] Implemented effective address compilation. --- src/386_dynarec_ops.c | 89 +---------- src/codegen.c | 245 +++++++++++++++++++++++++++++- src/codegen_backend_arm.c | 2 - src/codegen_backend_arm64_defs.h | 2 + src/codegen_backend_arm64_uops.c | 107 ++++++++++++- src/codegen_backend_arm_defs.h | 2 + src/codegen_backend_arm_uops.c | 122 +++++++++++++-- src/codegen_backend_x86-64_uops.c | 181 ++++++++++++++++++++-- src/codegen_backend_x86_uops.c | 137 ++++++++++++++++- src/codegen_ir.c | 17 ++- src/codegen_ir_defs.h | 59 ++++++- src/codegen_reg.c | 142 ++++++++++++++++- src/codegen_reg.h | 6 + 13 files changed, 978 insertions(+), 133 deletions(-) diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index 23c8036..5377a27 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -23,64 +23,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; ea_rseg = cpu_state.ea_seg->seg; - if (cpu_rm == 4) - { - uint8_t sib = rmdat >> 8; - - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = cpu_state.regs[sib & 7].l; - cpu_state.pc++; - break; - case 1: - cpu_state.pc++; - cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l; -// cpu_state.pc++; - break; - case 2: - cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; - cpu_state.pc += 5; - break; - } - /*SIB byte present*/ - if ((sib & 7) == 5 && !cpu_mod) - cpu_state.eaaddr = getlong(); - else if ((sib & 6) == 4 && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - if (((sib >> 3) & 7) != 4) - cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); - } - else - { - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - if (cpu_mod == 1) - { - cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); - cpu_state.pc++; - } - else - { - cpu_state.eaaddr += getlong(); - } - } - else if (cpu_rm == 5) - { - cpu_state.eaaddr = getlong(); - } - } if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { uint32_t addr = easeg + cpu_state.eaaddr; @@ -96,33 +38,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat) eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; ea_rseg = cpu_state.ea_seg->seg; - if (!cpu_mod && cpu_rm == 6) - { - cpu_state.eaaddr = getword(); - } - else - { - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = 0; - break; - case 1: - cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++; - break; - case 2: - cpu_state.eaaddr = getword(); - break; - } - cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); - if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - cpu_state.eaaddr &= 0xFFFF; - } if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { uint32_t addr = easeg + cpu_state.eaaddr; @@ -133,8 +48,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat) } } -#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; } -#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1 +#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat); +#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat); #define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32) diff --git a/src/codegen.c b/src/codegen.c index 238f4f6..db29524 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -9,6 +9,8 @@ #include "codegen_backend.h" #include "codegen_ir.h" +int has_ea; + codeblock_t *codeblock; codeblock_t **codeblock_hash; @@ -38,8 +40,211 @@ void codegen_generate_reset() last_op_ssegs = -1; last_op_ea_seg = NULL; last_op_32 = -1; + has_ea = 0; } +static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ +// pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat); + if (!cpu_mod && cpu_rm == 6) + { + uint16_t addr = (fetchdat >> 8) & 0xffff; + uop_MOV_IMM(ir, IREG_eaaddr, addr); + (*op_pc) += 2; + } + else + { + int base_reg, index_reg, offset; + + switch (cpu_rm) + { + case 0: case 1: case 7: + base_reg = IREG_EBX; + break; + case 2: case 3: case 6: + base_reg = IREG_EBP; + break; + case 4: + base_reg = IREG_ESI; + break; + case 5: + base_reg = IREG_EDI; + break; + } + uop_MOV(ir, IREG_eaaddr, base_reg); + + if (!(cpu_rm & 4)) + { + if (!(cpu_rm & 1)) + index_reg = IREG_ESI; + else + index_reg = IREG_EDI; + + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg); + } + + switch (cpu_mod) + { + case 1: + offset = (int)(int8_t)((fetchdat >> 8) & 0xff); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); + (*op_pc)++; + break; + case 2: + offset = (fetchdat >> 8) & 0xffff; + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); + (*op_pc) += 2; + break; + } + + uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + + if (mod1seg[cpu_rm] == &ss && !op_ssegs) + { + op_ea_seg = &_ss; + } + } + + return op_ea_seg; +} + +static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + uint32_t new_eaaddr; + + if (cpu_rm == 4) + { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (cpu_mod) + { + case 0: + if ((sib & 7) == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + (*op_pc) += 4; + } + else + { + uop_MOV(ir, IREG_eaaddr, sib & 7); + } + break; + case 1: + new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + (*op_pc) += 4; + break; + } +// if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ +// { +// addbyte(0x05); +// addlong(stack_offset); +// } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &_ss; + if (((sib >> 3) & 7) != 4) + { + switch (sib >> 6) + { + case 0: + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7); + break; + case 1: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1); + break; + case 2: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2); + break; + case 3: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3); + break; + } + } + } + else + { + if (!cpu_mod && cpu_rm == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + uop_MOV(ir, IREG_eaaddr, cpu_rm); + if (cpu_mod) + { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &_ss; + if (cpu_mod == 1) + { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8)); + (*op_pc)++; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); + (*op_pc) += 4; + } + } + } + return op_ea_seg; +} + +static uint8_t opcode_modrm[256] = +{ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; +static uint8_t opcode_0f_modrm[256] = +{ + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; + void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { codeblock_t *block = &codeblock[block_current]; @@ -52,6 +257,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t x86seg *op_ea_seg = &_ds; int op_ssegs = 0; int over = 0; + int test_modrm = 1; op_ea_seg = &_ds; @@ -127,14 +333,44 @@ generate_call: //pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (!test_modrm || + (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || + (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) + { + //int stack_offset = 0; + +// if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ +// stack_offset = (op_32 & 0x100) ? 4 : 2; + + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; + + uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); + +// op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) + { + op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); +// has_ea = 1; + } + if (cpu_mod != 3 && (op_32 & 0x200)) + { + op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); +// has_ea = 1; + } +// op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); +// op_pc -= pc_off; + } + + uop_MOV_IMM(ir, IREG_pc, op_pc); uop_MOV_IMM(ir, IREG_oldpc, old_pc); if (op_32 != last_op_32) uop_MOV_IMM(ir, IREG_op32, op_32); -/*Lazy ea_seg/ssegs updating isn't safe until EA calculation is implemented*/ -// if (op_ea_seg != last_op_ea_seg) + if (op_ea_seg != last_op_ea_seg) uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg); -// if (op_ssegs != last_op_ssegs) + if (op_ssegs != last_op_ssegs) uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); uop_CALL_INSTRUCTION_FUNC(ir, op); @@ -150,4 +386,7 @@ generate_call: CPU_BLOCK_END(); codegen_endpc = (cs + cpu_state.pc) + 8; + +// if (has_ea) +// fatal("Has EA\n"); } diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index fa0b57c..41aeb71 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -20,8 +20,6 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_R4, REG_R5, REG_R6, -// REG_X22, -// REG_X23 }; void codegen_backend_init() diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 56deb25..1c4de84 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -29,6 +29,7 @@ #define REG_W28 28 #define REG_W29 29 #define REG_W30 30 +#define REG_WZR 31 #define REG_X0 0 #define REG_X1 1 @@ -61,6 +62,7 @@ #define REG_X28 28 #define REG_X29 29 #define REG_X30 30 +#define REG_XZR 31 #define REG_SP 31 diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 2da9964..0845743 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -8,7 +8,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) { - *(uint32_t *)&block->data[block_pos] = val; + *(uint32_t *)&block->data[block_pos] = val; block_pos += 4; if (block_pos >= BLOCK_MAX) { @@ -21,6 +21,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define Rd(x) (x) #define Rn(x) ((x) << 5) #define Rt2(x) ((x) << 10) +#define Rm(x) ((x) << 16) + +#define shift_imm6(x) ((x) << 10) #define DATA_OFFSET_UP (1 << 23) #define DATA_OFFSET_DOWN (0 << 23) @@ -30,6 +33,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define COND_AL (0xe << COND_SHIFT) #define OPCODE_SHIFT 24 +#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) +#define OPCODE_AND_IMM (0x11 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) @@ -37,20 +42,28 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_MOVK_W (0x0e5 << 23) #define OPCODE_MOVZ_W (0x0a5 << 23) +#define OPCODE_LDR_IMM_W (0x2e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) #define OPCODE_STR_IMM_Q (0x3e4 << 22) #define OPCODE_STRB_IMM (0x0e4 << 22) +#define OPCODE_ADD_LSL (0x058 << 21) +#define OPCODE_AND_LSL (0x050 << 21) +#define OPCODE_ORR_LSL (0x150 << 21) + #define OPCODE_BLR (0xd63f0000) #define OPCODE_NOP (0xd503201f) #define OPCODE_RET (0xd65f0000) +#define DATPROC_SHIFT(sh) (sh << 10) +#define DATPROC_IMM_SHIFT(sh) (sh << 22) #define MOV_WIDE_HW(hw) (hw << 21) #define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) -#define IMM16(imm_data) (imm_data << 5) +#define IMM12(imm_data) ((imm_data) << 10) +#define IMM16(imm_data) ((imm_data) << 5) #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) @@ -112,7 +125,39 @@ static inline int imm_is_imm16(uint32_t imm_data) return 1; return 0; } +static inline int imm_is_imm12(uint32_t imm_data) +{ + if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff)) + return 1; + return 0; +} +void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (!(imm_data & 0xff000000)) + { + if (imm_data & 0xfff) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else + { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); +} void host_arm64_BLR(codeblock_t *block, int addr_reg) { @@ -134,6 +179,13 @@ void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, in codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); } +void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_w(offset)) + fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); +} + void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) { int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; @@ -153,6 +205,11 @@ void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offs codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg)); } +void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { int hw; @@ -237,6 +294,30 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) } +static int codegen_ADD(codeblock_t *block, uop_t *uop) +{ + host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} + +static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + return 0; +} + +static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_arm64_call(block, uop->p); @@ -270,6 +351,12 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV(codeblock_t *block, uop_t *uop) +{ + host_arm64_MOV_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0); + + return 0; +} static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, uop->dest_reg_a_real, uop->imm_data); @@ -319,10 +406,24 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + + [UOP_ADD & UOP_MASK] = codegen_ADD, + [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM }; +void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +{ + if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_LDR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_32 - not in range\n"); +} + void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index f6fe556..1fadfa1 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -23,6 +23,8 @@ #define REG_CPUSTATE REG_R10 #define REG_LITERAL REG_R11 +#define REG_TEMP REG_R3 + #define REG_MASK_R0 (1 << REG_R0) #define REG_MASK_R1 (1 << REG_R1) #define REG_MASK_R2 (1 << REG_R2) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 40d1409..a63e17a 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -30,6 +30,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SHIFT 20 #define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) +#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) +#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) +#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) #define OPCODE_B (0xa0 << OPCODE_SHIFT) #define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) #define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) @@ -45,6 +48,18 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define B_OFFSET(x) (((x) >> 2) & 0xffffff) +#define SHIFT_TYPE_SHIFT 5 +#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) +#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) +#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) +#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) + +#define SHIFT_TYPE_IMM (0 << 4) +#define SHIFT_TYPE_REG (1 << 4) + +#define SHIFT_IMM_SHIFT 7 +#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) + static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) { @@ -114,14 +129,49 @@ static inline int in_range(void *addr, void *base) return 1; } +void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { uint32_t arm_imm; - if (!get_arm_imm(imm, &arm_imm)) - fatal("host_arm_ADD_IMM !check_arm_imm %08x\n", imm); + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} - codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); +void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } void host_arm_BLX(codeblock_t *block, int addr_reg) @@ -153,15 +203,20 @@ void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) { uint32_t arm_imm; - if (!get_arm_imm(imm, &arm_imm)) - fatal("host_arm_MOV_IMM !check_arm_imm %08x\n", imm); - - codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, dst_reg, REG_LITERAL, offset); + } } -void host_arm_MOV_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) @@ -204,7 +259,31 @@ void host_arm_call(codeblock_t *block, void *dst_addr) void host_arm_nop(codeblock_t *block) { - host_arm_MOV_REG(block, REG_R0, REG_R0); + host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); +} + +static int codegen_ADD(codeblock_t *block, uop_t *uop) +{ + host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} + +static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + return 0; +} + +static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; } static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) @@ -269,6 +348,13 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0); + + return 0; +} + static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { uint32_t arm_imm; @@ -332,10 +418,24 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + + [UOP_ADD & UOP_MASK] = codegen_ADD, + [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM }; +void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +{ + if (in_range(p, &cpu_state)) + host_arm_LDR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_32 - not in range\n"); +} + void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { if (in_range(p, &cpu_state)) diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index e5c231a..d0b3e00 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -87,6 +87,13 @@ static inline void codegen_addquad(codeblock_t *block, uint64_t val) } } +static int is_imm8(uint32_t imm_data) +{ + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; +} + static inline void call(codeblock_t *block, uintptr_t func) { uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; @@ -104,6 +111,62 @@ static inline void call(codeblock_t *block, uintptr_t func) } } +static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + +static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xe0 | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xe0 | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + +static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | (src_reg_b & 7)); /*ADD dst_reg, src_reg_b*/ +} + static void host_x86_CALL(codeblock_t *block, void *p) { call(block, (uintptr_t)p); @@ -115,13 +178,22 @@ static void host_x86_JNZ(codeblock_t *block, void *p) codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); } +static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); + + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ + (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); +} + static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); if (offset >= -128 && offset < 127) { - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ codegen_addbyte(block, imm_data); } else @@ -139,7 +211,7 @@ static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_dat if (offset >= -128 && offset < 127) { - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addlong(block, imm_data); } else @@ -156,16 +228,19 @@ static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV8_ABS_REG - bad reg\n"); + if (offset >= -128 && offset < 127) { - codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ + codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); } } @@ -173,16 +248,19 @@ static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV32_ABS_REG - bad reg\n"); + if (offset >= -128 && offset < 127) { - codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); } } @@ -190,26 +268,47 @@ static void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV64_ABS_REG - bad reg\n"); + if (offset >= -128 && offset < 127) { - codegen_addbyte4(block, 0x48, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); - codegen_addbyte4(block, 0x48, 0x89, 0x04 | (src_reg << 3), 0x25); /*MOV [p], src_reg*/ + codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); } } +static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + if (dst_reg & 8) + fatal("host_x86_MOV32_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } + else + { + fatal("host_x86_MOV32_REG_ABS - out of range\n"); + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { if (reg & 8) fatal("host_x86_MOV32_REG_IMM reg & 8\n"); - codegen_addbyte(block, 0xb8 | reg); /*MOV reg, imm_data*/ + codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -217,10 +316,17 @@ static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_dat { if (reg & 8) fatal("host_x86_MOV64_REG_IMM reg & 8\n"); - codegen_addbyte2(block, 0x48, 0xb8 | reg); /*MOVQ reg, imm_data*/ + codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ codegen_addquad(block, imm_data); } +static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV32_REG_REG - bad reg\n"); + + codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) { @@ -244,9 +350,42 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) -static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) { - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_TEST32_REG - bad reg\n"); + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ +} + + +static int codegen_ADD(codeblock_t *block, uop_t *uop) +{ + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} + +static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + if (!uop->imm_data) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + else if (uop->imm_data < 4) + host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); + + return 0; +} + +static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; } static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) @@ -287,6 +426,11 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); @@ -325,10 +469,21 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + + [UOP_ADD & UOP_MASK] = codegen_ADD, + [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM }; +void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV32_REG_ABS(block, host_reg, p); +} + void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { host_x86_MOV8_ABS_REG(block, p, host_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index c19df3e..b437185 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -86,6 +86,70 @@ static inline void codegen_addquad(codeblock_t *block, uint64_t val) CPU_BLOCK_END(); } } + +static int is_imm8(uint32_t imm_data) +{ + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; +} + +static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + +static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xe0 | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xe0 | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + +static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | src_reg_b); /*ADD dst_reg, src_reg_b*/ +} + static void host_x86_CALL(codeblock_t *block, void *p) { codegen_addbyte(block, 0xe8); /*CALL*/ @@ -98,6 +162,11 @@ static void host_x86_JNZ(codeblock_t *block, void *p) codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); } +static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ +} + static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -162,6 +231,21 @@ static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) } } +static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (!imm_data) @@ -175,6 +259,11 @@ static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm } } +static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); +} + static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) { if (!offset) @@ -207,6 +296,36 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_ho pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); }*/ +static int codegen_ADD(codeblock_t *block, uop_t *uop) +{ + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} + +static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + if (!uop->imm_data) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + else if (uop->imm_data < 4) + host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); + + return 0; +} + +static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); @@ -238,6 +357,11 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); @@ -272,10 +396,21 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + + [UOP_ADD & UOP_MASK] = codegen_ADD, + [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM }; +void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV32_REG_ABS(block, host_reg, p); +} + void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { host_x86_MOV8_ABS_REG(block, p, host_reg); diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 692b9b4..9099aea 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -4,12 +4,13 @@ #include "codegen_ir.h" #include "codegen_reg.h" +extern int has_ea; static ir_data_t ir_block; ir_data_t *codegen_ir_init() { ir_block.wr_pos = 0; - //pclog("codegen_ir_init\n"); +// pclog("codegen_ir_init %04x:%04x\n", CS,cpu_state.pc); return &ir_block; } @@ -24,10 +25,19 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) { uop_t *uop = &ir->uops[c]; - //pclog("uOP %i : %08x\n", c, uop->type); +// pclog("uOP %i : %08x\n", c, uop->type); if (uop->type & UOP_TYPE_PARAMS_REGS) { + codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b); + if (uop->src_reg_a.reg != IREG_INVALID) + { + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a); + } + if (uop->src_reg_b.reg != IREG_INVALID) + { + uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b); + } if (uop->dest_reg_a.reg != IREG_INVALID) { uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); @@ -42,5 +52,6 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) codegen_backend_epilogue(block); - //fatal("IR compilation complete\n"); +// if (has_ea) +// fatal("IR compilation complete\n"); } diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 5bb310a..d64e926 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -32,8 +32,13 @@ #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) #define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) +#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) +#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) +#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) +#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) +#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) -#define UOP_MAX 0x22 +#define UOP_MAX 0x34 #define UOP_MASK 0xffff @@ -43,10 +48,10 @@ typedef struct uop_t ir_reg_t dest_reg_a; ir_reg_t src_reg_a; ir_reg_t src_reg_b; - ir_reg_t src_reg_c; uint32_t imm_data; void *p; ir_host_reg_t dest_reg_a_real; + ir_host_reg_t src_reg_a_real, src_reg_b_real; } uop_t; #define UOP_NR_MAX 4096 @@ -69,7 +74,7 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop->dest_reg_a = invalid_ir_reg; uop->src_reg_a = invalid_ir_reg; uop->src_reg_b = invalid_ir_reg; - uop->src_reg_c = invalid_ir_reg; +// uop->src_reg_c = invalid_ir_reg; return uop; } @@ -100,6 +105,46 @@ static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int uop->p = p; } +static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg); +} + +static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->dest_reg_a = codegen_reg_write(dest_reg); +} + +static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->imm_data = imm; +} + +static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->imm_data = imm; +} + static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) { uop_t *uop = uop_alloc(ir); @@ -129,15 +174,23 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) +#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) +#define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift) +#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) + #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) #define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) #define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) +void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); + void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index f9e3e36..c2ca44d 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -10,6 +10,9 @@ uint8_t reg_version_refcount[IREG_COUNT][256]; ir_reg_t invalid_ir_reg = {IREG_INVALID}; ir_reg_t host_regs[CODEGEN_HOST_REGS]; +static uint8_t host_reg_dirty[CODEGEN_HOST_REGS]; + +static uint8_t host_regs_locked; enum { @@ -48,6 +51,8 @@ struct [IREG_op32] = {REG_DWORD, &cpu_state.op32}, [IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs}, + + [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data}, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will @@ -76,6 +81,21 @@ static inline int ir_reg_is_invalid(ir_reg_t ir_reg) return (ir_reg.reg == IREG_INVALID); } +static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) +{ + switch (ireg_data[ir_reg.reg].native_size) + { + case REG_DWORD: + codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[ir_reg.reg].p); + break; + + default: + fatal("codegen_reg_load - native_size=%i\n", ireg_data[ir_reg.reg].native_size); + } + + host_regs[c] = ir_reg; +} + static void codegen_reg_writeback(codeblock_t *block, int c) { int ir_reg = host_regs[c].reg; @@ -101,27 +121,135 @@ static void codegen_reg_writeback(codeblock_t *block, int c) host_regs[c] = invalid_ir_reg; } +void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b) +{ + int c; + int dest_reference = 0; + + host_regs_locked = 0; + +/* pclog("alloc_register: dst=%i.%i src_a=%i.%i src_b=%i.%i\n", dest_reg_a.reg, dest_reg_a.version, + src_reg_a.reg, src_reg_a.version, + src_reg_b.reg, src_reg_b.version);*/ + + if (!ir_reg_is_invalid(dest_reg_a)) + { + if (!ir_reg_is_invalid(src_reg_a) && src_reg_a.reg == dest_reg_a.reg && src_reg_a.version == dest_reg_a.version-1) + dest_reference++; + if (!ir_reg_is_invalid(src_reg_b) && src_reg_b.reg == dest_reg_a.reg && src_reg_b.version == dest_reg_a.version-1) + dest_reference++; + } + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (!ir_reg_is_invalid(src_reg_a) && host_regs[c].reg == src_reg_a.reg) + { + if (host_regs[c].version != src_reg_a.version) + fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_a.version\n"); + host_regs_locked |= (1 << c); + } + if (!ir_reg_is_invalid(src_reg_b) && host_regs[c].reg == src_reg_b.reg) + { + if (host_regs[c].version != src_reg_b.version) + fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n"); + host_regs_locked |= (1 << c); + } + if (!ir_reg_is_invalid(dest_reg_a) && host_regs[c].reg == dest_reg_a.reg) + { + if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[host_regs[c].reg][host_regs[c].version] == dest_reference)) + host_regs_locked |= (1 << c); + else + fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", host_regs[c].version, dest_reg_a.version, dest_reference); + } + } +} + +ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg) +{ + int c; + + /*Search for required register*/ + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg && host_regs[c].version == ir_reg.version) + break; + + if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg && reg_version_refcount[host_regs[c].reg][host_regs[c].version]) + fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); + } + + if (c == CODEGEN_HOST_REGS) + { + /*No unused registers. Search for an unlocked register*/ + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (!(host_regs_locked & (1 << c))) + break; + } + if (c == CODEGEN_HOST_REGS) + fatal("codegen_reg_alloc_read_reg - out of registers\n"); + if (host_reg_dirty[c]) + codegen_reg_writeback(block, c); + codegen_reg_load(block, c, ir_reg); + host_regs_locked |= (1 << c); +// fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c); +// codegen_reg_writeback(block, c); + } + + reg_version_refcount[host_regs[c].reg][host_regs[c].version]--; + if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] < 0) + fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); + + host_reg_dirty[c] = 0; +// pclog(" codegen_reg_alloc_read_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); + return codegen_host_reg_list[c]; +} + ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { int c; - /*Search for unused registers*/ + /*Search for previous version in host register*/ for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (ir_reg_is_invalid(host_regs[c])) - break; + if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg) + { + if (host_regs[c].version == ir_reg.version-1) + { + if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] != 0) + fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); + break; + } + } } if (c == CODEGEN_HOST_REGS) { - c = 0; - codegen_reg_writeback(block, c); -// fatal("codegen_reg_alloc_write_reg - out of registers\n"); + /*Search for unused registers*/ + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (ir_reg_is_invalid(host_regs[c])) + break; + } + + if (c == CODEGEN_HOST_REGS) + { + /*No unused registers. Search for an unlocked register*/ + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (!(host_regs_locked & (1 << c))) + break; + } + if (c == CODEGEN_HOST_REGS) + fatal("codegen_reg_alloc_write_reg - out of registers\n"); + if (host_reg_dirty[c]) + codegen_reg_writeback(block, c); + } } host_regs[c].reg = ir_reg.reg; host_regs[c].version = ir_reg.version; - + host_reg_dirty[c] = 1; +// pclog(" codegen_reg_alloc_write_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); return codegen_host_reg_list[c]; } diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 1b8bd06..d1d81a2 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -29,6 +29,8 @@ enum IREG_ea_seg = 15, IREG_op32 = 16, IREG_ssegs = 17, + + IREG_rm_mod_reg = 18, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will @@ -94,6 +96,10 @@ struct ir_data_t; void codegen_reg_reset(); void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block); +/*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/ +void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b); + +ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg); ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); #endif From 93ec6b06927645d2c0a26212f3581b2e6dddf2a0 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 6 Jul 2018 17:50:32 +0100 Subject: [PATCH 004/181] Recompiler now handles FPU prefixes. --- src/codegen.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index db29524..eb7bd78 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -258,6 +258,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t int op_ssegs = 0; int over = 0; int test_modrm = 1; + int pc_off = 0; + + op_ea_seg = &_ds; op_ea_seg = &_ds; @@ -303,6 +306,81 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); break; + case 0xd8: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; +// recomp_op_table = recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; +// recomp_op_table = recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; +// recomp_op_table = recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; +// recomp_op_table = recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; +// recomp_op_table = recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; +// recomp_op_table = recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; +// recomp_op_table = recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; +// recomp_op_table = recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xf0: /*LOCK*/ break; @@ -323,7 +401,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t if (cpu_state.abrt) return; opcode = fetchdat & 0xff; -// if (!pc_off) + if (!pc_off) fetchdat >>= 8; op_pc++; @@ -348,7 +426,7 @@ generate_call: uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); -// op_pc += pc_off; + op_pc += pc_off; if (cpu_mod != 3 && !(op_32 & 0x200)) { op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); @@ -360,11 +438,11 @@ generate_call: // has_ea = 1; } // op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); -// op_pc -= pc_off; + op_pc -= pc_off; } - uop_MOV_IMM(ir, IREG_pc, op_pc); + uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off); uop_MOV_IMM(ir, IREG_oldpc, old_pc); if (op_32 != last_op_32) uop_MOV_IMM(ir, IREG_op32, op_32); From 774f4201ee9239670577e2aaf78982fbbeb0a46c Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 6 Jul 2018 17:51:22 +0100 Subject: [PATCH 005/181] Recompiler now handles instruction and cycle counting. --- src/386_dynarec_ops.c | 2 +- src/codegen.c | 18 +++++++++++++-- src/codegen_accumulate.c | 50 ++++++++++++++++++++++++++++++++++++++++ src/codegen_accumulate.h | 13 +++++++++++ src/codegen_backend.c | 3 +++ src/codegen_ir.c | 2 ++ src/codegen_reg.c | 7 ++++++ src/codegen_reg.h | 11 +++++---- 8 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 src/codegen_accumulate.c create mode 100644 src/codegen_accumulate.h diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index 5377a27..342e138 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -58,7 +58,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) #define OP_TABLE(name) dynarec_ops_ ## name /*Temporary*/ -#define CLOCK_CYCLES(c) cycles -= (c) +#define CLOCK_CYCLES(c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) #include "386_ops.h" diff --git a/src/codegen.c b/src/codegen.c index eb7bd78..87184da 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -6,6 +6,7 @@ #include "386_common.h" +#include "codegen_accumulate.h" #include "codegen_backend.h" #include "codegen_ir.h" @@ -262,7 +263,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t op_ea_seg = &_ds; - op_ea_seg = &_ds; + codegen_timing_start(); while (!over) { @@ -397,7 +398,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t goto generate_call; } fetchdat = fastreadl(cs + op_pc); -// codegen_timing_prefix(opcode, fetchdat); + codegen_timing_prefix(opcode, fetchdat); if (cpu_state.abrt) return; opcode = fetchdat & 0xff; @@ -408,6 +409,19 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t } generate_call: + codegen_timing_opcode(opcode, fetchdat, op_32); + + codegen_accumulate(ACCREG_ins, 1); + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; + + if ((op_table == x86_dynarec_opcodes && + ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || + (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || + (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || + (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) + codegen_accumulate_flush(ir); + //pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; diff --git a/src/codegen_accumulate.c b/src/codegen_accumulate.c new file mode 100644 index 0000000..968b7a5 --- /dev/null +++ b/src/codegen_accumulate.c @@ -0,0 +1,50 @@ +#include "ibm.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" + +static struct +{ + int count; + int dest_reg; +} acc_regs[] = +{ + [ACCREG_ins] = {0, IREG_ins}, + [ACCREG_cycles] = {0, IREG_cycles}, +}; + +void codegen_accumulate(int acc_reg, int delta) +{ + if (acc_reg == ACCREG_cycles) + { +// pclog("cycles %04x:%04x %i\n", CS, cpu_state.pc, delta); +// if (CS == 0x1000 && cpu_state.pc == 0x863) +// fatal("Here\n"); + } + acc_regs[acc_reg].count += delta; +} + +void codegen_accumulate_flush(ir_data_t *ir) +{ + int c; + + for (c = 0; c < ACCREG_COUNT; c++) + { + if (acc_regs[c].count) + { +// if (c == ACCREG_cycles) +// pclog("accumulate %i %i %i\n", c, acc_regs[c].dest_reg, acc_regs[c].count); + uop_ADD_IMM(ir, acc_regs[c].dest_reg, acc_regs[c].dest_reg, acc_regs[c].count); + } + + acc_regs[c].count = 0; + } +} + +void codegen_accumulate_reset() +{ + int c; + + for (c = 0; c < ACCREG_COUNT; c++) + acc_regs[c].count = 0; +} diff --git a/src/codegen_accumulate.h b/src/codegen_accumulate.h new file mode 100644 index 0000000..6c19499 --- /dev/null +++ b/src/codegen_accumulate.h @@ -0,0 +1,13 @@ +enum +{ + ACCREG_ins = 0, + ACCREG_cycles = 1, + + ACCREG_COUNT +}; + +struct ir_data_t; + +void codegen_accumulate(int acc_reg, int delta); +void codegen_accumulate_flush(struct ir_data_t *ir); +void codegen_accumulate_reset(); diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 2754f5e..afc6716 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -10,6 +10,7 @@ #include "386_common.h" #include "codegen.h" +#include "codegen_accumulate.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_reg.h" @@ -310,6 +311,7 @@ void codegen_block_start_recompile(codeblock_t *block) ir_data = codegen_ir_init(); codegen_reg_reset(); + codegen_accumulate_reset(); codegen_generate_reset(); } @@ -410,6 +412,7 @@ void codegen_block_end_recompile(codeblock_t *block) if (!(block->flags & CODEBLOCK_HAS_FPU)) block->flags &= ~CODEBLOCK_STATIC_TOP; + codegen_accumulate_flush(ir_data); codegen_ir_compile(ir_data, block); } diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 9099aea..36bea69 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -50,6 +50,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) uop_handlers[uop->type & UOP_MASK](block, uop); } + codegen_reg_flush(ir, block); + codegen_backend_epilogue(block); // if (has_ea) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index c2ca44d..e8e1410 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -54,6 +54,9 @@ struct [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data}, + [IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins}, + [IREG_cycles] = {REG_DWORD, &cpu_state._cycles}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ @@ -73,7 +76,10 @@ void codegen_reg_reset() reg_version_refcount[c][0] = 0; } for (c = 0; c < CODEGEN_HOST_REGS; c++) + { host_regs[c] = invalid_ir_reg; + host_reg_dirty[c] = 0; + } } static inline int ir_reg_is_invalid(ir_reg_t ir_reg) @@ -119,6 +125,7 @@ static void codegen_reg_writeback(codeblock_t *block, int c) } host_regs[c] = invalid_ir_reg; + host_reg_dirty[c] = 0; } void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index d1d81a2..e854fe1 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -31,14 +31,17 @@ enum IREG_ssegs = 17, IREG_rm_mod_reg = 18, + + IREG_ins = 19, + IREG_cycles = 20, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - IREG_temp0 = 20, - IREG_temp1 = 21, - IREG_temp2 = 22, - IREG_temp3 = 23, + IREG_temp0 = 21, + IREG_temp1 = 22, + IREG_temp2 = 23, + IREG_temp3 = 24, IREG_COUNT, From dc2afee95757a3f4d658d122a8d717fb0e29c1f4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 6 Jul 2018 17:52:33 +0100 Subject: [PATCH 006/181] ARM UOP_ADD_IMM can now generate SUB instructions to better handle negative data. --- src/codegen_backend_arm_uops.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index a63e17a..a4611d0 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -42,6 +42,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) #define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) +#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) #define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) #define OPCODE_BLX 0xe12fff30 @@ -131,12 +132,17 @@ static inline int in_range(void *addr, void *base) void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) + if ((int32_t)imm < 0) + { + host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm); + } + else if (get_arm_imm(imm, &arm_imm)) { codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); } @@ -238,10 +244,25 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm { uint32_t arm_imm; - if (!get_arm_imm(imm, &arm_imm)) - fatal("host_arm_SUB_IMM !check_arm_imm %08x\n", imm); + if ((int32_t)imm < 0) + { + host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm); + } + else if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} - codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); +void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) From d666c0aeb964bd4b42a9ee02d115b152ec9ca8a8 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 6 Jul 2018 17:53:11 +0100 Subject: [PATCH 007/181] ARM64 UOP_ADD_IMM can now generate SUB instructions to better handle negative data. --- src/codegen_backend_arm64_uops.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 0845743..ea70050 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -38,6 +38,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) +#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_MOVK_W (0x0e5 << 23) #define OPCODE_MOVZ_W (0x0a5 << 23) @@ -52,6 +53,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ADD_LSL (0x058 << 21) #define OPCODE_AND_LSL (0x050 << 21) #define OPCODE_ORR_LSL (0x150 << 21) +#define OPCODE_SUB_LSL (0x258 << 21) #define OPCODE_BLR (0xd63f0000) #define OPCODE_NOP (0xd503201f) @@ -132,9 +134,15 @@ static inline int imm_is_imm12(uint32_t imm_data) return 0; } +void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); + void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (!(imm_data & 0xff000000)) + if ((int32_t)imm_data < 0) + { + host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); + } + else if (!(imm_data & 0xff000000)) { if (imm_data & 0xfff) codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); @@ -274,6 +282,26 @@ void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int off codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); } +void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if ((int32_t)imm_data < 0) + { + host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); + } + else if (!(imm_data & 0xff000000)) + { + if (imm_data & 0xfff) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else + { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} void host_arm64_call(codeblock_t *block, void *dst_addr) { From ced37ac545cc36ccbc5e5886fbb92ac0697cdafa Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 6 Jul 2018 17:53:58 +0100 Subject: [PATCH 008/181] Hacked in quick ARM64 UOP_AND_IMM handling of immediate 0xffff. --- src/codegen_backend_arm64_uops.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index ea70050..f52b465 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -34,12 +34,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) -#define OPCODE_AND_IMM (0x11 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) +#define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_MOVK_W (0x0e5 << 23) #define OPCODE_MOVZ_W (0x0a5 << 23) @@ -67,6 +67,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define IMM12(imm_data) ((imm_data) << 10) #define IMM16(imm_data) ((imm_data) << 5) +#define IMMN(immn) ((immn) << 22) +#define IMMR(immr) ((immr) << 16) +#define IMMS(imms) ((imms) << 10) + #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) #define OFFSET12_B(offset) (offset << 10) @@ -163,8 +167,15 @@ void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } void host_arm64_BLR(codeblock_t *block, int addr_reg) From 67804322b6d97d9d9fe8ee94b584d8086e4d0d24 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 6 Jul 2018 17:54:17 +0100 Subject: [PATCH 009/181] Add codegen_accumulate.c to Makefile.am. --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index c672b74..e0b6458 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_backend.c codegen_ir.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ +cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ From fc27be592cbf548168853b37ffc08c159ed72f8c Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 8 Jul 2018 16:36:11 +0100 Subject: [PATCH 010/181] Added recompiled versions of immediate->reg and reg->reg versions of MOV, ADD, SUB, CMP, AND, OR and XOR. --- src/Makefile.am | 2 +- src/codegen.c | 39 ++-- src/codegen_backend_arm64_uops.c | 116 +++++++++++- src/codegen_backend_arm_uops.c | 107 ++++++++++- src/codegen_backend_x86-64_uops.c | 175 +++++++++++++++++- src/codegen_backend_x86_uops.c | 218 ++++++++++++++++++++--- src/codegen_ir_defs.h | 25 ++- src/codegen_ops.c | 54 ++++++ src/codegen_ops.h | 10 +- src/codegen_ops_arith.c | 285 ++++++++++++++++++++++++++++++ src/codegen_ops_arith.h | 14 ++ src/codegen_ops_logic.c | 129 ++++++++++++++ src/codegen_ops_logic.h | 11 ++ src/codegen_ops_mov.c | 48 +++++ src/codegen_ops_mov.h | 3 + src/codegen_reg.c | 2 +- src/codegen_reg.h | 2 + 17 files changed, 1169 insertions(+), 71 deletions(-) create mode 100644 src/codegen_ops.c create mode 100644 src/codegen_ops_arith.c create mode 100644 src/codegen_ops_arith.h create mode 100644 src/codegen_ops_logic.c create mode 100644 src/codegen_ops_logic.h create mode 100644 src/codegen_ops_mov.c create mode 100644 src/codegen_ops_mov.h diff --git a/src/Makefile.am b/src/Makefile.am index e0b6458..ab44ff7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ +cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_arith.c codegen_ops_logic.c codegen_ops_mov.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ diff --git a/src/codegen.c b/src/codegen.c index 87184da..2255d85 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -9,6 +9,7 @@ #include "codegen_accumulate.h" #include "codegen_backend.h" #include "codegen_ir.h" +#include "codegen_ops.h" int has_ea; @@ -252,6 +253,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t ir_data_t *ir = codegen_get_ir_data(); uint32_t op_pc = new_pc; OpFn *op_table = x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; int opcode_shift = 0; int opcode_mask = 0x3ff; uint32_t op_32 = use32; @@ -271,7 +273,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t { case 0x0f: op_table = x86_dynarec_opcodes_0f; -// recomp_op_table = recomp_opcodes_0f; + recomp_op_table = NULL;//recomp_opcodes_0f; over = 1; break; @@ -309,7 +311,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t case 0xd8: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; -// recomp_op_table = recomp_opcodes_d8; + recomp_op_table = NULL;//recomp_opcodes_d8; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -319,7 +321,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; -// recomp_op_table = recomp_opcodes_d9; + recomp_op_table = NULL;//recomp_opcodes_d9; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -328,7 +330,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; -// recomp_op_table = recomp_opcodes_da; + recomp_op_table = NULL;//recomp_opcodes_da; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -337,7 +339,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; -// recomp_op_table = recomp_opcodes_db; + recomp_op_table = NULL;//recomp_opcodes_db; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -346,7 +348,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; -// recomp_op_table = recomp_opcodes_dc; + recomp_op_table = NULL;//recomp_opcodes_dc; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -356,7 +358,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; -// recomp_op_table = recomp_opcodes_dd; + recomp_op_table = NULL;//recomp_opcodes_dd; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -365,7 +367,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; -// recomp_op_table = recomp_opcodes_de; + recomp_op_table = NULL;//recomp_opcodes_de; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -374,7 +376,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; -// recomp_op_table = recomp_opcodes_df; + recomp_op_table = NULL;//recomp_opcodes_df; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -387,11 +389,11 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t case 0xf2: /*REPNE*/ op_table = x86_dynarec_opcodes_REPNE; -// recomp_op_table = recomp_opcodes_REPNE; + recomp_op_table = NULL;//recomp_opcodes_REPNE; break; case 0xf3: /*REPE*/ op_table = x86_dynarec_opcodes_REPE; -// recomp_op_table = recomp_opcodes_REPE; + recomp_op_table = NULL;//recomp_opcodes_REPE; break; default: @@ -421,8 +423,21 @@ generate_call: (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) codegen_accumulate_flush(ir); +// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) + { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](block, ir, opcode, fetchdat, op_32, op_pc); + if (new_pc) + { + if (new_pc != -1) + uop_MOV_IMM(ir, IREG_pc, new_pc); - //pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); + codegen_endpc = (cs + cpu_state.pc) + 8; + + return; + } + } + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; if (!test_modrm || diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index f52b465..e838e4f 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -40,8 +40,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_AND_IMM (0x024 << 23) +#define OPCODE_EOR_IMM (0x0a4 << 23) #define OPCODE_MOVK_W (0x0e5 << 23) #define OPCODE_MOVZ_W (0x0a5 << 23) +#define OPCODE_ORR_IMM (0x064 << 23) #define OPCODE_LDR_IMM_W (0x2e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) @@ -52,6 +54,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ADD_LSL (0x058 << 21) #define OPCODE_AND_LSL (0x050 << 21) +#define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_SUB_LSL (0x258 << 21) @@ -138,19 +141,26 @@ static inline int imm_is_imm12(uint32_t imm_data) return 0; } +void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if ((int32_t)imm_data < 0) + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) { host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); } else if (!(imm_data & 0xff000000)) { if (imm_data & 0xfff) + { codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else if (imm_data & 0xfff000) codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); } else @@ -177,6 +187,10 @@ void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); } } +void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} void host_arm64_BLR(codeblock_t *block, int addr_reg) { @@ -191,6 +205,23 @@ void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); } +void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { if (!in_range7_x(offset)) @@ -226,7 +257,8 @@ void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offs void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + if (dst_reg != src_m_reg) + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) @@ -262,6 +294,23 @@ void host_arm64_NOP(codeblock_t *block) codegen_addlong(block, OPCODE_NOP); } +void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_RET(codeblock_t *block, int reg) { codegen_addlong(block, OPCODE_RET | Rn(reg)); @@ -295,15 +344,21 @@ void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int off void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if ((int32_t)imm_data < 0) + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) { host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); } else if (!(imm_data & 0xff000000)) { if (imm_data & 0xfff) + { codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else if (imm_data & 0xfff000) codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); } else @@ -313,6 +368,10 @@ void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); } } +void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} void host_arm64_call(codeblock_t *block, void *dst_addr) { @@ -351,6 +410,11 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_AND(codeblock_t *block, uop_t *uop) +{ + host_arm64_AND_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { host_arm64_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); @@ -410,6 +474,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_OR(codeblock_t *block, uop_t *uop) +{ + host_arm64_ORR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} +static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, REG_W16, uop->imm_data); @@ -433,6 +508,28 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SUB(codeblock_t *block, uop_t *uop) +{ + host_arm64_SUB_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} +static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_XOR(codeblock_t *block, uop_t *uop) +{ + host_arm64_EOR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} +static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm64_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, @@ -452,7 +549,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM + [UOP_AND & UOP_MASK] = codegen_AND, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_OR & UOP_MASK] = codegen_OR, + [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, + [UOP_SUB & UOP_MASK] = codegen_SUB, + [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, + [UOP_XOR & UOP_MASK] = codegen_XOR, + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index a4611d0..8215caa 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -34,10 +34,16 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) #define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) #define OPCODE_B (0xa0 << OPCODE_SHIFT) +#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) +#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) +#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) +#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) #define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) #define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) #define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) +#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) #define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) #define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) #define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) @@ -132,13 +138,15 @@ static inline int in_range(void *addr, void *base) void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { uint32_t arm_imm; - if ((int32_t)imm < 0) + if ((int32_t)imm < 0 && imm != 0x80000000) { host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm); } @@ -167,6 +175,10 @@ void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm { codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); } + else if (get_arm_imm(~imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { int offset = add_literal(block, imm); @@ -195,6 +207,27 @@ void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); } +void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); @@ -225,6 +258,27 @@ void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } +void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); @@ -244,7 +298,7 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm { uint32_t arm_imm; - if ((int32_t)imm < 0) + if ((int32_t)imm < 0 && imm != 0x80000000) { host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm); } @@ -288,19 +342,22 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); return 0; } - static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); return 0; } - static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); return 0; } +static int codegen_AND(codeblock_t *block, uop_t *uop) +{ + host_arm_AND_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { host_arm_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); @@ -398,6 +455,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_OR(codeblock_t *block, uop_t *uop) +{ + host_arm_ORR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} +static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { uint32_t arm_imm; @@ -427,6 +495,28 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SUB(codeblock_t *block, uop_t *uop) +{ + host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} +static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_XOR(codeblock_t *block, uop_t *uop) +{ + host_arm_EOR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + return 0; +} +static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, @@ -446,7 +536,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM + [UOP_AND & UOP_MASK] = codegen_AND, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_OR & UOP_MASK] = codegen_OR, + [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, + [UOP_SUB & UOP_MASK] = codegen_SUB, + [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, + [UOP_XOR & UOP_MASK] = codegen_XOR, + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index d0b3e00..4e0d50c 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -11,6 +11,12 @@ #define STACK_ARG2 (8) #define STACK_ARG3 (12) +#define RM_OP_ADD 0x00 +#define RM_OP_OR 0x08 +#define RM_OP_AND 0x20 +#define RM_OP_SUB 0x28 +#define RM_OP_XOR 0x30 + static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { block->data[block_pos++] = val; @@ -118,7 +124,7 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, if (is_imm8(imm_data)) { - codegen_addbyte3(block, 0x83, 0xc0 | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ } else { @@ -129,11 +135,18 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, } else { - codegen_addbyte2(block, 0x81, 0xc0 | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ codegen_addlong(block, imm_data); } } } +static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { @@ -142,7 +155,7 @@ static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, if (is_imm8(imm_data)) { - codegen_addbyte3(block, 0x83, 0xe0 | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ } else { @@ -153,18 +166,17 @@ static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, } else { - codegen_addbyte2(block, 0x81, 0xe0 | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ codegen_addlong(block, imm_data); } } } - -static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n"); - codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | (src_reg_b & 7)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } static void host_x86_CALL(codeblock_t *block, void *p) @@ -348,6 +360,68 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ } } +static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} +static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} + +static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} +static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} + #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) @@ -357,6 +431,37 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ } +static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} +static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} + static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -382,6 +487,12 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_AND(codeblock_t *block, uop_t *uop) +{ + host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} + static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); @@ -442,6 +553,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_OR(codeblock_t *block, uop_t *uop) +{ + host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} +static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { if (((uintptr_t)uop->p) >> 32) @@ -457,6 +579,34 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SUB(codeblock_t *block, uop_t *uop) +{ + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + + host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real); + return 0; +} +static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + + host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_XOR(codeblock_t *block, uop_t *uop) +{ + host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} +static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, @@ -476,7 +626,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM + [UOP_AND & UOP_MASK] = codegen_AND, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_OR & UOP_MASK] = codegen_OR, + [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, + [UOP_SUB & UOP_MASK] = codegen_SUB, + [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, + [UOP_XOR & UOP_MASK] = codegen_XOR, + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index b437185..9dac085 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -11,6 +11,12 @@ #define STACK_ARG2 (8) #define STACK_ARG3 (12) +#define RM_OP_ADD 0x00 +#define RM_OP_OR 0x08 +#define RM_OP_AND 0x20 +#define RM_OP_SUB 0x28 +#define RM_OP_XOR 0x30 + static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { block->data[block_pos++] = val; @@ -101,7 +107,7 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, if (is_imm8(imm_data)) { - codegen_addbyte3(block, 0x83, 0xc0 | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ } else { @@ -112,31 +118,7 @@ static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, } else { - codegen_addbyte2(block, 0x81, 0xc0 | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } - } -} - -static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - { - codegen_addbyte3(block, 0x83, 0xe0 | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else - { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xe0 | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ codegen_addlong(block, imm_data); } } @@ -147,7 +129,39 @@ static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ if (dst_reg != src_reg_a) fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); - codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | src_reg_b); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} + +static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + +static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } static void host_x86_CALL(codeblock_t *block, void *p) @@ -284,13 +298,109 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ } } +static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} +static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + +static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} + static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } +static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} + +static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + { + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } + else + { + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } + } +} + + /*void codegen_debug() { pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); @@ -320,6 +430,12 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_AND(codeblock_t *block, uop_t *uop) +{ + host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} + static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); @@ -373,6 +489,17 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_OR(codeblock_t *block, uop_t *uop) +{ + host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} +static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); @@ -384,6 +511,34 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SUB(codeblock_t *block, uop_t *uop) +{ + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + + host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real); + return 0; +} +static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + + host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data); + return 0; +} + +static int codegen_XOR(codeblock_t *block, uop_t *uop) +{ + host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; +} +static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + return 0; +} + const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, @@ -403,7 +558,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM + [UOP_AND & UOP_MASK] = codegen_AND, + [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_OR & UOP_MASK] = codegen_OR, + [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, + [UOP_SUB & UOP_MASK] = codegen_SUB, + [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, + [UOP_XOR & UOP_MASK] = codegen_XOR, + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index d64e926..bac0ab6 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -35,10 +35,17 @@ #define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) #define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) -#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) -#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) +#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) +#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) +#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) +#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) +#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) +#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) +#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) +#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) +#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) -#define UOP_MAX 0x34 +#define UOP_MAX 0x3b #define UOP_MASK 0xffff @@ -175,9 +182,16 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) #define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) +#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) #define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift) -#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) +#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) +#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) +#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) @@ -189,6 +203,7 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) + void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); diff --git a/src/codegen_ops.c b/src/codegen_ops.c new file mode 100644 index 0000000..728c659 --- /dev/null +++ b/src/codegen_ops.c @@ -0,0 +1,54 @@ +#include "ibm.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_arith.h" +#include "codegen_ops_logic.h" +#include "codegen_ops_mov.h" + +RecompOpFn recomp_opcodes[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, ropADD_l_rmw, NULL, ropADD_l_rm, NULL, ropADD_EAX_imm, NULL, NULL, NULL, ropOR_l_rmw, NULL, ropOR_l_rm, NULL, ropOR_EAX_imm, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, ropAND_l_rmw, NULL, ropAND_l_rm, NULL, ropAND_EAX_imm, NULL, NULL, NULL, ropSUB_l_rmw, NULL, ropSUB_l_rm, NULL, ropSUB_EAX_imm, NULL, NULL, +/*30*/ NULL, ropXOR_l_rmw, NULL, ropXOR_l_rm, NULL, ropXOR_EAX_imm, NULL, NULL, NULL, ropCMP_l_rmw, NULL, ropCMP_l_rm, NULL, ropCMP_EAX_imm, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, rop81_l, NULL, rop83_l, NULL, NULL, NULL, NULL, NULL, ropMOV_l_r, NULL, ropMOV_r_l, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; diff --git a/src/codegen_ops.h b/src/codegen_ops.h index 7060238..1229ce4 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -3,10 +3,12 @@ #include "codegen.h" -typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block); +struct ir_data_t; + +typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); extern RecompOpFn recomp_opcodes[512]; -extern RecompOpFn recomp_opcodes_0f[512]; +/*extern RecompOpFn recomp_opcodes_0f[512]; extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; extern RecompOpFn recomp_opcodes_da[512]; @@ -15,8 +17,8 @@ extern RecompOpFn recomp_opcodes_dc[512]; extern RecompOpFn recomp_opcodes_dd[512]; extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; -RecompOpFn recomp_opcodes_REPE[512]; -RecompOpFn recomp_opcodes_REPNE[512]; +extern RecompOpFn recomp_opcodes_REPE[512]; +extern RecompOpFn recomp_opcodes_REPNE[512];*/ #define REG_EAX 0 #define REG_ECX 1 diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c new file mode 100644 index 0000000..d516152 --- /dev/null +++ b/src/codegen_ops_arith.c @@ -0,0 +1,285 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_arith.h" + +uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + uint32_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = fastreadl(cs + op_pc + 1); + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + imm = fastreadl(cs + op_pc + 1); + + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + imm = fastreadl(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + imm = fastreadl(cs + op_pc + 1); + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + imm = fastreadl(cs + op_pc + 1); + + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + imm = fastreadl(cs + op_pc + 1); + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + + codegen_flags_changed = 1; + return op_pc + 5; +} +uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + uint32_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + + codegen_flags_changed = 1; + return op_pc + 2; +} diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h new file mode 100644 index 0000000..f219318 --- /dev/null +++ b/src/codegen_ops_arith.h @@ -0,0 +1,14 @@ +uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c new file mode 100644 index 0000000..c4aca26 --- /dev/null +++ b/src/codegen_ops_logic.c @@ -0,0 +1,129 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_logic.h" + +uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h new file mode 100644 index 0000000..127f4c1 --- /dev/null +++ b/src/codegen_ops_logic.h @@ -0,0 +1,11 @@ +uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c new file mode 100644 index 0000000..2266602 --- /dev/null +++ b/src/codegen_ops_mov.c @@ -0,0 +1,48 @@ +#include "ibm.h" + +#include "x86.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mov.h" + +uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); + + return op_pc + 4; +} + + + +uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = (fetchdat >> 3) & 7; + uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); + } + else + return 0; + + return op_pc + 1; +} +uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); + } + else + return 0; + + return op_pc + 1; +} diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h new file mode 100644 index 0000000..c9bafdc --- /dev/null +++ b/src/codegen_ops_mov.h @@ -0,0 +1,3 @@ +uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index e8e1410..164a190 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -200,13 +200,13 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg) host_regs_locked |= (1 << c); // fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c); // codegen_reg_writeback(block, c); + host_reg_dirty[c] = 0; } reg_version_refcount[host_regs[c].reg][host_regs[c].version]--; if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] < 0) fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); - host_reg_dirty[c] = 0; // pclog(" codegen_reg_alloc_read_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); return codegen_host_reg_list[c]; } diff --git a/src/codegen_reg.h b/src/codegen_reg.h index e854fe1..e1b4965 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -48,6 +48,8 @@ enum IREG_INVALID = 255 }; +#define IREG_32(reg) ((reg) + IREG_EAX) + extern uint8_t reg_last_version[IREG_COUNT]; extern uint8_t reg_version_refcount[IREG_COUNT][256]; From e4e0f76d5c545faff67f2c51aa899989133f3512 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 8 Jul 2018 16:36:26 +0100 Subject: [PATCH 011/181] De-duplicate ARM literal pools. --- src/codegen_backend_arm_uops.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 8215caa..372044b 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -75,9 +75,18 @@ void codegen_reset_literal_pool(codeblock_t *block) int add_literal(codeblock_t *block, uint32_t data) { + int c; + if (literal_offset >= 4096) fatal("add_literal - literal pool full\n"); + /*Search for pre-existing value*/ + for (c = 0; c < literal_offset; c += 4) + { + if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data) + return c; + } + *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; literal_offset += 4; From 648aa0e3e83d2b2f081d13a61b4d4aefd5473369 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 17 Jul 2018 22:08:25 +0100 Subject: [PATCH 012/181] Added recompiled versions of 8 and 16 bit immediate->reg and reg->reg versions of MOV, ADD, SUB, CMP, AND, OR and XOR. --- src/codegen.c | 2 +- src/codegen_backend_arm64_defs.h | 2 + src/codegen_backend_arm64_uops.c | 483 +++++++++++++++++++++++- src/codegen_backend_arm_uops.c | 514 ++++++++++++++++++++++++- src/codegen_backend_x86-64_uops.c | 605 ++++++++++++++++++++++++++---- src/codegen_backend_x86_uops.c | 604 +++++++++++++++++++++++++---- src/codegen_ir.c | 4 +- src/codegen_ir_defs.h | 36 +- src/codegen_ops.c | 20 +- src/codegen_ops_arith.c | 484 ++++++++++++++++++++++++ src/codegen_ops_arith.h | 21 ++ src/codegen_ops_logic.c | 234 ++++++++++++ src/codegen_ops_logic.h | 18 + src/codegen_ops_mov.c | 72 ++++ src/codegen_ops_mov.h | 6 + src/codegen_reg.c | 70 ++-- src/codegen_reg.h | 62 ++- 17 files changed, 3006 insertions(+), 231 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 2255d85..512b4b3 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -58,7 +58,7 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin { int base_reg, index_reg, offset; - switch (cpu_rm) + switch (cpu_rm & 7) { case 0: case 1: case 7: base_reg = IREG_EBX; diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 1c4de84..7de61f0 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -73,4 +73,6 @@ #define REG_CPUSTATE REG_X29 +#define REG_TEMP REG_X7 + #define CODEGEN_HOST_REGS 5 \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index e838e4f..b641a4b 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -45,18 +45,25 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_MOVZ_W (0x0a5 << 23) #define OPCODE_ORR_IMM (0x064 << 23) +#define OPCODE_BFI (0x0cc << 22) #define OPCODE_LDR_IMM_W (0x2e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) #define OPCODE_STR_IMM_Q (0x3e4 << 22) #define OPCODE_STRB_IMM (0x0e4 << 22) +#define OPCODE_UBFX (0x14c << 22) #define OPCODE_ADD_LSL (0x058 << 21) +#define OPCODE_ADD_LSR (0x05a << 21) +#define OPCODE_AND_ASR (0x054 << 21) #define OPCODE_AND_LSL (0x050 << 21) +#define OPCODE_AND_ROR (0x056 << 21) #define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_LSL (0x150 << 21) +#define OPCODE_ORR_LSR (0x152 << 21) #define OPCODE_SUB_LSL (0x258 << 21) +#define OPCODE_SUB_LSR (0x25a << 21) #define OPCODE_BLR (0xd63f0000) #define OPCODE_NOP (0xd503201f) @@ -174,13 +181,33 @@ void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } - +void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +//12001c00 S=0 R=7 void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); + } + else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ { codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } + else if (imm_data == 0x0000ff00) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); + } else { host_arm64_mov_imm(block, REG_W16, imm_data); @@ -191,6 +218,19 @@ void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); +} void host_arm64_BLR(codeblock_t *block, int addr_reg) { @@ -261,6 +301,11 @@ void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shif codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { int hw; @@ -300,6 +345,18 @@ void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t { codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); } + else if (imm_data == 0xffff0000) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f)); + } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } else { host_arm64_mov_imm(block, REG_W16, imm_data); @@ -372,6 +429,15 @@ void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); +} void host_arm64_call(codeblock_t *block, void *dst_addr) { @@ -391,16 +457,83 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) } } +#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_ADD_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_a, 0x0000ff00); + host_arm64_ADD_REG(block, REG_TEMP, REG_TEMP, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ADD_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -412,12 +545,67 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_arm64_AND_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_AND_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff0000); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ASR(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG_ROR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } + else + fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -456,13 +644,65 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_arm64_MOV_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) + { + host_arm64_BFI(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, uop->dest_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_arm64_mov_imm(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size)) + { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size)) + { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV_IMM %x\n", uop->dest_reg_a_real); return 0; } @@ -474,14 +714,92 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); + } + else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_arm64_ORR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -510,23 +828,157 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - host_arm64_SUB_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_SUB_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_arm64_EOR_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_EOR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -545,7 +997,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 372044b..17fd823 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -41,9 +41,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) #define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) +#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) #define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) #define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) #define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) #define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) #define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) #define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) @@ -51,7 +54,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) #define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) -#define OPCODE_BLX 0xe12fff30 +#define OPCODE_BFI 0xe7c00010 +#define OPCODE_BLX 0xe12fff30 +#define OPCODE_UADD8 0xe6500f90 +#define OPCODE_UADD16 0xe6500f10 +#define OPCODE_USUB8 0xe6500ff0 +#define OPCODE_USUB16 0xe6500f70 +#define OPCODE_UXTB 0xe6ef0070 +#define OPCODE_UXTH 0xe6ff0070 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -66,6 +76,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define SHIFT_IMM_SHIFT 7 #define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) + +#define BFI_lsb(lsb) ((lsb) << 7) +#define BFI_msb(msb) ((msb) << 16) + +#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) + +#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) @@ -201,6 +219,20 @@ void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); +} + +void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} +void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + void host_arm_BLX(codeblock_t *block, int addr_reg) { codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); @@ -266,6 +298,20 @@ void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif { codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } +void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); +} + +void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +{ + codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); +} + +void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); +} void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { @@ -288,6 +334,11 @@ void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); @@ -327,12 +378,45 @@ void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr { codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) { codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); } +void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} + +void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} void host_arm_call(codeblock_t *block, void *dst_addr) { @@ -346,15 +430,85 @@ void host_arm_nop(codeblock_t *block) host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); } +#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0xf) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) + static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_UADD16(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_AND_IMM(block, REG_TEMP, src_reg_b, 0x0000ff00); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); +// host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); +// return 0; + + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && src_reg == dest_reg) + { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_UADD16(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && src_reg == dest_reg) + { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) + { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data << 8); + host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + } + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; + } static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { @@ -364,12 +518,69 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_arm_AND_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_AND_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 24); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 0); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_arm_AND_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -437,22 +648,75 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_arm_MOV_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) + { + host_arm_BFI(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, uop->dest_reg_a_real, uop->imm_data); - else + if (REG_IS_L(dest_size)) { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, uop->dest_reg_a_real, REG_LITERAL, offset); + uint32_t arm_imm; + + if (get_arm_imm(uop->imm_data, &arm_imm)) + host_arm_MOV_IMM(block, dest_reg, uop->imm_data); + else + { + int offset = add_literal(block, uop->imm_data); + host_arm_LDR_IMM(block, dest_reg, REG_LITERAL, offset); + } } + else if (REG_IS_W(dest_size)) + { + host_arm_MOVW_IMM(block, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size)) + { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x000000ff); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size)) + { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x0000ff00); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data << 8); + } + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); return 0; } @@ -464,14 +728,92 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_arm_UXTB(block, dest_reg, src_reg, 0); + } + else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, dest_reg, src_reg, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, dest_reg, src_reg, 0); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_arm_ORR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_arm_ORR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -506,23 +848,158 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_SUB_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; + +// host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); +// return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - host_arm_SUB_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_arm_EOR_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) + { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_arm_EOR_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -541,6 +1018,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 4e0d50c..ff1f31f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -117,29 +117,66 @@ static inline void call(codeblock_t *block, uintptr_t func) } } +static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ +} +static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} +static void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) @@ -148,29 +185,66 @@ static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } +static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ +} +static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} +static void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) @@ -316,6 +390,19 @@ static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) } } +static void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg >= 8) + fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ +} +static void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); +} static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { if (reg & 8) @@ -332,6 +419,20 @@ static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_dat codegen_addquad(block, imm_data); } +static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV8_REG_REG - bad reg\n"); + + codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV16_REG_REG - bad reg\n"); + + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) @@ -360,29 +461,79 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ } } +static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ +} +static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} +static void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) @@ -391,33 +542,70 @@ static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } +static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ +} +static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} +static void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } @@ -431,29 +619,66 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ } +static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ +} +static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} +static void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) @@ -462,16 +687,56 @@ static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } +#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_ADD16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_ADD8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -489,13 +754,47 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_AND32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_AND16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_AND8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_AND32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_AND16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_AND8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -539,12 +838,46 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); + return 0; } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) @@ -552,15 +885,66 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_OR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_OR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_OR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -581,29 +965,103 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real); return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data); return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_XOR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_XOR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -622,7 +1080,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 9dac085..0f68a25 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -100,30 +100,67 @@ static int is_imm8(uint32_t imm_data) return 0; } +static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ +} +static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} +static void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -132,30 +169,67 @@ static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } +static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ +} +static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} +static void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -260,6 +334,23 @@ static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addlong(block, (uint32_t)p); } } + +static void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ +} +static void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (!imm_data) + { + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } + else + { + codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (!imm_data) @@ -273,6 +364,14 @@ static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm } } +static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); +} +static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); +} static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); @@ -298,6 +397,29 @@ static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_ } } +static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +static void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} +static void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -305,60 +427,121 @@ static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } + +static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ +} +static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ +} +static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } +static void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} +static void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } @@ -368,6 +551,20 @@ static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_ho codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } +static void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} +static void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -376,27 +573,50 @@ static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_ codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } +static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ +} +static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) { if (dst_reg != src_reg) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) - { codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); } else { - if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); } } @@ -406,15 +626,61 @@ static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); }*/ +#define HOST_REG_IS_L(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_L) +#define HOST_REG_IS_W(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_W) +#define HOST_REG_IS_B(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_B && IREG_GET_REG(reg) < 4) +#define HOST_REG_IS_BH(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_BH && IREG_GET_REG(reg) < 4) + +#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) + +#define REG_IS_L(size) (size == IREG_SIZE_L) +#define REG_IS_W(size) (size == IREG_SIZE_W) +#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +#define REG_IS_BH(size) (size == IREG_SIZE_BH) + static int codegen_ADD(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - host_x86_ADD32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_ADD16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_ADD8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -432,13 +698,47 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) static int codegen_AND(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_AND32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_AND16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_AND8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - host_x86_AND32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_AND32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_AND16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_AND8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -475,12 +775,46 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_MOV(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); + return 0; } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) @@ -488,15 +822,66 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); return 0; } +static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_OR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_OR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_OR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_OR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -513,29 +898,103 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) static int codegen_SUB(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + } + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - host_x86_SUB32_REG_REG(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->src_reg_b_real); return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + } + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - host_x86_SUB32_REG_IMM(block, uop->dest_reg_a_real, uop->dest_reg_a_real, uop->imm_data); return 0; } static int codegen_XOR(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - host_x86_XOR32_REG_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_x86_XOR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_x86_XOR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; } @@ -554,6 +1013,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 36bea69..1d89807 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -32,11 +32,11 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b); if (uop->src_reg_a.reg != IREG_INVALID) { - uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a); + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); } if (uop->src_reg_b.reg != IREG_INVALID) { - uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b); + uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); } if (uop->dest_reg_a.reg != IREG_INVALID) { diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index bac0ab6..04ee628 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -27,22 +27,40 @@ #define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a) #define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b) #define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) +/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/ #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) #define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) +/*UOP_MOV_PTR - dest_reg = p*/ #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) +/*UOP_MOV_IMM - dest_reg = imm_data*/ #define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) +/*UOP_MOV - dest_reg = src_reg_a*/ #define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) +/*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/ +#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) +/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) +/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ #define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) +/*UOP_AND - dest_reg = src_reg_a & src_reg_b*/ #define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) +/*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/ #define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) +/*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data) + Intended for EA calcluations, imm_data must be between 0 and 3*/ #define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) +/*UOP_OR - dest_reg = src_reg_a | src_reg_b*/ #define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) +/*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/ #define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) +/*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/ #define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) +/*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/ #define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) +/*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/ #define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) +/*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/ #define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) #define UOP_MAX 0x3b @@ -81,7 +99,6 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop->dest_reg_a = invalid_ir_reg; uop->src_reg_a = invalid_ir_reg; uop->src_reg_b = invalid_ir_reg; -// uop->src_reg_c = invalid_ir_reg; return uop; } @@ -121,6 +138,16 @@ static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int de uop->dest_reg_a = codegen_reg_write(dest_reg); } +static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->imm_data = imm; +} + static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) { uop_t *uop = uop_alloc(ir); @@ -196,9 +223,10 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) -#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) -#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) -#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) +#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) +#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 728c659..caaf3ff 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -10,20 +10,20 @@ RecompOpFn recomp_opcodes[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, NULL, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, +/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -32,20 +32,20 @@ RecompOpFn recomp_opcodes[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, ropADD_l_rmw, NULL, ropADD_l_rm, NULL, ropADD_EAX_imm, NULL, NULL, NULL, ropOR_l_rmw, NULL, ropOR_l_rm, NULL, ropOR_EAX_imm, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, NULL, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, ropAND_l_rmw, NULL, ropAND_l_rm, NULL, ropAND_EAX_imm, NULL, NULL, NULL, ropSUB_l_rmw, NULL, ropSUB_l_rm, NULL, ropSUB_EAX_imm, NULL, NULL, -/*30*/ NULL, ropXOR_l_rmw, NULL, ropXOR_l_rm, NULL, ropXOR_EAX_imm, NULL, NULL, NULL, ropCMP_l_rmw, NULL, ropCMP_l_rm, NULL, ropCMP_EAX_imm, NULL, NULL, +/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, +/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ NULL, rop81_l, NULL, rop83_l, NULL, NULL, NULL, NULL, NULL, ropMOV_l_r, NULL, ropMOV_r_l, NULL, NULL, NULL, NULL, +/*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, +/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index d516152..1e3f226 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -8,6 +8,32 @@ #include "codegen_ops.h" #include "codegen_ops_arith.h" +uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -21,6 +47,70 @@ uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; @@ -54,6 +144,32 @@ uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_AL, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_AX, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -66,6 +182,70 @@ uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; @@ -97,6 +277,32 @@ uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -110,6 +316,70 @@ uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; @@ -143,6 +413,148 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + uint8_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = fastreadb(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*OR*/ + imm = fastreadb(cs + op_pc + 1); + + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: /*AND*/ + imm = fastreadb(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SUB*/ + imm = fastreadb(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x30: /*XOR*/ + imm = fastreadb(cs + op_pc + 1); + + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*CMP*/ + imm = fastreadb(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; + } + + codegen_flags_changed = 1; + return op_pc + 2; +} +uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + uint16_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = fastreadw(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + imm = fastreadw(cs + op_pc + 1); + + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + imm = fastreadw(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + imm = fastreadw(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + imm = fastreadw(cs + op_pc + 1); + + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + imm = fastreadw(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + + codegen_flags_changed = 1; + return op_pc + 3; +} uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; @@ -213,6 +625,78 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_flags_changed = 1; return op_pc + 5; } + +uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + uint16_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index f219318..2faa55d 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -1,14 +1,35 @@ +uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index c4aca26..ad74d7e 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -8,6 +8,28 @@ #include "codegen_ops.h" #include "codegen_ops_logic.h" +uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -19,6 +41,62 @@ uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; @@ -48,6 +126,28 @@ uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -59,6 +159,62 @@ uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 codegen_flags_changed = 1; return op_pc + 4; } +uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; @@ -88,6 +244,28 @@ uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc + 1; } +uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -99,6 +277,62 @@ uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_flags_changed = 1; return op_pc + 4; } +uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h index 127f4c1..cfb7af3 100644 --- a/src/codegen_ops_logic.h +++ b/src/codegen_ops_logic.h @@ -1,11 +1,29 @@ +uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 2266602..b8bb8aa 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -7,6 +7,22 @@ #include "codegen_ops.h" #include "codegen_ops_mov.h" +uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm = fastreadb(cs + op_pc); + + uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); + + return op_pc + 1; +} +uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); + + return op_pc + 2; +} uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { fetchdat = fastreadl(cs + op_pc); @@ -18,6 +34,34 @@ uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 +uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = (fetchdat >> 3) & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + return 0; + + return op_pc + 1; +} +uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = (fetchdat >> 3) & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + return 0; + + return op_pc + 1; +} uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; @@ -32,6 +76,34 @@ uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc + 1; } +uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + return 0; + + return op_pc + 1; +} +uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + return 0; + + return op_pc + 1; +} uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index c9bafdc..cf8b31f 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -1,3 +1,9 @@ +uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 164a190..43027f3 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -84,27 +84,28 @@ void codegen_reg_reset() static inline int ir_reg_is_invalid(ir_reg_t ir_reg) { - return (ir_reg.reg == IREG_INVALID); + return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) { - switch (ireg_data[ir_reg.reg].native_size) + switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { case REG_DWORD: - codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[ir_reg.reg].p); + codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; default: - fatal("codegen_reg_load - native_size=%i\n", ireg_data[ir_reg.reg].native_size); + fatal("codegen_reg_load - native_size=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size); } host_regs[c] = ir_reg; +//pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version); } static void codegen_reg_writeback(codeblock_t *block, int c) { - int ir_reg = host_regs[c].reg; + int ir_reg = IREG_GET_REG(host_regs[c].reg); switch (ireg_data[ir_reg].native_size) { @@ -141,28 +142,28 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ if (!ir_reg_is_invalid(dest_reg_a)) { - if (!ir_reg_is_invalid(src_reg_a) && src_reg_a.reg == dest_reg_a.reg && src_reg_a.version == dest_reg_a.version-1) + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version-1) dest_reference++; - if (!ir_reg_is_invalid(src_reg_b) && src_reg_b.reg == dest_reg_a.reg && src_reg_b.version == dest_reg_a.version-1) + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1) dest_reference++; } for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(src_reg_a) && host_regs[c].reg == src_reg_a.reg) + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_a.reg)) { if (host_regs[c].version != src_reg_a.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_a.version\n"); host_regs_locked |= (1 << c); } - if (!ir_reg_is_invalid(src_reg_b) && host_regs[c].reg == src_reg_b.reg) + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_b.reg)) { if (host_regs[c].version != src_reg_b.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n"); host_regs_locked |= (1 << c); } - if (!ir_reg_is_invalid(dest_reg_a) && host_regs[c].reg == dest_reg_a.reg) + if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(dest_reg_a.reg)) { - if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[host_regs[c].reg][host_regs[c].version] == dest_reference)) + if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] == dest_reference)) host_regs_locked |= (1 << c); else fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", host_regs[c].version, dest_reg_a.version, dest_reference); @@ -170,17 +171,17 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ } } -ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg) +ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) { int c; /*Search for required register*/ for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg && host_regs[c].version == ir_reg.version) + if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && host_regs[c].version == ir_reg.version) break; - if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg && reg_version_refcount[host_regs[c].reg][host_regs[c].version]) + if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]) fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); } @@ -196,33 +197,60 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg) fatal("codegen_reg_alloc_read_reg - out of registers\n"); if (host_reg_dirty[c]) codegen_reg_writeback(block, c); +// pclog(" load %i\n", c); codegen_reg_load(block, c, ir_reg); host_regs_locked |= (1 << c); // fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c); // codegen_reg_writeback(block, c); host_reg_dirty[c] = 0; } +// else +// pclog(" already loaded %i\n", c); - reg_version_refcount[host_regs[c].reg][host_regs[c].version]--; - if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] < 0) + reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]--; + if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] < 0) fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); -// pclog(" codegen_reg_alloc_read_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); - return codegen_host_reg_list[c]; + if (host_reg_idx) + *host_reg_idx = c; +// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], host_regs[c].reg,host_regs[c].version, c); + return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { int c; + if (IREG_GET_SIZE(ir_reg.reg) != IREG_SIZE_L) + { + /*Read in parent register so we can do partial accesses to it*/ + ir_reg_t parent_reg; + + parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; + parent_reg.version = ir_reg.version - 1; + + codegen_reg_alloc_read_reg(block, parent_reg, &c); + + if (IREG_GET_REG(host_regs[c].reg) != IREG_GET_REG(ir_reg.reg) || host_regs[c].version != ir_reg.version-1) + fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, + host_regs[c].reg,host_regs[c].version, + ir_reg.reg,ir_reg.version); + + host_regs[c].reg = ir_reg.reg; + host_regs[c].version = ir_reg.version; + host_reg_dirty[c] = 1; +// pclog(" codegen_reg_alloc_write_reg: partial %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); + return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); + } + /*Search for previous version in host register*/ for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && host_regs[c].reg == ir_reg.reg) + if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { if (host_regs[c].version == ir_reg.version-1) { - if (reg_version_refcount[host_regs[c].reg][host_regs[c].version] != 0) + if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] != 0) fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); break; } @@ -257,7 +285,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) host_regs[c].version = ir_reg.version; host_reg_dirty[c] = 1; // pclog(" codegen_reg_alloc_write_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); - return codegen_host_reg_list[c]; + return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index e1b4965..b8f4de5 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -1,10 +1,17 @@ #ifndef _CODEGEN_REG_H_ #define _CODEGEN_REG_H_ -#define IREG_SIZE_L (0 << 6) -#define IREG_SIZE_W (1 << 6) -#define IREG_SIZE_B (2 << 6) -#define IREG_SIZE_BH (3 << 6) +#define IREG_REG_MASK 0x3f +#define IREG_SIZE_SHIFT 6 +#define IREG_SIZE_MASK (3 << IREG_SIZE_SHIFT) + +#define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK) +#define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK) + +#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT) +#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) +#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) +#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) enum { @@ -45,9 +52,34 @@ enum IREG_COUNT, - IREG_INVALID = 255 + IREG_INVALID = 63, + + IREG_AX = IREG_EAX + IREG_SIZE_W, + IREG_CX = IREG_ECX + IREG_SIZE_W, + IREG_DX = IREG_EDX + IREG_SIZE_W, + IREG_BX = IREG_EBX + IREG_SIZE_W, + IREG_SP = IREG_ESP + IREG_SIZE_W, + IREG_BP = IREG_EBP + IREG_SIZE_W, + IREG_SI = IREG_ESI + IREG_SIZE_W, + IREG_DI = IREG_EDI + IREG_SIZE_W, + + IREG_AL = IREG_EAX + IREG_SIZE_B, + IREG_CL = IREG_ECX + IREG_SIZE_B, + IREG_DL = IREG_EDX + IREG_SIZE_B, + IREG_BL = IREG_EBX + IREG_SIZE_B, + + IREG_AH = IREG_EAX + IREG_SIZE_BH, + IREG_CH = IREG_ECX + IREG_SIZE_BH, + IREG_DH = IREG_EDX + IREG_SIZE_BH, + IREG_BH = IREG_EBX + IREG_SIZE_BH, + + IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, + + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B }; +#define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) +#define IREG_16(reg) ((reg) + IREG_AX) #define IREG_32(reg) ((reg) + IREG_EAX) extern uint8_t reg_last_version[IREG_COUNT]; @@ -67,13 +99,13 @@ static inline ir_reg_t codegen_reg_read(int reg) { ir_reg_t ireg; - if (reg == IREG_INVALID) + if (IREG_GET_REG(reg) == IREG_INVALID) fatal("codegen_reg_read - IREG_INVALID\n"); ireg.reg = reg; - ireg.version = reg_last_version[reg]; - reg_version_refcount[ireg.reg][ireg.version]++; - if (!reg_version_refcount[ireg.reg][ireg.version]) + ireg.version = reg_last_version[IREG_GET_REG(reg)]; + reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]++; + if (!reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]) fatal("codegen_reg_read - refcount overflow\n"); return ireg; @@ -83,15 +115,15 @@ static inline ir_reg_t codegen_reg_write(int reg) { ir_reg_t ireg; - if (reg == IREG_INVALID) + if (IREG_GET_REG(reg) == IREG_INVALID) fatal("codegen_reg_write - IREG_INVALID\n"); ireg.reg = reg; - ireg.version = reg_last_version[reg] + 1; - reg_last_version[reg]++; - if (!reg_last_version[reg]) + ireg.version = reg_last_version[IREG_GET_REG(reg)] + 1; + reg_last_version[IREG_GET_REG(reg)]++; + if (!reg_last_version[IREG_GET_REG(reg)]) fatal("codegen_reg_write - version overflow\n"); - reg_version_refcount[reg][ireg.version] = 0; + reg_version_refcount[IREG_GET_REG(reg)][ireg.version] = 0; return ireg; } @@ -104,7 +136,7 @@ void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block); /*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b); -ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg); +ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx); ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); #endif From 0f0a1c3223ff35393fbe0b18252e40a47ecdadde Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 18 Jul 2018 22:10:18 +0100 Subject: [PATCH 013/181] Perform NULL segment checks upfront in opcode handlers, rather than on every memory access. This removes the need to pass the segment to readmem*l()/writemem*l(). --- src/386_common.h | 54 +++++-- src/386_dynarec.c | 2 +- src/808x.c | 20 +-- src/ibm.h | 20 +-- src/mem.c | 340 +++++++++++++++++----------------------- src/x86_ops_arith.h | 106 +++++++++++-- src/x86_ops_atomic.h | 14 ++ src/x86_ops_bit.h | 28 +++- src/x86_ops_bitscan.h | 16 ++ src/x86_ops_call.h | 56 +++++++ src/x86_ops_inc_dec.h | 4 + src/x86_ops_misc.h | 39 +++++ src/x86_ops_mmx.h | 1 + src/x86_ops_mmx_arith.h | 6 +- src/x86_ops_mmx_mov.h | 12 +- src/x86_ops_mmx_pack.h | 4 +- src/x86_ops_mmx_shift.h | 1 + src/x86_ops_mov.h | 44 +++++- src/x86_ops_mov_seg.h | 34 +++- src/x86_ops_movx.h | 28 ++++ src/x86_ops_mul.h | 42 ++++- src/x86_ops_pmode.h | 35 ++++- src/x86_ops_rep.h | 71 +++++++-- src/x86_ops_set.h | 4 + src/x86_ops_shift.h | 44 ++++++ src/x86_ops_stack.h | 8 + src/x86_ops_string.h | 192 ++++++++++++++++++----- src/x86_ops_xchg.h | 18 +++ src/x87_ops_arith.h | 8 + src/x87_ops_loadstore.h | 34 ++++ src/x87_ops_misc.h | 14 ++ 31 files changed, 975 insertions(+), 324 deletions(-) diff --git a/src/386_common.h b/src/386_common.h index 3401257..906c09a 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -4,14 +4,14 @@ extern uint16_t ea_rseg; #undef writememb -#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) -#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) +#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmemb386l((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) +#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writememb386l((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v -#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v -#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v -#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v int checkio(int port); @@ -37,6 +37,26 @@ int checkio(int port); } \ } +#define SEG_CHECK_READ(seg) \ + do \ + { \ + if ((seg)->base == 0xffffffff) \ + { \ + x86gpf("Segment can't read", 0);\ + return 1; \ + } \ + } while (0) + +#define SEG_CHECK_WRITE(seg) \ + do \ + { \ + if ((seg)->base == 0xffffffff) \ + { \ + x86gpf("Segment can't write", 0);\ + return 1; \ + } \ + } while (0) + #define CHECK_READ(seg, low, high) \ if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \ { \ @@ -156,7 +176,7 @@ static inline uint8_t geteab() return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l; if (eal_r) return *(uint8_t *)eal_r; - return readmemb(easeg, cpu_state.eaaddr); + return readmemb(easeg,cpu_state.eaaddr); } static inline uint16_t geteaw() @@ -166,7 +186,7 @@ static inline uint16_t geteaw() // cycles-=3; if (eal_r) return *(uint16_t *)eal_r; - return readmemw(easeg, cpu_state.eaaddr); + return readmemw(easeg,cpu_state.eaaddr); } static inline uint32_t geteal() @@ -176,12 +196,12 @@ static inline uint32_t geteal() // cycles-=3; if (eal_r) return *eal_r; - return readmeml(easeg, cpu_state.eaaddr); + return readmeml(easeg,cpu_state.eaaddr); } static inline uint64_t geteaq() { - return readmemq(easeg, cpu_state.eaaddr); + return readmemq(easeg,cpu_state.eaaddr); } static inline uint8_t geteab_mem() @@ -202,16 +222,16 @@ static inline uint32_t geteal_mem() static inline void seteaq(uint64_t v) { - writememql(easeg, cpu_state.eaaddr, v); + writememql(easeg+cpu_state.eaaddr, v); } -#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v -#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v -#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v +#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v +#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v +#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v -#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v); -#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v); -#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v); +#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg+cpu_state.eaaddr,v); +#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); +#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); #define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++ #define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 4dff9e7..7224d09 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -429,7 +429,7 @@ int checkio(int port) // pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3)); if ((t+(port>>3))>tr.limit) return 1; cpl_override = 1; - d = readmemb386l(0, tr.base + t + (port >> 3)); + d = readmemb386l(tr.base + t + (port >> 3)); // d=readmemb(tr.base,t+(port>>3)); cpl_override = 0; // pclog("%02X %02X\n",d,d&(1<<(port&7))); diff --git a/src/808x.c b/src/808x.c index e50a13c..082e0b0 100644 --- a/src/808x.c +++ b/src/808x.c @@ -38,13 +38,6 @@ int nopageerrors=0; void FETCHCOMPLETE(); -uint8_t readmembl(uint32_t addr); -void writemembl(uint32_t addr, uint8_t val); -uint16_t readmemwl(uint32_t seg, uint32_t addr); -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); -uint32_t readmemll(uint32_t seg, uint32_t addr); -void writememll(uint32_t seg, uint32_t addr, uint32_t val); - #undef readmemb #undef readmemw uint8_t readmemb(uint32_t a) @@ -63,7 +56,7 @@ uint8_t readmembf(uint32_t a) uint16_t readmemw(uint32_t s, uint16_t a) { if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086); - if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s,a); + if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s+a); else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); } @@ -76,24 +69,21 @@ void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE(); memcycs+=4; } cpu_rm=rmdat&7; \ if (cpu_mod!=3) fetcheal(); } -void writemembl(uint32_t addr, uint8_t val); void writememb(uint32_t a, uint8_t v) { memcycs+=4; if (writelookup2[(a)>>12]==-1) writemembl(a,v); else *(uint8_t *)(writelookup2[a >> 12] + a) = v; } -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); void writememw(uint32_t s, uint32_t a, uint16_t v) { memcycs+=(8>>is8086); - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s,a,v); + if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s+a,v); else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v; } -void writememll(uint32_t seg, uint32_t addr, uint32_t val); void writememl(uint32_t s, uint32_t a, uint32_t v) { - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s,a,v); + if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s+a,v); else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v; } @@ -538,10 +528,10 @@ void dumpregs() fclose(f);*/ pclog("Dumping rram4.dmp\n"); f=fopen("rram4.dmp","wb"); - for (c=0;c<0x0050000;c++) + for (c=0;c<0x0050000;c++) { cpu_state.abrt = 0; - putc(readmemb386l(0,c+0x80000000),f); + putc(readmemb386l(c+0x80000000),f); } fclose(f); pclog("Dumping done\n"); diff --git a/src/ibm.h b/src/ibm.h index 549acc2..6177fef 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -31,8 +31,8 @@ int writelnext; extern int mmu_perm; #define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a))) -#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl(s,a):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll(s,a):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) +#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) +#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) //#define writememb(a,v) if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v); else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v //#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v @@ -43,14 +43,14 @@ extern int mmu_perm; //void writememb(uint32_t addr, uint8_t val); uint8_t readmembl(uint32_t addr); void writemembl(uint32_t addr, uint8_t val); -uint8_t readmemb386l(uint32_t seg, uint32_t addr); -void writememb386l(uint32_t seg, uint32_t addr, uint8_t val); -uint16_t readmemwl(uint32_t seg, uint32_t addr); -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); -uint32_t readmemll(uint32_t seg, uint32_t addr); -void writememll(uint32_t seg, uint32_t addr, uint32_t val); -uint64_t readmemql(uint32_t seg, uint32_t addr); -void writememql(uint32_t seg, uint32_t addr, uint64_t val); +uint8_t readmemb386l(uint32_t addr); +void writememb386l(uint32_t addr, uint8_t val); +uint16_t readmemwl(uint32_t addr); +void writememwl(uint32_t addr, uint16_t val); +uint32_t readmemll(uint32_t addr); +void writememll(uint32_t addr, uint32_t val); +uint64_t readmemql(uint32_t addr); +void writememql(uint32_t addr, uint64_t val); uint8_t *getpccache(uint32_t a); diff --git a/src/mem.c b/src/mem.c index eabbcaa..6fa3a69 100644 --- a/src/mem.c +++ b/src/mem.c @@ -295,7 +295,6 @@ uint32_t mmutranslatereal(uint32_t addr, int rw) if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && ((CPL == 3 && !cpl_override) || cr0&WP_FLAG))) { // if (!nopageerrors) pclog("Page not present! %08X %08X %02X %02X %i %08X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,frame,rmdat32, CS,pc,SS,ESP,ins,CPL,rw); - // dumpregs(); // exit(-1); // if (addr == 0x815F6E90) output = 3; @@ -498,15 +497,9 @@ void writemembl(uint32_t addr, uint8_t val) // else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc); } -uint8_t readmemb386l(uint32_t seg, uint32_t addr) +uint8_t readmemb386l(uint32_t addr) { - if (seg==-1) - { - x86gpf("NULL segment", 0); - printf("NULL segment! rb %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return -1; - } - mem_logical_addr = addr = addr + seg; + mem_logical_addr = addr; /* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF) { return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)]; @@ -525,16 +518,9 @@ uint8_t readmemb386l(uint32_t seg, uint32_t addr) return 0xFF; } -void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) +void writememb386l(uint32_t addr, uint8_t val) { - if (seg==-1) - { - x86gpf("NULL segment", 0); - printf("NULL segment! wb %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return; - } - - mem_logical_addr = addr = addr + seg; + mem_logical_addr = addr; if (page_lookup[addr>>12]) { page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); @@ -555,352 +541,308 @@ void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) // else pclog("Bad writememb386l %08X %02X %04X:%08X\n", addr, val, CS, pc); } -uint16_t readmemwl(uint32_t seg, uint32_t addr) +uint16_t readmemwl(uint32_t addr) { - uint32_t addr2 = mem_logical_addr = seg + addr; + mem_logical_addr = addr; - if (seg==-1) + if (addr & 1) { - x86gpf("NULL segment", 0); - printf("NULL segment! rw %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return -1; - } - if (addr2 & 1) - { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) + if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFFE) + if ((addr & 0xFFF) > 0xFFE) { if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff; - if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff; + if (mmutranslate_read(addr) == 0xffffffff) return 0xffff; + if (mmutranslate_read(addr+1) == 0xffffffff) return 0xffff; } - if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); - else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); + if (is386) return readmemb386l(addr)|(readmemb386l(addr+1)<<8); + else return readmembl(addr)|(readmembl(addr+1)<<8); } - else if (readlookup2[addr2 >> 12] != -1) - return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); + else if (readlookup2[addr >> 12] != -1) + return *(uint16_t *)(readlookup2[addr >> 12] + addr); } if (cr0>>31) { - addr2 = mmutranslate_read(addr2); - if (addr2==0xFFFFFFFF) return 0xFFFF; + addr = mmutranslate_read(addr); + if (addr==0xFFFFFFFF) return 0xFFFF; } - addr2 &= rammask; + addr &= rammask; - if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); + if (_mem_read_w[addr >> 14]) return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]); - if (_mem_read_b[addr2 >> 14]) - { - if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8); - else return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8); - } -// pclog("Bad readmemwl %08X\n", addr2); + if (_mem_read_b[addr >> 14]) + return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]) | (_mem_read_b[(addr + 1) >> 14](addr + 1, _mem_priv_r[addr >> 14]) << 8); + +// pclog("Bad readmemwl %08X\n", addr); return 0xffff; } -void writememwl(uint32_t seg, uint32_t addr, uint16_t val) +void writememwl(uint32_t addr, uint16_t val) { - uint32_t addr2 = mem_logical_addr = seg + addr; + mem_logical_addr = addr; - if (seg==-1) + if (addr & 1) { - x86gpf("NULL segment", 0); - printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return; - } - - if (addr2 & 1) - { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) + if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFFE) + if ((addr & 0xFFF) > 0xFFE) { if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffff) return; - if (mmutranslate_write(addr2+1) == 0xffffffff) return; + if (mmutranslate_write(addr) == 0xffffffff) return; + if (mmutranslate_write(addr+1) == 0xffffffff) return; } if (is386) { - writememb386l(seg,addr,val); - writememb386l(seg,addr+1,val>>8); + writememb386l(addr,val); + writememb386l(addr+1,val>>8); } else { - writemembl(seg+addr,val); - writemembl(seg+addr+1,val>>8); + writemembl(addr,val); + writemembl(addr+1,val>>8); } return; } - else if (writelookup2[addr2 >> 12] != -1) + else if (writelookup2[addr >> 12] != -1) { - *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; + *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr2>>12]) + if (page_lookup[addr>>12]) { - page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]); + page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]); return; } if (cr0>>31) { - addr2 = mmutranslate_write(addr2); - if (addr2==0xFFFFFFFF) return; + addr = mmutranslate_write(addr); + if (addr==0xFFFFFFFF) return; } - addr2 &= rammask; + addr &= rammask; -/* if (addr2 >= 0xa0000 && addr2 < 0xc0000) - pclog("writememwl %08X %02X\n", addr2, val);*/ - - if (_mem_write_w[addr2 >> 14]) + if (_mem_write_w[addr >> 14]) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); return; } - if (_mem_write_b[addr2 >> 14]) + if (_mem_write_b[addr >> 14]) { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + _mem_write_b[(addr + 1) >> 14](addr + 1, val >> 8, _mem_priv_w[addr >> 14]); return; } -// pclog("Bad writememwl %08X %04X\n", addr2, val); +// pclog("Bad writememwl %08X %04X\n", addr, val); } -uint32_t readmemll(uint32_t seg, uint32_t addr) +uint32_t readmemll(uint32_t addr) { - uint32_t addr2 = mem_logical_addr = seg + addr; + mem_logical_addr = addr; - if (seg==-1) + if (addr & 3) { - x86gpf("NULL segment", 0); - printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return -1; - } - - if (addr2 & 3) - { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + if (!cpu_cyrix_alignment || (addr & 7) > 4) cycles -= timing_misaligned; - if ((addr2&0xFFF)>0xFFC) + if ((addr&0xFFF)>0xFFC) { if (cr0>>31) { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff; - if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff; + if (mmutranslate_read(addr) == 0xffffffff) return 0xffffffff; + if (mmutranslate_read(addr+3) == 0xffffffff) return 0xffffffff; } - return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); + return readmemwl(addr)|(readmemwl(addr+2)<<16); } - else if (readlookup2[addr2 >> 12] != -1) - return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); + else if (readlookup2[addr >> 12] != -1) + return *(uint32_t *)(readlookup2[addr >> 12] + addr); } if (cr0>>31) { - addr2 = mmutranslate_read(addr2); - if (addr2==0xFFFFFFFF) return 0xFFFFFFFF; + addr = mmutranslate_read(addr); + if (addr==0xFFFFFFFF) return 0xFFFFFFFF; } - addr2&=rammask; + addr&=rammask; - if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); + if (_mem_read_l[addr >> 14]) return _mem_read_l[addr >> 14](addr, _mem_priv_r[addr >> 14]); - if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16); + if (_mem_read_w[addr >> 14]) return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]) | (_mem_read_w[addr >> 14](addr + 2, _mem_priv_r[addr >> 14]) << 16); - if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24); + if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]) | (_mem_read_b[addr >> 14](addr + 1, _mem_priv_r[addr >> 14]) << 8) | (_mem_read_b[addr >> 14](addr + 2, _mem_priv_r[addr >> 14]) << 16) | (_mem_read_b[addr >> 14](addr + 3, _mem_priv_r[addr >> 14]) << 24); -// pclog("Bad readmemll %08X\n", addr2); +// pclog("Bad readmemll %08X\n", addr); return 0xffffffff; } -void writememll(uint32_t seg, uint32_t addr, uint32_t val) +void writememll(uint32_t addr, uint32_t val) { - uint32_t addr2 = mem_logical_addr = seg + addr; + mem_logical_addr = addr; - if (seg==-1) + if (addr & 3) { - x86gpf("NULL segment", 0); - printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return; - } - if (addr2 & 3) - { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + if (!cpu_cyrix_alignment || (addr & 7) > 4) cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFFC) + if ((addr & 0xFFF) > 0xFFC) { if (cr0>>31) { - if (mmutranslate_write(addr2) == 0xffffffff) return; - if (mmutranslate_write(addr2+3) == 0xffffffff) return; + if (mmutranslate_write(addr) == 0xffffffff) return; + if (mmutranslate_write(addr+3) == 0xffffffff) return; } - writememwl(seg,addr,val); - writememwl(seg,addr+2,val>>16); + writememwl(addr,val); + writememwl(addr+2,val>>16); return; } - else if (writelookup2[addr2 >> 12] != -1) + else if (writelookup2[addr >> 12] != -1) { - *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; + *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr2>>12]) + if (page_lookup[addr>>12]) { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); + page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); return; } if (cr0>>31) { - addr2 = mmutranslate_write(addr2); - if (addr2==0xFFFFFFFF) return; + addr = mmutranslate_write(addr); + if (addr==0xFFFFFFFF) return; } - addr2&=rammask; + addr&=rammask; /* if (addr >= 0xa0000 && addr < 0xc0000) pclog("writememll %08X %08X\n", addr, val);*/ - if (_mem_write_l[addr2 >> 14]) + if (_mem_write_l[addr >> 14]) { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_l[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); return; } - if (_mem_write_w[addr2 >> 14]) + if (_mem_write_w[addr >> 14]) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + _mem_write_w[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); return; } - if (_mem_write_b[addr2 >> 14]) + if (_mem_write_b[addr >> 14]) { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 1, val >> 8, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 3, val >> 24, _mem_priv_w[addr >> 14]); return; } -// pclog("Bad writememll %08X %08X\n", addr2, val); +// pclog("Bad writememll %08X %08X\n", addr, val); } -uint64_t readmemql(uint32_t seg, uint32_t addr) +uint64_t readmemql(uint32_t addr) { - uint32_t addr2 = mem_logical_addr = seg + addr; + mem_logical_addr = addr; - if (seg==-1) - { - x86gpf("NULL segment", 0); - printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return -1; - } - - if (addr2 & 7) + if (addr & 7) { cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFF8) + if ((addr & 0xFFF) > 0xFF8) { if (cr0>>31) { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff; - if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff; + if (mmutranslate_read(addr) == 0xffffffff) return 0xffffffff; + if (mmutranslate_read(addr+7) == 0xffffffff) return 0xffffffff; } - return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); + return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); } - else if (readlookup2[addr2 >> 12] != -1) - return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); + else if (readlookup2[addr >> 12] != -1) + return *(uint64_t *)(readlookup2[addr >> 12] + addr); } if (cr0>>31) { - addr2 = mmutranslate_read(addr2); - if (addr2==0xFFFFFFFF) return 0xFFFFFFFF; + addr = mmutranslate_read(addr); + if (addr==0xFFFFFFFF) return 0xFFFFFFFF; } - addr2&=rammask; + addr&=rammask; - if (_mem_read_l[addr2 >> 14]) - return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | - ((uint64_t)_mem_read_l[addr2 >> 14](addr2 + 4, _mem_priv_r[addr2 >> 14]) << 32); + if (_mem_read_l[addr >> 14]) + return _mem_read_l[addr >> 14](addr, _mem_priv_r[addr >> 14]) | + ((uint64_t)_mem_read_l[addr >> 14](addr + 4, _mem_priv_r[addr >> 14]) << 32); - return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32); + return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); } -void writememql(uint32_t seg, uint32_t addr, uint64_t val) +void writememql(uint32_t addr, uint64_t val) { - uint32_t addr2 = mem_logical_addr = seg + addr; + mem_logical_addr = addr; - if (seg==-1) - { - x86gpf("NULL segment", 0); - printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return; - } - if (addr2 & 7) + if (addr & 7) { cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFF8) + if ((addr & 0xFFF) > 0xFF8) { if (cr0>>31) { - if (mmutranslate_write(addr2) == 0xffffffff) return; - if (mmutranslate_write(addr2+7) == 0xffffffff) return; + if (mmutranslate_write(addr) == 0xffffffff) return; + if (mmutranslate_write(addr+7) == 0xffffffff) return; } - writememll(seg, addr, val); - writememll(seg, addr+4, val >> 32); + writememll(addr, val); + writememll(addr+4, val >> 32); return; } - else if (writelookup2[addr2 >> 12] != -1) + else if (writelookup2[addr >> 12] != -1) { - *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; + *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr2>>12]) + if (page_lookup[addr>>12]) { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); - page_lookup[addr2>>12]->write_l(addr2 + 4, val >> 32, page_lookup[addr2>>12]); + page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); + page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]); return; } if (cr0>>31) { - addr2 = mmutranslate_write(addr2); - if (addr2==0xFFFFFFFF) return; + addr = mmutranslate_write(addr); + if (addr==0xFFFFFFFF) return; } - addr2&=rammask; + addr&=rammask; - if (_mem_write_l[addr2 >> 14]) + if (_mem_write_l[addr >> 14]) { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_l[addr2 >> 14](addr2+4, val >> 32, _mem_priv_w[addr2 >> 14]); + _mem_write_l[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + _mem_write_l[addr >> 14](addr+4, val >> 32, _mem_priv_w[addr >> 14]); return; } - if (_mem_write_w[addr2 >> 14]) + if (_mem_write_w[addr >> 14]) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + _mem_write_w[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); + _mem_write_w[addr >> 14](addr + 4, val >> 32, _mem_priv_w[addr >> 14]); + _mem_write_w[addr >> 14](addr + 6, val >> 48, _mem_priv_w[addr >> 14]); return; } - if (_mem_write_b[addr2 >> 14]) + if (_mem_write_b[addr >> 14]) { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 5, val >> 40, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 7, val >> 56, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 1, val >> 8, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 3, val >> 24, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 4, val >> 32, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 5, val >> 40, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 6, val >> 48, _mem_priv_w[addr >> 14]); + _mem_write_b[addr >> 14](addr + 7, val >> 56, _mem_priv_w[addr >> 14]); return; } -// pclog("Bad writememql %08X %08X\n", addr2, val); +// pclog("Bad writememql %08X %08X\n", addr, val); } uint8_t mem_readb_phys(uint32_t addr) diff --git a/src/x86_ops_arith.h b/src/x86_ops_arith.h index 2417555..b9787e9 100644 --- a/src/x86_ops_arith.h +++ b/src/x86_ops_arith.h @@ -14,9 +14,11 @@ } \ else \ { \ - uint8_t dst = geteab(); if (cpu_state.abrt) return 1; \ + uint8_t dst; \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteab(); if (cpu_state.abrt) return 1; \ uint8_t src = getr8(cpu_reg); \ - seteab(operation); if (cpu_state.abrt) return 1; \ + seteab(operation); if (cpu_state.abrt) return 1; \ setflags ## 8 flagops; \ CLOCK_CYCLES(timing_mr); \ PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 0); \ @@ -38,7 +40,9 @@ } \ else \ { \ - uint8_t dst = geteab(); if (cpu_state.abrt) return 1; \ + uint8_t dst; \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteab(); if (cpu_state.abrt) return 1; \ uint8_t src = getr8(cpu_reg); \ seteab(operation); if (cpu_state.abrt) return 1; \ setflags ## 8 flagops; \ @@ -63,7 +67,9 @@ } \ else \ { \ - uint16_t dst = geteaw(); if (cpu_state.abrt) return 1; \ + uint16_t dst; \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteaw(); if (cpu_state.abrt) return 1; \ uint16_t src = cpu_state.regs[cpu_reg].w; \ seteaw(operation); if (cpu_state.abrt) return 1; \ setflags ## 16 flagops; \ @@ -87,7 +93,9 @@ } \ else \ { \ - uint16_t dst = geteaw(); if (cpu_state.abrt) return 1; \ + uint16_t dst; \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteaw(); if (cpu_state.abrt) return 1; \ uint16_t src = cpu_state.regs[cpu_reg].w; \ seteaw(operation); if (cpu_state.abrt) return 1; \ setflags ## 16 flagops; \ @@ -112,7 +120,9 @@ } \ else \ { \ - uint32_t dst = geteal(); if (cpu_state.abrt) return 1; \ + uint32_t dst; \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteal(); if (cpu_state.abrt) return 1; \ uint32_t src = cpu_state.regs[cpu_reg].l; \ seteal(operation); if (cpu_state.abrt) return 1; \ setflags ## 32 flagops; \ @@ -136,7 +146,9 @@ } \ else \ { \ - uint32_t dst = geteal(); if (cpu_state.abrt) return 1; \ + uint32_t dst; \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteal(); if (cpu_state.abrt) return 1; \ uint32_t src = cpu_state.regs[cpu_reg].l; \ seteal(operation); if (cpu_state.abrt) return 1; \ setflags ## 32 flagops; \ @@ -151,6 +163,8 @@ uint8_t dst, src; \ if (gettempc) tempc = CF_SET() ? 1 : 0; \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ dst = getr8(cpu_reg); \ src = geteab(); if (cpu_state.abrt) return 1; \ setflags ## 8 flagops; \ @@ -164,6 +178,8 @@ uint8_t dst, src; \ if (gettempc) tempc = CF_SET() ? 1 : 0; \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ dst = getr8(cpu_reg); \ src = geteab(); if (cpu_state.abrt) return 1; \ setflags ## 8 flagops; \ @@ -178,6 +194,8 @@ uint16_t dst, src; \ if (gettempc) tempc = CF_SET() ? 1 : 0; \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ dst = cpu_state.regs[cpu_reg].w; \ src = geteaw(); if (cpu_state.abrt) return 1; \ setflags ## 16 flagops; \ @@ -191,6 +209,8 @@ uint16_t dst, src; \ if (gettempc) tempc = CF_SET() ? 1 : 0; \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ dst = cpu_state.regs[cpu_reg].w; \ src = geteaw(); if (cpu_state.abrt) return 1; \ setflags ## 16 flagops; \ @@ -205,6 +225,8 @@ uint32_t dst, src; \ if (gettempc) tempc = CF_SET() ? 1 : 0; \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ dst = cpu_state.regs[cpu_reg].l; \ src = geteal(); if (cpu_state.abrt) return 1; \ setflags ## 32 flagops; \ @@ -218,6 +240,8 @@ uint32_t dst, src; \ if (gettempc) tempc = CF_SET() ? 1 : 0; \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ dst = cpu_state.regs[cpu_reg].l; \ src = geteal(); if (cpu_state.abrt) return 1; \ setflags ## 32 flagops; \ @@ -275,6 +299,8 @@ static int opCMP_b_rmw_a16(uint32_t fetchdat) { uint8_t dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteab(); if (cpu_state.abrt) return 1; setsub8(dst, getr8(cpu_reg)); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -286,6 +312,8 @@ static int opCMP_b_rmw_a32(uint32_t fetchdat) { uint8_t dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteab(); if (cpu_state.abrt) return 1; setsub8(dst, getr8(cpu_reg)); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -298,6 +326,8 @@ static int opCMP_w_rmw_a16(uint32_t fetchdat) { uint16_t dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteaw(); if (cpu_state.abrt) return 1; setsub16(dst, cpu_state.regs[cpu_reg].w); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -309,6 +339,8 @@ static int opCMP_w_rmw_a32(uint32_t fetchdat) { uint16_t dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteaw(); if (cpu_state.abrt) return 1; setsub16(dst, cpu_state.regs[cpu_reg].w); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -321,6 +353,8 @@ static int opCMP_l_rmw_a16(uint32_t fetchdat) { uint32_t dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteal(); if (cpu_state.abrt) return 1; setsub32(dst, cpu_state.regs[cpu_reg].l); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -332,6 +366,8 @@ static int opCMP_l_rmw_a32(uint32_t fetchdat) { uint32_t dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteal(); if (cpu_state.abrt) return 1; setsub32(dst, cpu_state.regs[cpu_reg].l); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -344,7 +380,9 @@ static int opCMP_b_rm_a16(uint32_t fetchdat) { uint8_t src; fetch_ea_16(fetchdat); - src = geteab(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteab(); if (cpu_state.abrt) return 1; setsub8(getr8(cpu_reg), src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); @@ -354,7 +392,9 @@ static int opCMP_b_rm_a32(uint32_t fetchdat) { uint8_t src; fetch_ea_32(fetchdat); - src = geteab(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteab(); if (cpu_state.abrt) return 1; setsub8(getr8(cpu_reg), src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); @@ -365,7 +405,9 @@ static int opCMP_w_rm_a16(uint32_t fetchdat) { uint16_t src; fetch_ea_16(fetchdat); - src = geteaw(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteaw(); if (cpu_state.abrt) return 1; setsub16(cpu_state.regs[cpu_reg].w, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); @@ -375,7 +417,9 @@ static int opCMP_w_rm_a32(uint32_t fetchdat) { uint16_t src; fetch_ea_32(fetchdat); - src = geteaw(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteaw(); if (cpu_state.abrt) return 1; setsub16(cpu_state.regs[cpu_reg].w, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); @@ -386,7 +430,9 @@ static int opCMP_l_rm_a16(uint32_t fetchdat) { uint32_t src; fetch_ea_16(fetchdat); - src = geteal(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteal(); if (cpu_state.abrt) return 1; setsub32(cpu_state.regs[cpu_reg].l, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); @@ -396,7 +442,9 @@ static int opCMP_l_rm_a32(uint32_t fetchdat) { uint32_t src; fetch_ea_32(fetchdat); - src = geteal(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteal(); if (cpu_state.abrt) return 1; setsub32(cpu_state.regs[cpu_reg].l, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); @@ -434,6 +482,8 @@ static int opTEST_b_a16(uint32_t fetchdat) { uint8_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; temp2 = getr8(cpu_reg); setznp8(temp & temp2); @@ -446,6 +496,8 @@ static int opTEST_b_a32(uint32_t fetchdat) { uint8_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; temp2 = getr8(cpu_reg); setznp8(temp & temp2); @@ -459,6 +511,8 @@ static int opTEST_w_a16(uint32_t fetchdat) { uint16_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; temp2 = cpu_state.regs[cpu_reg].w; setznp16(temp & temp2); @@ -471,6 +525,8 @@ static int opTEST_w_a32(uint32_t fetchdat) { uint16_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; temp2 = cpu_state.regs[cpu_reg].w; setznp16(temp & temp2); @@ -484,6 +540,8 @@ static int opTEST_l_a16(uint32_t fetchdat) { uint32_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; temp2 = cpu_state.regs[cpu_reg].l; setznp32(temp & temp2); @@ -496,6 +554,8 @@ static int opTEST_l_a32(uint32_t fetchdat) { uint32_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; temp2 = cpu_state.regs[cpu_reg].l; setznp32(temp & temp2); @@ -588,6 +648,8 @@ static int op80_a16(uint32_t fetchdat) uint8_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getbyte(); if (cpu_state.abrt) return 1; ARITH_MULTI(b, 8); if ((rmdat & 0x38) == 0x38) @@ -602,6 +664,8 @@ static int op80_a32(uint32_t fetchdat) uint8_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getbyte(); if (cpu_state.abrt) return 1; ARITH_MULTI(b, 8); if ((rmdat & 0x38) == 0x38) @@ -616,6 +680,8 @@ static int op81_w_a16(uint32_t fetchdat) uint16_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getword(); if (cpu_state.abrt) return 1; ARITH_MULTI(w, 16); if ((rmdat & 0x38) == 0x38) @@ -630,6 +696,8 @@ static int op81_w_a32(uint32_t fetchdat) uint16_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getword(); if (cpu_state.abrt) return 1; ARITH_MULTI(w, 16); if ((rmdat & 0x38) == 0x38) @@ -644,6 +712,8 @@ static int op81_l_a16(uint32_t fetchdat) uint32_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getlong(); if (cpu_state.abrt) return 1; ARITH_MULTI(l, 32); if ((rmdat & 0x38) == 0x38) @@ -658,6 +728,8 @@ static int op81_l_a32(uint32_t fetchdat) uint32_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getlong(); if (cpu_state.abrt) return 1; ARITH_MULTI(l, 32); if ((rmdat & 0x38) == 0x38) @@ -673,6 +745,8 @@ static int op83_w_a16(uint32_t fetchdat) uint16_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xff00; ARITH_MULTI(w, 16); @@ -688,6 +762,8 @@ static int op83_w_a32(uint32_t fetchdat) uint16_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xff00; ARITH_MULTI(w, 16); @@ -704,6 +780,8 @@ static int op83_l_a16(uint32_t fetchdat) uint32_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xffffff00; ARITH_MULTI(l, 32); @@ -719,6 +797,8 @@ static int op83_l_a32(uint32_t fetchdat) uint32_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xffffff00; ARITH_MULTI(l, 32); diff --git a/src/x86_ops_atomic.h b/src/x86_ops_atomic.h index 0e0069c..d74c30e 100644 --- a/src/x86_ops_atomic.h +++ b/src/x86_ops_atomic.h @@ -8,6 +8,7 @@ static int opCMPXCHG_b_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; if (AL == temp) seteab(getr8(cpu_reg)); else AL = temp; @@ -26,6 +27,7 @@ static int opCMPXCHG_b_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; if (AL == temp) seteab(getr8(cpu_reg)); else AL = temp; @@ -45,6 +47,7 @@ static int opCMPXCHG_w_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w); else AX = temp; @@ -63,6 +66,7 @@ static int opCMPXCHG_w_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w); else AX = temp; @@ -82,6 +86,7 @@ static int opCMPXCHG_l_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l); else EAX = temp; @@ -100,6 +105,7 @@ static int opCMPXCHG_l_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l); else EAX = temp; @@ -119,6 +125,7 @@ static int opCMPXCHG8B_a16(uint32_t fetchdat) return 0; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; if (EAX == temp && EDX == temp_hi) @@ -150,6 +157,7 @@ static int opCMPXCHG8B_a32(uint32_t fetchdat) return 0; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; if (EAX == temp && EDX == temp_hi) @@ -182,6 +190,7 @@ static int opXADD_b_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; seteab(temp + getr8(cpu_reg)); if (cpu_state.abrt) return 1; setadd8(temp, getr8(cpu_reg)); @@ -199,6 +208,7 @@ static int opXADD_b_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; seteab(temp + getr8(cpu_reg)); if (cpu_state.abrt) return 1; setadd8(temp, getr8(cpu_reg)); @@ -217,6 +227,7 @@ static int opXADD_w_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp + cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; setadd16(temp, cpu_state.regs[cpu_reg].w); @@ -234,6 +245,7 @@ static int opXADD_w_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp + cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; setadd16(temp, cpu_state.regs[cpu_reg].w); @@ -252,6 +264,7 @@ static int opXADD_l_a16(uint32_t fetchdat) return 1; } fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp + cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; setadd32(temp, cpu_state.regs[cpu_reg].l); @@ -269,6 +282,7 @@ static int opXADD_l_a32(uint32_t fetchdat) return 1; } fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp + cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; setadd32(temp, cpu_state.regs[cpu_reg].l); diff --git a/src/x86_ops_bit.h b/src/x86_ops_bit.h index 272d22b..74194f5 100644 --- a/src/x86_ops_bit.h +++ b/src/x86_ops_bit.h @@ -3,6 +3,7 @@ static int opBT_w_r_a16(uint32_t fetchdat) uint16_t temp; fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0; temp = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -18,6 +19,7 @@ static int opBT_w_r_a32(uint32_t fetchdat) uint16_t temp; fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0; temp = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -33,6 +35,7 @@ static int opBT_l_r_a16(uint32_t fetchdat) uint32_t temp; fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0; temp = geteal(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -48,6 +51,7 @@ static int opBT_l_r_a32(uint32_t fetchdat) uint32_t temp; fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0; temp = geteal(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -66,6 +70,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) uint16_t temp; \ \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \ temp = geteaw(); if (cpu_state.abrt) return 1; \ tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \ @@ -85,6 +91,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) uint16_t temp; \ \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \ temp = geteaw(); if (cpu_state.abrt) return 1; \ tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \ @@ -104,6 +112,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) uint32_t temp; \ \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \ temp = geteal(); if (cpu_state.abrt) return 1; \ tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \ @@ -123,6 +133,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) uint32_t temp; \ \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \ temp = geteal(); if (cpu_state.abrt) return 1; \ tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \ @@ -147,7 +159,9 @@ static int opBA_w_a16(uint32_t fetchdat) uint16_t temp; fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); count = getbyte(); if (cpu_state.abrt) return 1; tempc = temp & (1 << count); @@ -189,7 +203,9 @@ static int opBA_w_a32(uint32_t fetchdat) uint16_t temp; fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); count = getbyte(); if (cpu_state.abrt) return 1; tempc = temp & (1 << count); @@ -232,7 +248,9 @@ static int opBA_l_a16(uint32_t fetchdat) uint32_t temp; fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); count = getbyte(); if (cpu_state.abrt) return 1; tempc = temp & (1 << count); @@ -274,7 +292,9 @@ static int opBA_l_a32(uint32_t fetchdat) uint32_t temp; fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); count = getbyte(); if (cpu_state.abrt) return 1; tempc = temp & (1 << count); diff --git a/src/x86_ops_bitscan.h b/src/x86_ops_bitscan.h index 0c1ee04..4fcc79c 100644 --- a/src/x86_ops_bitscan.h +++ b/src/x86_ops_bitscan.h @@ -25,6 +25,8 @@ static int opBSF_w_a16(uint32_t fetchdat) int instr_cycles; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); @@ -40,6 +42,8 @@ static int opBSF_w_a32(uint32_t fetchdat) int instr_cycles; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); @@ -55,6 +59,8 @@ static int opBSF_l_a16(uint32_t fetchdat) int instr_cycles; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); @@ -70,6 +76,8 @@ static int opBSF_l_a32(uint32_t fetchdat) int instr_cycles; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); @@ -86,6 +94,8 @@ static int opBSR_w_a16(uint32_t fetchdat) int instr_cycles; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); @@ -101,6 +111,8 @@ static int opBSR_w_a32(uint32_t fetchdat) int instr_cycles; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); @@ -116,6 +128,8 @@ static int opBSR_l_a16(uint32_t fetchdat) int instr_cycles; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); @@ -131,6 +145,8 @@ static int opBSR_l_a32(uint32_t fetchdat) int instr_cycles; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); diff --git a/src/x86_ops_call.h b/src/x86_ops_call.h index bbb5dca..aa126c6 100644 --- a/src/x86_ops_call.h +++ b/src/x86_ops_call.h @@ -104,6 +104,8 @@ static int opFF_w_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp + 1); if (cpu_state.abrt) return 1; setadd16nc(temp, 1); @@ -111,6 +113,8 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x08: /*DEC w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp - 1); if (cpu_state.abrt) return 1; setsub16nc(temp, 1); @@ -118,6 +122,8 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x10: /*CALL*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(cpu_state.pc); cpu_state.pc = new_pc; @@ -128,6 +134,8 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1; @@ -137,6 +145,8 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteaw(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -146,6 +156,8 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); oxpc = cpu_state.pc; new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -156,6 +168,8 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH w*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); @@ -181,6 +195,8 @@ static int opFF_w_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp + 1); if (cpu_state.abrt) return 1; setadd16nc(temp, 1); @@ -188,6 +204,8 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x08: /*DEC w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp - 1); if (cpu_state.abrt) return 1; setsub16nc(temp, 1); @@ -195,6 +213,8 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x10: /*CALL*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(cpu_state.pc); cpu_state.pc = new_pc; @@ -205,6 +225,8 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1; @@ -214,6 +236,8 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteaw(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -223,6 +247,8 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); oxpc = cpu_state.pc; new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -233,6 +259,8 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH w*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); @@ -259,6 +287,8 @@ static int opFF_l_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp + 1); if (cpu_state.abrt) return 1; setadd32nc(temp, 1); @@ -266,6 +296,8 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x08: /*DEC l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp - 1); if (cpu_state.abrt) return 1; setsub32nc(temp, 1); @@ -273,6 +305,8 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x10: /*CALL*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteal(); if (cpu_state.abrt) return 1; PUSH_L(cpu_state.pc); cpu_state.pc = new_pc; @@ -283,6 +317,8 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1; @@ -292,6 +328,8 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteal(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -301,6 +339,8 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); oxpc = cpu_state.pc; new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; @@ -311,6 +351,8 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH l*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; PUSH_L(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); @@ -336,6 +378,8 @@ static int opFF_l_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp + 1); if (cpu_state.abrt) return 1; setadd32nc(temp, 1); @@ -343,6 +387,8 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x08: /*DEC l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp - 1); if (cpu_state.abrt) return 1; setsub32nc(temp, 1); @@ -350,6 +396,8 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x10: /*CALL*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteal(); if (cpu_state.abrt) return 1; PUSH_L(cpu_state.pc); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; @@ -360,6 +408,8 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1; @@ -369,6 +419,8 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_pc = geteal(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -378,6 +430,8 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); oxpc = cpu_state.pc; new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; @@ -388,6 +442,8 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH l*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; PUSH_L(temp); PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1); diff --git a/src/x86_ops_inc_dec.h b/src/x86_ops_inc_dec.h index b13070c..8b9509b 100644 --- a/src/x86_ops_inc_dec.h +++ b/src/x86_ops_inc_dec.h @@ -50,6 +50,8 @@ static int opINCDEC_b_a16(uint32_t fetchdat) uint8_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp=geteab(); if (cpu_state.abrt) return 1; if (rmdat&0x38) @@ -71,6 +73,8 @@ static int opINCDEC_b_a32(uint32_t fetchdat) uint8_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp=geteab(); if (cpu_state.abrt) return 1; if (rmdat&0x38) diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index 43c0d97..354059d 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -54,6 +54,7 @@ static int opF6_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); } dst = geteab(); if (cpu_state.abrt) return 1; @@ -68,11 +69,15 @@ static int opF6_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x10: /*NOT b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteab(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x18: /*NEG b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteab(0 - dst); if (cpu_state.abrt) return 1; setsub8(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); @@ -156,6 +161,8 @@ static int opF6_a32(uint32_t fetchdat) int8_t temps; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteab(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) { @@ -168,11 +175,15 @@ static int opF6_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x10: /*NOT b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteab(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x18: /*NEG b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteab(0 - dst); if (cpu_state.abrt) return 1; setsub8(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); @@ -259,6 +270,8 @@ static int opF7_w_a16(uint32_t fetchdat) uint16_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteaw(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) { @@ -271,11 +284,15 @@ static int opF7_w_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x10: /*NOT w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x18: /*NEG w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(0 - dst); if (cpu_state.abrt) return 1; setsub16(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); @@ -353,6 +370,8 @@ static int opF7_w_a32(uint32_t fetchdat) uint16_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteaw(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) { @@ -365,11 +384,15 @@ static int opF7_w_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x10: /*NOT w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x18: /*NEG w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(0 - dst); if (cpu_state.abrt) return 1; setsub16(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); @@ -446,6 +469,8 @@ static int opF7_l_a16(uint32_t fetchdat) uint32_t src, dst; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteal(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) @@ -459,11 +484,15 @@ static int opF7_l_a16(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; case 0x10: /*NOT l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteal(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x18: /*NEG l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteal(0 - dst); if (cpu_state.abrt) return 1; setsub32(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); @@ -516,6 +545,8 @@ static int opF7_l_a32(uint32_t fetchdat) uint32_t src, dst; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); dst = geteal(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) @@ -529,11 +560,15 @@ static int opF7_l_a32(uint32_t fetchdat) PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; case 0x10: /*NOT l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteal(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x18: /*NEG l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteal(0 - dst); if (cpu_state.abrt) return 1; setsub32(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); @@ -625,6 +660,7 @@ static int opBOUND_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteaw(); high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -644,6 +680,7 @@ static int opBOUND_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteaw(); high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -664,6 +701,7 @@ static int opBOUND_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteal(); high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; @@ -683,6 +721,7 @@ static int opBOUND_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteal(); high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; diff --git a/src/x86_ops_mmx.h b/src/x86_ops_mmx.h index 4397a39..4f361c6 100644 --- a/src/x86_ops_mmx.h +++ b/src/x86_ops_mmx.h @@ -11,6 +11,7 @@ } \ else \ { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ src.q = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; \ CLOCK_CYCLES(2); \ } diff --git a/src/x86_ops_mmx_arith.h b/src/x86_ops_mmx_arith.h index 0a66eea..231662c 100644 --- a/src/x86_ops_mmx_arith.h +++ b/src/x86_ops_mmx_arith.h @@ -293,7 +293,8 @@ static int opPMULLW_a16(uint32_t fetchdat) else { MMX_REG src; - + + SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; cpu_state.MM[cpu_reg].w[0] *= src.w[0]; @@ -321,6 +322,7 @@ static int opPMULLW_a32(uint32_t fetchdat) { MMX_REG src; + SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; cpu_state.MM[cpu_reg].w[0] *= src.w[0]; @@ -349,6 +351,7 @@ static int opPMULHW_a16(uint32_t fetchdat) { MMX_REG src; + SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) >> 16; @@ -376,6 +379,7 @@ static int opPMULHW_a32(uint32_t fetchdat) { MMX_REG src; + SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) >> 16; diff --git a/src/x86_ops_mmx_mov.h b/src/x86_ops_mmx_mov.h index 37899b3..133d48d 100644 --- a/src/x86_ops_mmx_mov.h +++ b/src/x86_ops_mmx_mov.h @@ -12,7 +12,8 @@ static int opMOVD_l_mm_a16(uint32_t fetchdat) else { uint32_t dst; - + + SEG_CHECK_READ(cpu_state.ea_seg); dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; cpu_state.MM[cpu_reg].l[0] = dst; cpu_state.MM[cpu_reg].l[1] = 0; @@ -35,7 +36,8 @@ static int opMOVD_l_mm_a32(uint32_t fetchdat) else { uint32_t dst; - + + SEG_CHECK_READ(cpu_state.ea_seg); dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; cpu_state.MM[cpu_reg].l[0] = dst; cpu_state.MM[cpu_reg].l[1] = 0; @@ -57,6 +59,7 @@ static int opMOVD_mm_l_a16(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; CLOCK_CYCLES(2); @@ -75,6 +78,7 @@ static int opMOVD_mm_l_a32(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; CLOCK_CYCLES(2); @@ -96,6 +100,7 @@ static int opMOVQ_q_mm_a16(uint32_t fetchdat) { uint64_t dst; + SEG_CHECK_READ(cpu_state.ea_seg); dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; cpu_state.MM[cpu_reg].q = dst; CLOCK_CYCLES(2); @@ -116,6 +121,7 @@ static int opMOVQ_q_mm_a32(uint32_t fetchdat) { uint64_t dst; + SEG_CHECK_READ(cpu_state.ea_seg); dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; cpu_state.MM[cpu_reg].q = dst; CLOCK_CYCLES(2); @@ -135,6 +141,7 @@ static int opMOVQ_mm_q_a16(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1; CLOCK_CYCLES(2); @@ -153,6 +160,7 @@ static int opMOVQ_mm_q_a32(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1; CLOCK_CYCLES(2); diff --git a/src/x86_ops_mmx_pack.h b/src/x86_ops_mmx_pack.h index cdba2a2..5b8b798 100644 --- a/src/x86_ops_mmx_pack.h +++ b/src/x86_ops_mmx_pack.h @@ -12,6 +12,7 @@ static int opPUNPCKLDQ_a16(uint32_t fetchdat) { uint32_t src; + SEG_CHECK_READ(cpu_state.ea_seg); src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; cpu_state.MM[cpu_reg].l[1] = src; @@ -32,7 +33,8 @@ static int opPUNPCKLDQ_a32(uint32_t fetchdat) else { uint32_t src; - + + SEG_CHECK_READ(cpu_state.ea_seg); src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; cpu_state.MM[cpu_reg].l[1] = src; diff --git a/src/x86_ops_mmx_shift.h b/src/x86_ops_mmx_shift.h index ad3fc16..d641279 100644 --- a/src/x86_ops_mmx_shift.h +++ b/src/x86_ops_mmx_shift.h @@ -6,6 +6,7 @@ } \ else \ { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ shift = readmemb(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; \ CLOCK_CYCLES(2); \ } diff --git a/src/x86_ops_mov.h b/src/x86_ops_mov.h index 64072bf..6a0a087 100644 --- a/src/x86_ops_mov.h +++ b/src/x86_ops_mov.h @@ -182,6 +182,7 @@ static int opMOV_b_imm_a16(uint32_t fetchdat) uint8_t temp; fetch_ea_16(fetchdat); ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = readmemb(cs,cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); seteab(temp); @@ -194,6 +195,7 @@ static int opMOV_b_imm_a32(uint32_t fetchdat) uint8_t temp; fetch_ea_32(fetchdat); ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = getbyte(); if (cpu_state.abrt) return 1; seteab(temp); CLOCK_CYCLES(timing_rr); @@ -206,6 +208,7 @@ static int opMOV_w_imm_a16(uint32_t fetchdat) uint16_t temp; fetch_ea_16(fetchdat); ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = getword(); if (cpu_state.abrt) return 1; seteaw(temp); CLOCK_CYCLES(timing_rr); @@ -217,6 +220,7 @@ static int opMOV_w_imm_a32(uint32_t fetchdat) uint16_t temp; fetch_ea_32(fetchdat); ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = getword(); if (cpu_state.abrt) return 1; seteaw(temp); CLOCK_CYCLES(timing_rr); @@ -228,6 +232,7 @@ static int opMOV_l_imm_a16(uint32_t fetchdat) uint32_t temp; fetch_ea_16(fetchdat); ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = getlong(); if (cpu_state.abrt) return 1; seteal(temp); CLOCK_CYCLES(timing_rr); @@ -239,6 +244,7 @@ static int opMOV_l_imm_a32(uint32_t fetchdat) uint32_t temp; fetch_ea_32(fetchdat); ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = getlong(); if (cpu_state.abrt) return 1; seteal(temp); CLOCK_CYCLES(timing_rr); @@ -251,6 +257,7 @@ static int opMOV_AL_a16(uint32_t fetchdat) { uint16_t addr = getwordf(); uint8_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, addr, addr); temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AL = temp; @@ -262,6 +269,7 @@ static int opMOV_AL_a32(uint32_t fetchdat) { uint32_t addr = getlong(); uint8_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, addr, addr); temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AL = temp; @@ -273,6 +281,7 @@ static int opMOV_AX_a16(uint32_t fetchdat) { uint16_t addr = getwordf(); uint16_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, addr, addr+1); temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AX = temp; @@ -284,6 +293,7 @@ static int opMOV_AX_a32(uint32_t fetchdat) { uint32_t addr = getlong(); uint16_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, addr, addr+1); temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AX = temp; @@ -295,6 +305,7 @@ static int opMOV_EAX_a16(uint32_t fetchdat) { uint16_t addr = getwordf(); uint32_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, addr, addr+3); temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; EAX = temp; @@ -306,6 +317,7 @@ static int opMOV_EAX_a32(uint32_t fetchdat) { uint32_t addr = getlong(); uint32_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, addr, addr+3); temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; EAX = temp; @@ -317,6 +329,7 @@ static int opMOV_EAX_a32(uint32_t fetchdat) static int opMOV_a16_AL(uint32_t fetchdat) { uint16_t addr = getwordf(); + SEG_CHECK_WRITE(cpu_state.ea_seg); writememb(cpu_state.ea_seg->base, addr, AL); CLOCK_CYCLES((is486) ? 1 : 2); PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); @@ -325,6 +338,7 @@ static int opMOV_a16_AL(uint32_t fetchdat) static int opMOV_a32_AL(uint32_t fetchdat) { uint32_t addr = getlong(); + SEG_CHECK_WRITE(cpu_state.ea_seg); writememb(cpu_state.ea_seg->base, addr, AL); CLOCK_CYCLES((is486) ? 1 : 2); PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); @@ -333,6 +347,7 @@ static int opMOV_a32_AL(uint32_t fetchdat) static int opMOV_a16_AX(uint32_t fetchdat) { uint16_t addr = getwordf(); + SEG_CHECK_WRITE(cpu_state.ea_seg); writememw(cpu_state.ea_seg->base, addr, AX); CLOCK_CYCLES((is486) ? 1 : 2); PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); @@ -341,6 +356,7 @@ static int opMOV_a16_AX(uint32_t fetchdat) static int opMOV_a32_AX(uint32_t fetchdat) { uint32_t addr = getlong(); if (cpu_state.abrt) return 1; + SEG_CHECK_WRITE(cpu_state.ea_seg); writememw(cpu_state.ea_seg->base, addr, AX); CLOCK_CYCLES((is486) ? 1 : 2); PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); @@ -349,6 +365,7 @@ static int opMOV_a32_AX(uint32_t fetchdat) static int opMOV_a16_EAX(uint32_t fetchdat) { uint16_t addr = getwordf(); + SEG_CHECK_WRITE(cpu_state.ea_seg); writememl(cpu_state.ea_seg->base, addr, EAX); CLOCK_CYCLES((is486) ? 1 : 2); PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0); @@ -357,6 +374,7 @@ static int opMOV_a16_EAX(uint32_t fetchdat) static int opMOV_a32_EAX(uint32_t fetchdat) { uint32_t addr = getlong(); if (cpu_state.abrt) return 1; + SEG_CHECK_WRITE(cpu_state.ea_seg); writememl(cpu_state.ea_seg->base, addr, EAX); CLOCK_CYCLES((is486) ? 1 : 2); PREFETCH_RUN(2, 5, -1, 0,0,0,1, 1); @@ -407,7 +425,10 @@ static int opLEA_l_a32(uint32_t fetchdat) static int opXLAT_a16(uint32_t fetchdat) { uint32_t addr = (BX + AL)&0xFFFF; - uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AL = temp; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); @@ -416,7 +437,10 @@ static int opXLAT_a16(uint32_t fetchdat) static int opXLAT_a32(uint32_t fetchdat) { uint32_t addr = EBX + AL; - uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AL = temp; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); @@ -434,6 +458,7 @@ static int opMOV_b_r_a16(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); seteab(getr8(cpu_reg)); CLOCK_CYCLES(is486 ? 1 : 2); @@ -452,6 +477,7 @@ static int opMOV_b_r_a32(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); seteab(getr8(cpu_reg)); CLOCK_CYCLES(is486 ? 1 : 2); @@ -470,6 +496,7 @@ static int opMOV_w_r_a16(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); seteaw(cpu_state.regs[cpu_reg].w); CLOCK_CYCLES(is486 ? 1 : 2); @@ -488,6 +515,7 @@ static int opMOV_w_r_a32(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); seteaw(cpu_state.regs[cpu_reg].w); CLOCK_CYCLES(is486 ? 1 : 2); @@ -506,6 +534,7 @@ static int opMOV_l_r_a16(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); seteal(cpu_state.regs[cpu_reg].l); CLOCK_CYCLES(is486 ? 1 : 2); @@ -524,6 +553,7 @@ static int opMOV_l_r_a32(uint32_t fetchdat) } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); seteal(cpu_state.regs[cpu_reg].l); CLOCK_CYCLES(is486 ? 1 : 2); @@ -544,6 +574,7 @@ static int opMOV_r_b_a16(uint32_t fetchdat) else { uint8_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); temp = geteab(); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); @@ -564,6 +595,7 @@ static int opMOV_r_b_a32(uint32_t fetchdat) else { uint8_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); temp = geteab(); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); @@ -584,6 +616,7 @@ static int opMOV_r_w_a16(uint32_t fetchdat) else { uint16_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; @@ -604,6 +637,7 @@ static int opMOV_r_w_a32(uint32_t fetchdat) else { uint16_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; @@ -624,6 +658,7 @@ static int opMOV_r_l_a16(uint32_t fetchdat) else { uint32_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); temp = geteal(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; @@ -644,6 +679,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) else { uint32_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); temp = geteal(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; @@ -664,6 +700,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) else \ { \ uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \ temp = geteaw(); if (cpu_state.abrt) return 1; \ cpu_state.regs[cpu_reg].w = temp; \ @@ -682,6 +719,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) else \ { \ uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \ temp = geteaw(); if (cpu_state.abrt) return 1; \ cpu_state.regs[cpu_reg].w = temp; \ @@ -700,6 +738,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) else \ { \ uint32_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \ temp = geteal(); if (cpu_state.abrt) return 1; \ cpu_state.regs[cpu_reg].l = temp; \ @@ -719,6 +758,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) { \ uint32_t temp; \ CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ temp = geteal(); if (cpu_state.abrt) return 1; \ cpu_state.regs[cpu_reg].l = temp; \ } \ diff --git a/src/x86_ops_mov_seg.h b/src/x86_ops_mov_seg.h index 5153bb1..ecaeba1 100644 --- a/src/x86_ops_mov_seg.h +++ b/src/x86_ops_mov_seg.h @@ -1,7 +1,9 @@ static int opMOV_w_seg_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + switch (rmdat & 0x38) { case 0x00: /*ES*/ @@ -31,7 +33,9 @@ static int opMOV_w_seg_a16(uint32_t fetchdat) static int opMOV_w_seg_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + switch (rmdat & 0x38) { case 0x00: /*ES*/ @@ -62,7 +66,9 @@ static int opMOV_w_seg_a32(uint32_t fetchdat) static int opMOV_l_seg_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + switch (rmdat & 0x38) { case 0x00: /*ES*/ @@ -98,7 +104,9 @@ static int opMOV_l_seg_a16(uint32_t fetchdat) static int opMOV_l_seg_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + switch (rmdat & 0x38) { case 0x00: /*ES*/ @@ -137,7 +145,8 @@ static int opMOV_seg_w_a16(uint32_t fetchdat) uint16_t new_seg; fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_seg=geteaw(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) @@ -177,7 +186,8 @@ static int opMOV_seg_w_a32(uint32_t fetchdat) uint16_t new_seg; fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); new_seg=geteaw(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) @@ -220,6 +230,7 @@ static int opLDS_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; loadseg(seg, &_ds); if (cpu_state.abrt) return 1; @@ -235,6 +246,7 @@ static int opLDS_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; loadseg(seg, &_ds); if (cpu_state.abrt) return 1; @@ -251,6 +263,7 @@ static int opLDS_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; loadseg(seg, &_ds); if (cpu_state.abrt) return 1; @@ -267,6 +280,7 @@ static int opLDS_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; loadseg(seg, &_ds); if (cpu_state.abrt) return 1; @@ -283,6 +297,7 @@ static int opLSS_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; loadseg(seg, &_ss); if (cpu_state.abrt) return 1; @@ -298,6 +313,7 @@ static int opLSS_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; loadseg(seg, &_ss); if (cpu_state.abrt) return 1; @@ -314,6 +330,7 @@ static int opLSS_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; loadseg(seg, &_ss); if (cpu_state.abrt) return 1; @@ -330,6 +347,7 @@ static int opLSS_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; loadseg(seg, &_ss); if (cpu_state.abrt) return 1; @@ -346,6 +364,7 @@ static int opLSS_l_a32(uint32_t fetchdat) uint16_t addr, seg; \ \ fetch_ea_16(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ addr = readmemw(easeg, cpu_state.eaaddr); \ seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \ @@ -362,6 +381,7 @@ static int opLSS_l_a32(uint32_t fetchdat) uint16_t addr, seg; \ \ fetch_ea_32(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ addr = readmemw(easeg, cpu_state.eaaddr); \ seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \ @@ -379,6 +399,7 @@ static int opLSS_l_a32(uint32_t fetchdat) uint16_t seg; \ \ fetch_ea_16(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ addr = readmeml(easeg, cpu_state.eaaddr); \ seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \ @@ -396,6 +417,7 @@ static int opLSS_l_a32(uint32_t fetchdat) uint16_t seg; \ \ fetch_ea_32(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ ILLEGAL_ON(cpu_mod == 3); \ addr = readmeml(easeg, cpu_state.eaaddr); \ seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \ diff --git a/src/x86_ops_movx.h b/src/x86_ops_movx.h index 9dfced8..2f679b0 100644 --- a/src/x86_ops_movx.h +++ b/src/x86_ops_movx.h @@ -3,6 +3,8 @@ static int opMOVZX_w_b_a16(uint32_t fetchdat) uint8_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = (uint16_t)temp; @@ -15,6 +17,8 @@ static int opMOVZX_w_b_a32(uint32_t fetchdat) uint8_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = (uint16_t)temp; @@ -27,6 +31,8 @@ static int opMOVZX_l_b_a16(uint32_t fetchdat) uint8_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; @@ -39,6 +45,8 @@ static int opMOVZX_l_b_a32(uint32_t fetchdat) uint8_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; @@ -51,6 +59,8 @@ static int opMOVZX_w_w_a16(uint32_t fetchdat) uint16_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; @@ -63,6 +73,8 @@ static int opMOVZX_w_w_a32(uint32_t fetchdat) uint16_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; @@ -75,6 +87,8 @@ static int opMOVZX_l_w_a16(uint32_t fetchdat) uint16_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; @@ -87,6 +101,8 @@ static int opMOVZX_l_w_a32(uint32_t fetchdat) uint16_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; @@ -100,6 +116,8 @@ static int opMOVSX_w_b_a16(uint32_t fetchdat) uint8_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = (uint16_t)temp; if (temp & 0x80) @@ -114,6 +132,8 @@ static int opMOVSX_w_b_a32(uint32_t fetchdat) uint8_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = (uint16_t)temp; if (temp & 0x80) @@ -128,6 +148,8 @@ static int opMOVSX_l_b_a16(uint32_t fetchdat) uint8_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; if (temp & 0x80) @@ -142,6 +164,8 @@ static int opMOVSX_l_b_a32(uint32_t fetchdat) uint8_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; if (temp & 0x80) @@ -156,6 +180,8 @@ static int opMOVSX_l_w_a16(uint32_t fetchdat) uint16_t temp; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; if (temp & 0x8000) @@ -170,6 +196,8 @@ static int opMOVSX_l_w_a32(uint32_t fetchdat) uint16_t temp; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = (uint32_t)temp; if (temp & 0x8000) diff --git a/src/x86_ops_mul.h b/src/x86_ops_mul.h index 9a316b9..27778b0 100644 --- a/src/x86_ops_mul.h +++ b/src/x86_ops_mul.h @@ -4,7 +4,9 @@ static int opIMUL_w_iw_a16(uint32_t fetchdat) int16_t tempw, tempw2; fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); if (cpu_state.abrt) return 1; tempw2 = getword(); if (cpu_state.abrt) return 1; @@ -24,7 +26,9 @@ static int opIMUL_w_iw_a32(uint32_t fetchdat) int16_t tempw, tempw2; fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); if (cpu_state.abrt) return 1; tempw2 = getword(); if (cpu_state.abrt) return 1; @@ -45,7 +49,9 @@ static int opIMUL_l_il_a16(uint32_t fetchdat) int32_t templ, templ2; fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); if (cpu_state.abrt) return 1; templ2 = getlong(); if (cpu_state.abrt) return 1; @@ -65,7 +71,9 @@ static int opIMUL_l_il_a32(uint32_t fetchdat) int32_t templ, templ2; fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); if (cpu_state.abrt) return 1; templ2 = getlong(); if (cpu_state.abrt) return 1; @@ -86,7 +94,9 @@ static int opIMUL_w_ib_a16(uint32_t fetchdat) int16_t tempw, tempw2; fetch_ea_16(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); if (cpu_state.abrt) return 1; tempw2 = getbyte(); if (cpu_state.abrt) return 1; if (tempw2 & 0x80) tempw2 |= 0xff00; @@ -107,7 +117,9 @@ static int opIMUL_w_ib_a32(uint32_t fetchdat) int16_t tempw, tempw2; fetch_ea_32(fetchdat); - + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); if (cpu_state.abrt) return 1; tempw2 = getbyte(); if (cpu_state.abrt) return 1; if (tempw2 & 0x80) tempw2 |= 0xff00; @@ -129,6 +141,9 @@ static int opIMUL_l_ib_a16(uint32_t fetchdat) int32_t templ, templ2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); if (cpu_state.abrt) return 1; templ2 = getbyte(); if (cpu_state.abrt) return 1; if (templ2 & 0x80) templ2 |= 0xffffff00; @@ -149,6 +164,9 @@ static int opIMUL_l_ib_a32(uint32_t fetchdat) int32_t templ, templ2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); if (cpu_state.abrt) return 1; templ2 = getbyte(); if (cpu_state.abrt) return 1; if (templ2 & 0x80) templ2 |= 0xffffff00; @@ -171,6 +189,9 @@ static int opIMUL_w_w_a16(uint32_t fetchdat) int32_t templ; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = templ & 0xFFFF; @@ -187,6 +208,9 @@ static int opIMUL_w_w_a32(uint32_t fetchdat) int32_t templ; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = templ & 0xFFFF; @@ -204,6 +228,9 @@ static int opIMUL_l_l_a16(uint32_t fetchdat) int64_t temp64; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; @@ -220,6 +247,9 @@ static int opIMUL_l_l_a32(uint32_t fetchdat) int64_t temp64; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; diff --git a/src/x86_ops_pmode.h b/src/x86_ops_pmode.h index 288d1bb..a59340b 100644 --- a/src/x86_ops_pmode.h +++ b/src/x86_ops_pmode.h @@ -4,6 +4,8 @@ static int opARPL_a16(uint32_t fetchdat) NOTRM fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); pclog("ARPL_a16\n"); temp_seg = geteaw(); if (cpu_state.abrt) return 1; @@ -27,7 +29,9 @@ static int opARPL_a32(uint32_t fetchdat) NOTRM fetch_ea_32(fetchdat); - pclog("ARPL_a32\n"); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + pclog("ARPL_a32\n"); temp_seg = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -53,6 +57,8 @@ static int opARPL_a32(uint32_t fetchdat) \ NOTRM \ fetch_ea(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ \ sel = geteaw(); if (cpu_state.abrt) return 1; \ \ @@ -103,6 +109,8 @@ opLAR(l_a32, fetch_ea_32, 1, 1) \ NOTRM \ fetch_ea(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ \ sel = geteaw(); if (cpu_state.abrt) return 1; \ flags_rebuild(); \ @@ -163,11 +171,15 @@ static int op0F00_common(uint32_t fetchdat, int ea32) switch (rmdat & 0x38) { case 0x00: /*SLDT*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(ldt.seg); CLOCK_CYCLES(4); PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x08: /*STR*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(tr.seg); CLOCK_CYCLES(4); PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); @@ -179,6 +191,8 @@ static int op0F00_common(uint32_t fetchdat, int ea32) x86gpf(NULL,0); return 1; } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); sel = geteaw(); if (cpu_state.abrt) return 1; addr = (sel & ~7) + gdt.base; limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); @@ -205,6 +219,8 @@ static int op0F00_common(uint32_t fetchdat, int ea32) x86gpf(NULL,0); break; } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); sel = geteaw(); if (cpu_state.abrt) return 1; addr = (sel & ~7) + gdt.base; limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); @@ -228,6 +244,8 @@ static int op0F00_common(uint32_t fetchdat, int ea32) PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32); break; case 0x20: /*VERR*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); sel = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); flags &= ~Z_FLAG; @@ -248,6 +266,8 @@ static int op0F00_common(uint32_t fetchdat, int ea32) PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); break; case 0x28: /*VERW*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); sel = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); flags &= ~Z_FLAG; @@ -300,6 +320,8 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) switch (rmdat & 0x38) { case 0x00: /*SGDT*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(gdt.limit); base = gdt.base; //is32 ? gdt.base : (gdt.base & 0xffffff); if (is286) @@ -309,6 +331,8 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32); break; case 0x08: /*SIDT*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(idt.limit); base = idt.base; if (is286) @@ -324,6 +348,8 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) x86gpf(NULL,0); break; } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); // pclog("LGDT %08X:%08X\n", easeg, eaaddr); limit = geteaw(); base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -341,6 +367,8 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) x86gpf(NULL,0); break; } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); // pclog("LIDT %08X:%08X\n", easeg, eaaddr); limit = geteaw(); base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -353,6 +381,8 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) break; case 0x20: /*SMSW*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); if (is486) seteaw(msw); else if (is386) seteaw(msw | 0xFF00); else seteaw(msw | 0xFFF0); @@ -366,6 +396,8 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) x86gpf(NULL, 0); break; } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); tempw = geteaw(); if (cpu_state.abrt) return 1; if (msw & 1) tempw |= 1; if (is386) @@ -391,6 +423,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) x86gpf(NULL, 0); break; } + SEG_CHECK_READ(cpu_state.ea_seg); mmu_invalidate(ds + cpu_state.eaaddr); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, rmdat, 0,0,0,0, ea32); diff --git a/src/x86_ops_rep.h b/src/x86_ops_rep.h index 66587ef..5b24beb 100644 --- a/src/x86_ops_rep.h +++ b/src/x86_ops_rep.h @@ -9,7 +9,8 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) { \ uint8_t temp; \ \ - check_io_perm(DX); \ + SEG_CHECK_WRITE(&_es); \ + check_io_perm(DX); \ temp = inb(DX); \ writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ @@ -36,6 +37,7 @@ static int opREP_INSW_ ## size(uint32_t fetchdat) { \ uint16_t temp; \ \ + SEG_CHECK_WRITE(&_es); \ check_io_perm(DX); \ check_io_perm(DX+1); \ temp = inw(DX); \ @@ -64,6 +66,7 @@ static int opREP_INSL_ ## size(uint32_t fetchdat) { \ uint32_t temp; \ \ + SEG_CHECK_WRITE(&_es); \ check_io_perm(DX); \ check_io_perm(DX+1); \ check_io_perm(DX+2); \ @@ -93,7 +96,9 @@ static int opREP_OUTSB_ ## size(uint32_t fetchdat) \ if (CNT_REG > 0) \ { \ - uint8_t temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + uint8_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ check_io_perm(DX); \ outb(DX, temp); \ if (flags & D_FLAG) SRC_REG--; \ @@ -117,7 +122,9 @@ static int opREP_OUTSW_ ## size(uint32_t fetchdat) \ if (CNT_REG > 0) \ { \ - uint16_t temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ check_io_perm(DX); \ check_io_perm(DX+1); \ outw(DX, temp); \ @@ -142,7 +149,9 @@ static int opREP_OUTSL_ ## size(uint32_t fetchdat) \ if (CNT_REG > 0) \ { \ - uint32_t temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ + uint32_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ check_io_perm(DX); \ check_io_perm(DX+1); \ check_io_perm(DX+2); \ @@ -170,6 +179,11 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&_es); \ + } \ while (CNT_REG > 0) \ { \ uint8_t temp; \ @@ -203,6 +217,11 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&_es); \ + } \ while (CNT_REG > 0) \ { \ uint16_t temp; \ @@ -236,6 +255,11 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&_es); \ + } \ while (CNT_REG > 0) \ { \ uint32_t temp; \ @@ -271,6 +295,8 @@ static int opREP_STOSB_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&_es); \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ @@ -299,6 +325,8 @@ static int opREP_STOSW_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&_es); \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+1); \ @@ -327,6 +355,8 @@ static int opREP_STOSL_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&_es); \ while (CNT_REG > 0) \ { \ CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+3); \ @@ -356,6 +386,8 @@ static int opREP_LODSB_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ while (CNT_REG > 0) \ { \ AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -383,6 +415,8 @@ static int opREP_LODSW_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ while (CNT_REG > 0) \ { \ AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -410,6 +444,8 @@ static int opREP_LODSL_ ## size(uint32_t fetchdat) int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ while (CNT_REG > 0) \ { \ EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ @@ -441,8 +477,11 @@ static int opREP_CMPSB_ ## size(uint32_t fetchdat) tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ { \ - uint8_t temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ - uint8_t temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ + uint8_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&_es); \ + temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ else { DEST_REG++; SRC_REG++; } \ @@ -468,8 +507,11 @@ static int opREP_CMPSW_ ## size(uint32_t fetchdat) tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ { \ - uint16_t temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ - uint16_t temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ + uint16_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&_es); \ + temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ else { DEST_REG += 2; SRC_REG += 2; } \ @@ -495,8 +537,11 @@ static int opREP_CMPSL_ ## size(uint32_t fetchdat) tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ { \ - uint32_t temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ - uint32_t temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ + uint32_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&_es); \ + temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ else { DEST_REG += 4; SRC_REG += 4; } \ @@ -523,6 +568,8 @@ static int opREP_SCASB_ ## size(uint32_t fetchdat) if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\ @@ -554,6 +601,8 @@ static int opREP_SCASW_ ## size(uint32_t fetchdat) if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\ @@ -585,6 +634,8 @@ static int opREP_SCASL_ ## size(uint32_t fetchdat) if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\ diff --git a/src/x86_ops_set.h b/src/x86_ops_set.h index 298f28c..5a3dfaa 100644 --- a/src/x86_ops_set.h +++ b/src/x86_ops_set.h @@ -2,6 +2,8 @@ static int opSET ## condition ## _a16(uint32_t fetchdat) \ { \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ seteab((cond_ ## condition) ? 1 : 0); \ CLOCK_CYCLES(4); \ return cpu_state.abrt; \ @@ -10,6 +12,8 @@ static int opSET ## condition ## _a32(uint32_t fetchdat) \ { \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ seteab((cond_ ## condition) ? 1 : 0); \ CLOCK_CYCLES(4); \ return cpu_state.abrt; \ diff --git a/src/x86_ops_shift.h b/src/x86_ops_shift.h index 5144d10..1fe2e89 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -281,6 +281,8 @@ static int opC0_a16(uint32_t fetchdat) uint8_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; PREFETCH_PREFIX(); temp = geteab(); if (cpu_state.abrt) return 1; @@ -294,6 +296,8 @@ static int opC0_a32(uint32_t fetchdat) uint8_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; PREFETCH_PREFIX(); temp = geteab(); if (cpu_state.abrt) return 1; @@ -307,6 +311,8 @@ static int opC1_w_a16(uint32_t fetchdat) uint16_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; PREFETCH_PREFIX(); temp = geteaw(); if (cpu_state.abrt) return 1; @@ -320,6 +326,8 @@ static int opC1_w_a32(uint32_t fetchdat) uint16_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; PREFETCH_PREFIX(); temp = geteaw(); if (cpu_state.abrt) return 1; @@ -333,6 +341,8 @@ static int opC1_l_a16(uint32_t fetchdat) uint32_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; PREFETCH_PREFIX(); temp = geteal(); if (cpu_state.abrt) return 1; @@ -346,6 +356,8 @@ static int opC1_l_a32(uint32_t fetchdat) uint32_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; PREFETCH_PREFIX(); temp = geteal(); if (cpu_state.abrt) return 1; @@ -360,6 +372,8 @@ static int opD0_a16(uint32_t fetchdat) uint8_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; OP_SHIFT_b(c, 0); return 0; @@ -371,6 +385,8 @@ static int opD0_a32(uint32_t fetchdat) uint8_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; OP_SHIFT_b(c, 1); return 0; @@ -382,6 +398,8 @@ static int opD1_w_a16(uint32_t fetchdat) uint16_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; OP_SHIFT_w(c, 0); return 0; @@ -393,6 +411,8 @@ static int opD1_w_a32(uint32_t fetchdat) uint16_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; OP_SHIFT_w(c, 1); return 0; @@ -404,6 +424,8 @@ static int opD1_l_a16(uint32_t fetchdat) uint32_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; OP_SHIFT_l(c, 0); return 0; @@ -415,6 +437,8 @@ static int opD1_l_a32(uint32_t fetchdat) uint32_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; OP_SHIFT_l(c, 1); return 0; @@ -427,6 +451,8 @@ static int opD2_a16(uint32_t fetchdat) uint8_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = CL & 31; temp = geteab(); if (cpu_state.abrt) return 1; OP_SHIFT_b(c, 0); @@ -439,6 +465,8 @@ static int opD2_a32(uint32_t fetchdat) uint8_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = CL & 31; temp = geteab(); if (cpu_state.abrt) return 1; OP_SHIFT_b(c, 1); @@ -451,6 +479,8 @@ static int opD3_w_a16(uint32_t fetchdat) uint16_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = CL & 31; temp = geteaw(); if (cpu_state.abrt) return 1; OP_SHIFT_w(c, 0); @@ -463,6 +493,8 @@ static int opD3_w_a32(uint32_t fetchdat) uint16_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = CL & 31; temp = geteaw(); if (cpu_state.abrt) return 1; OP_SHIFT_w(c, 1); @@ -475,6 +507,8 @@ static int opD3_l_a16(uint32_t fetchdat) uint32_t temp, temp2; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = CL & 31; temp = geteal(); if (cpu_state.abrt) return 1; OP_SHIFT_l(c, 0); @@ -487,6 +521,8 @@ static int opD3_l_a32(uint32_t fetchdat) uint32_t temp, temp2; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); c = CL & 31; temp = geteal(); if (cpu_state.abrt) return 1; OP_SHIFT_l(c, 1); @@ -552,6 +588,8 @@ static int opD3_l_a32(uint32_t fetchdat) int count; \ \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ count = getbyte() & 31; \ operation(); \ \ @@ -564,6 +602,8 @@ static int opD3_l_a32(uint32_t fetchdat) int count; \ \ fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ count = CL & 31; \ operation(); \ \ @@ -576,6 +616,8 @@ static int opD3_l_a32(uint32_t fetchdat) int count; \ \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ count = getbyte() & 31; \ operation(); \ \ @@ -588,6 +630,8 @@ static int opD3_l_a32(uint32_t fetchdat) int count; \ \ fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ count = CL & 31; \ operation(); \ \ diff --git a/src/x86_ops_stack.h b/src/x86_ops_stack.h index 31f0908..dbe333f 100644 --- a/src/x86_ops_stack.h +++ b/src/x86_ops_stack.h @@ -236,6 +236,8 @@ static int opPOPW_a16(uint32_t fetchdat) temp = POP_W(); if (cpu_state.abrt) return 1; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(temp); if (cpu_state.abrt) { @@ -255,6 +257,8 @@ static int opPOPW_a32(uint32_t fetchdat) temp = POP_W(); if (cpu_state.abrt) return 1; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(temp); if (cpu_state.abrt) { @@ -275,6 +279,8 @@ static int opPOPL_a16(uint32_t fetchdat) temp = POP_L(); if (cpu_state.abrt) return 1; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteal(temp); if (cpu_state.abrt) { @@ -294,6 +300,8 @@ static int opPOPL_a32(uint32_t fetchdat) temp = POP_L(); if (cpu_state.abrt) return 1; fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); seteal(temp); if (cpu_state.abrt) { diff --git a/src/x86_ops_string.h b/src/x86_ops_string.h index b08460b..d76b3f8 100644 --- a/src/x86_ops_string.h +++ b/src/x86_ops_string.h @@ -1,6 +1,10 @@ static int opMOVSB_a16(uint32_t fetchdat) { - uint8_t temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&_es); + temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememb(es, DI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } @@ -10,7 +14,11 @@ static int opMOVSB_a16(uint32_t fetchdat) } static int opMOVSB_a32(uint32_t fetchdat) { - uint8_t temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&_es); + temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememb(es, EDI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } @@ -21,7 +29,11 @@ static int opMOVSB_a32(uint32_t fetchdat) static int opMOVSW_a16(uint32_t fetchdat) { - uint16_t temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&_es); + temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememw(es, DI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } @@ -31,7 +43,11 @@ static int opMOVSW_a16(uint32_t fetchdat) } static int opMOVSW_a32(uint32_t fetchdat) { - uint16_t temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&_es); + temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememw(es, EDI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } @@ -42,7 +58,11 @@ static int opMOVSW_a32(uint32_t fetchdat) static int opMOVSL_a16(uint32_t fetchdat) { - uint32_t temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&_es); + temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememl(es, DI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } @@ -52,7 +72,11 @@ static int opMOVSL_a16(uint32_t fetchdat) } static int opMOVSL_a32(uint32_t fetchdat) { - uint32_t temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&_es); + temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememl(es, EDI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } @@ -64,8 +88,12 @@ static int opMOVSL_a32(uint32_t fetchdat) static int opCMPSB_a16(uint32_t fetchdat) { - uint8_t src = readmemb(cpu_state.ea_seg->base, SI); - uint8_t dst = readmemb(es, DI); if (cpu_state.abrt) return 1; + uint8_t src, dst; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&_es); + src = readmemb(cpu_state.ea_seg->base, SI); + dst = readmemb(es, DI); if (cpu_state.abrt) return 1; setsub8(src, dst); if (flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } @@ -75,8 +103,12 @@ static int opCMPSB_a16(uint32_t fetchdat) } static int opCMPSB_a32(uint32_t fetchdat) { - uint8_t src = readmemb(cpu_state.ea_seg->base, ESI); - uint8_t dst = readmemb(es, EDI); if (cpu_state.abrt) return 1; + uint8_t src, dst; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&_es); + src = readmemb(cpu_state.ea_seg->base, ESI); + dst = readmemb(es, EDI); if (cpu_state.abrt) return 1; setsub8(src, dst); if (flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } @@ -87,8 +119,12 @@ static int opCMPSB_a32(uint32_t fetchdat) static int opCMPSW_a16(uint32_t fetchdat) { - uint16_t src = readmemw(cpu_state.ea_seg->base, SI); - uint16_t dst = readmemw(es, DI); if (cpu_state.abrt) return 1; + uint16_t src, dst; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&_es); + src = readmemw(cpu_state.ea_seg->base, SI); + dst = readmemw(es, DI); if (cpu_state.abrt) return 1; setsub16(src, dst); if (flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } @@ -98,8 +134,12 @@ static int opCMPSW_a16(uint32_t fetchdat) } static int opCMPSW_a32(uint32_t fetchdat) { - uint16_t src = readmemw(cpu_state.ea_seg->base, ESI); - uint16_t dst = readmemw(es, EDI); if (cpu_state.abrt) return 1; + uint16_t src, dst; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&_es); + src = readmemw(cpu_state.ea_seg->base, ESI); + dst = readmemw(es, EDI); if (cpu_state.abrt) return 1; setsub16(src, dst); if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } @@ -110,8 +150,12 @@ static int opCMPSW_a32(uint32_t fetchdat) static int opCMPSL_a16(uint32_t fetchdat) { - uint32_t src = readmeml(cpu_state.ea_seg->base, SI); - uint32_t dst = readmeml(es, DI); if (cpu_state.abrt) return 1; + uint32_t src, dst; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&_es); + src = readmeml(cpu_state.ea_seg->base, SI); + dst = readmeml(es, DI); if (cpu_state.abrt) return 1; setsub32(src, dst); if (flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } @@ -121,8 +165,12 @@ static int opCMPSL_a16(uint32_t fetchdat) } static int opCMPSL_a32(uint32_t fetchdat) { - uint32_t src = readmeml(cpu_state.ea_seg->base, ESI); - uint32_t dst = readmeml(es, EDI); if (cpu_state.abrt) return 1; + uint32_t src, dst; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&_es); + src = readmeml(cpu_state.ea_seg->base, ESI); + dst = readmeml(es, EDI); if (cpu_state.abrt) return 1; setsub32(src, dst); if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } @@ -133,6 +181,7 @@ static int opCMPSL_a32(uint32_t fetchdat) static int opSTOSB_a16(uint32_t fetchdat) { + SEG_CHECK_WRITE(&_es); writememb(es, DI, AL); if (cpu_state.abrt) return 1; if (flags & D_FLAG) DI--; else DI++; @@ -142,6 +191,7 @@ static int opSTOSB_a16(uint32_t fetchdat) } static int opSTOSB_a32(uint32_t fetchdat) { + SEG_CHECK_WRITE(&_es); writememb(es, EDI, AL); if (cpu_state.abrt) return 1; if (flags & D_FLAG) EDI--; else EDI++; @@ -152,6 +202,7 @@ static int opSTOSB_a32(uint32_t fetchdat) static int opSTOSW_a16(uint32_t fetchdat) { + SEG_CHECK_WRITE(&_es); writememw(es, DI, AX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) DI -= 2; else DI += 2; @@ -161,6 +212,7 @@ static int opSTOSW_a16(uint32_t fetchdat) } static int opSTOSW_a32(uint32_t fetchdat) { + SEG_CHECK_WRITE(&_es); writememw(es, EDI, AX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) EDI -= 2; else EDI += 2; @@ -171,6 +223,7 @@ static int opSTOSW_a32(uint32_t fetchdat) static int opSTOSL_a16(uint32_t fetchdat) { + SEG_CHECK_WRITE(&_es); writememl(es, DI, EAX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) DI -= 4; else DI += 4; @@ -180,6 +233,7 @@ static int opSTOSL_a16(uint32_t fetchdat) } static int opSTOSL_a32(uint32_t fetchdat) { + SEG_CHECK_WRITE(&_es); writememl(es, EDI, EAX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) EDI -= 4; else EDI += 4; @@ -191,7 +245,10 @@ static int opSTOSL_a32(uint32_t fetchdat) static int opLODSB_a16(uint32_t fetchdat) { - uint8_t temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; AL = temp; if (flags & D_FLAG) SI--; else SI++; @@ -201,7 +258,10 @@ static int opLODSB_a16(uint32_t fetchdat) } static int opLODSB_a32(uint32_t fetchdat) { - uint8_t temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; AL = temp; if (flags & D_FLAG) ESI--; else ESI++; @@ -212,7 +272,10 @@ static int opLODSB_a32(uint32_t fetchdat) static int opLODSW_a16(uint32_t fetchdat) { - uint16_t temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; AX = temp; if (flags & D_FLAG) SI -= 2; else SI += 2; @@ -222,7 +285,10 @@ static int opLODSW_a16(uint32_t fetchdat) } static int opLODSW_a32(uint32_t fetchdat) { - uint16_t temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; AX = temp; if (flags & D_FLAG) ESI -= 2; else ESI += 2; @@ -233,7 +299,10 @@ static int opLODSW_a32(uint32_t fetchdat) static int opLODSL_a16(uint32_t fetchdat) { - uint32_t temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; EAX = temp; if (flags & D_FLAG) SI -= 4; else SI += 4; @@ -243,7 +312,10 @@ static int opLODSL_a16(uint32_t fetchdat) } static int opLODSL_a32(uint32_t fetchdat) { - uint32_t temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; EAX = temp; if (flags & D_FLAG) ESI -= 4; else ESI += 4; @@ -255,7 +327,10 @@ static int opLODSL_a32(uint32_t fetchdat) static int opSCASB_a16(uint32_t fetchdat) { - uint8_t temp = readmemb(es, DI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(&_es); + temp = readmemb(es, DI); if (cpu_state.abrt) return 1; setsub8(AL, temp); if (flags & D_FLAG) DI--; else DI++; @@ -265,7 +340,10 @@ static int opSCASB_a16(uint32_t fetchdat) } static int opSCASB_a32(uint32_t fetchdat) { - uint8_t temp = readmemb(es, EDI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(&_es); + temp = readmemb(es, EDI); if (cpu_state.abrt) return 1; setsub8(AL, temp); if (flags & D_FLAG) EDI--; else EDI++; @@ -276,7 +354,10 @@ static int opSCASB_a32(uint32_t fetchdat) static int opSCASW_a16(uint32_t fetchdat) { - uint16_t temp = readmemw(es, DI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(&_es); + temp = readmemw(es, DI); if (cpu_state.abrt) return 1; setsub16(AX, temp); if (flags & D_FLAG) DI -= 2; else DI += 2; @@ -286,7 +367,10 @@ static int opSCASW_a16(uint32_t fetchdat) } static int opSCASW_a32(uint32_t fetchdat) { - uint16_t temp = readmemw(es, EDI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(&_es); + temp = readmemw(es, EDI); if (cpu_state.abrt) return 1; setsub16(AX, temp); if (flags & D_FLAG) EDI -= 2; else EDI += 2; @@ -297,7 +381,10 @@ static int opSCASW_a32(uint32_t fetchdat) static int opSCASL_a16(uint32_t fetchdat) { - uint32_t temp = readmeml(es, DI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(&_es); + temp = readmeml(es, DI); if (cpu_state.abrt) return 1; setsub32(EAX, temp); if (flags & D_FLAG) DI -= 4; else DI += 4; @@ -307,7 +394,10 @@ static int opSCASL_a16(uint32_t fetchdat) } static int opSCASL_a32(uint32_t fetchdat) { - uint32_t temp = readmeml(es, EDI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(&_es); + temp = readmeml(es, EDI); if (cpu_state.abrt) return 1; setsub32(EAX, temp); if (flags & D_FLAG) EDI -= 4; else EDI += 4; @@ -319,6 +409,8 @@ static int opSCASL_a32(uint32_t fetchdat) static int opINSB_a16(uint32_t fetchdat) { uint8_t temp; + + SEG_CHECK_WRITE(&_es); check_io_perm(DX); temp = inb(DX); writememb(es, DI, temp); if (cpu_state.abrt) return 1; @@ -331,6 +423,8 @@ static int opINSB_a16(uint32_t fetchdat) static int opINSB_a32(uint32_t fetchdat) { uint8_t temp; + + SEG_CHECK_WRITE(&_es); check_io_perm(DX); temp = inb(DX); writememb(es, EDI, temp); if (cpu_state.abrt) return 1; @@ -344,6 +438,8 @@ static int opINSB_a32(uint32_t fetchdat) static int opINSW_a16(uint32_t fetchdat) { uint16_t temp; + + SEG_CHECK_WRITE(&_es); check_io_perm(DX); check_io_perm(DX + 1); temp = inw(DX); @@ -357,6 +453,8 @@ static int opINSW_a16(uint32_t fetchdat) static int opINSW_a32(uint32_t fetchdat) { uint16_t temp; + + SEG_CHECK_WRITE(&_es); check_io_perm(DX); check_io_perm(DX + 1); temp = inw(DX); @@ -371,6 +469,8 @@ static int opINSW_a32(uint32_t fetchdat) static int opINSL_a16(uint32_t fetchdat) { uint32_t temp; + + SEG_CHECK_WRITE(&_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); @@ -386,6 +486,8 @@ static int opINSL_a16(uint32_t fetchdat) static int opINSL_a32(uint32_t fetchdat) { uint32_t temp; + + SEG_CHECK_WRITE(&_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); @@ -401,7 +503,10 @@ static int opINSL_a32(uint32_t fetchdat) static int opOUTSB_a16(uint32_t fetchdat) { - uint8_t temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; check_io_perm(DX); if (flags & D_FLAG) SI--; else SI++; @@ -412,7 +517,10 @@ static int opOUTSB_a16(uint32_t fetchdat) } static int opOUTSB_a32(uint32_t fetchdat) { - uint8_t temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; check_io_perm(DX); if (flags & D_FLAG) ESI--; else ESI++; @@ -424,7 +532,10 @@ static int opOUTSB_a32(uint32_t fetchdat) static int opOUTSW_a16(uint32_t fetchdat) { - uint16_t temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; check_io_perm(DX); check_io_perm(DX + 1); if (flags & D_FLAG) SI -= 2; @@ -436,7 +547,10 @@ static int opOUTSW_a16(uint32_t fetchdat) } static int opOUTSW_a32(uint32_t fetchdat) { - uint16_t temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; check_io_perm(DX); check_io_perm(DX + 1); if (flags & D_FLAG) ESI -= 2; @@ -449,7 +563,10 @@ static int opOUTSW_a32(uint32_t fetchdat) static int opOUTSL_a16(uint32_t fetchdat) { - uint32_t temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); @@ -463,7 +580,10 @@ static int opOUTSL_a16(uint32_t fetchdat) } static int opOUTSL_a32(uint32_t fetchdat) { - uint32_t temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); diff --git a/src/x86_ops_xchg.h b/src/x86_ops_xchg.h index 6e08933..ae8f69c 100644 --- a/src/x86_ops_xchg.h +++ b/src/x86_ops_xchg.h @@ -1,7 +1,10 @@ static int opXCHG_b_a16(uint32_t fetchdat) { uint8_t temp; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); @@ -12,7 +15,10 @@ static int opXCHG_b_a16(uint32_t fetchdat) static int opXCHG_b_a32(uint32_t fetchdat) { uint8_t temp; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteab(); if (cpu_state.abrt) return 1; seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); @@ -24,7 +30,10 @@ static int opXCHG_b_a32(uint32_t fetchdat) static int opXCHG_w_a16(uint32_t fetchdat) { uint16_t temp; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; @@ -35,7 +44,10 @@ static int opXCHG_w_a16(uint32_t fetchdat) static int opXCHG_w_a32(uint32_t fetchdat) { uint16_t temp; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; @@ -47,7 +59,10 @@ static int opXCHG_w_a32(uint32_t fetchdat) static int opXCHG_l_a16(uint32_t fetchdat) { uint32_t temp; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; @@ -58,7 +73,10 @@ static int opXCHG_l_a16(uint32_t fetchdat) static int opXCHG_l_a32(uint32_t fetchdat) { uint32_t temp; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); temp = geteal(); if (cpu_state.abrt) return 1; seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h index 6723bd1..45077c7 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -4,6 +4,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ if ((cpu_state.npxc >> 10) & 3) \ fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \ @@ -19,6 +20,7 @@ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ @@ -30,6 +32,7 @@ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ @@ -42,6 +45,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), ST(0), use_var); \ cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ @@ -53,6 +57,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), use_var, ST(0)); \ cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ @@ -64,6 +69,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) *= use_var; \ cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ @@ -75,6 +81,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) -= use_var; \ cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ @@ -86,6 +93,7 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) = use_var - ST(0); \ cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h index 09bbf82..bf9fc1f 100644 --- a/src/x87_ops_loadstore.h +++ b/src/x87_ops_loadstore.h @@ -3,6 +3,7 @@ static int opFILDiw_a16(uint32_t fetchdat) int16_t temp; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr); temp = geteaw(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", (double)temp); @@ -15,6 +16,7 @@ static int opFILDiw_a32(uint32_t fetchdat) int16_t temp; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr); temp = geteaw(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", (double)temp); @@ -28,6 +30,7 @@ static int opFISTiw_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) @@ -41,6 +44,7 @@ static int opFISTiw_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) @@ -55,6 +59,7 @@ static int opFISTPiw_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) @@ -69,6 +74,7 @@ static int opFISTPiw_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) @@ -84,6 +90,7 @@ static int opFILDiq_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); @@ -99,6 +106,7 @@ static int opFILDiq_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); @@ -116,6 +124,7 @@ static int FBSTP_a16(uint32_t fetchdat) int c; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr); tempd = ST(0); if (tempd < 0.0) @@ -142,6 +151,7 @@ static int FBSTP_a32(uint32_t fetchdat) int c; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr); tempd = ST(0); if (tempd < 0.0) @@ -168,6 +178,7 @@ static int FISTPiq_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) temp64 = cpu_state.MM[cpu_state.TOP].q; @@ -183,6 +194,7 @@ static int FISTPiq_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) temp64 = cpu_state.MM[cpu_state.TOP].q; @@ -199,6 +211,7 @@ static int opFILDil_a16(uint32_t fetchdat) int32_t templ; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr); templ = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); @@ -211,6 +224,7 @@ static int opFILDil_a32(uint32_t fetchdat) int32_t templ; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr); templ = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); @@ -224,6 +238,7 @@ static int opFISTil_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) @@ -237,6 +252,7 @@ static int opFISTil_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) @@ -251,6 +267,7 @@ static int opFISTPil_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) @@ -265,6 +282,7 @@ static int opFISTPil_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) @@ -280,6 +298,7 @@ static int opFLDe_a16(uint32_t fetchdat) double t; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr); t=x87_ld80(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t); @@ -292,6 +311,7 @@ static int opFLDe_a32(uint32_t fetchdat) double t; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr); t=x87_ld80(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t); @@ -304,6 +324,7 @@ static int opFSTPe_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); @@ -314,6 +335,7 @@ static int opFSTPe_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); @@ -326,6 +348,7 @@ static int opFLDd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr); t.i = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t.d); @@ -338,6 +361,7 @@ static int opFLDd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr); t.i = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t.d); @@ -351,6 +375,7 @@ static int opFSTd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); @@ -362,6 +387,7 @@ static int opFSTd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); @@ -374,6 +400,7 @@ static int opFSTPd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); @@ -387,6 +414,7 @@ static int opFSTPd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); @@ -401,6 +429,7 @@ static int opFLDs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.i = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", ts.s); @@ -413,6 +442,7 @@ static int opFLDs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.i = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", ts.s); @@ -426,6 +456,7 @@ static int opFSTs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); @@ -437,6 +468,7 @@ static int opFSTs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); @@ -449,6 +481,7 @@ static int opFSTPs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; @@ -461,6 +494,7 @@ static int opFSTPs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 4305487..5f21a99 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -127,6 +127,7 @@ static int opFSTOR_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); FSTOR(); return cpu_state.abrt; } @@ -134,6 +135,7 @@ static int opFSTOR_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); FSTOR(); return cpu_state.abrt; } @@ -287,6 +289,7 @@ static int opFSAVE_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSAVE(); return cpu_state.abrt; } @@ -294,6 +297,7 @@ static int opFSAVE_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSAVE(); return cpu_state.abrt; } @@ -302,6 +306,7 @@ static int opFSTSW_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); CLOCK_CYCLES(3); @@ -311,6 +316,7 @@ static int opFSTSW_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); CLOCK_CYCLES(3); @@ -698,6 +704,7 @@ static int opFLDENV_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); FLDENV(); return cpu_state.abrt; } @@ -705,6 +712,7 @@ static int opFLDENV_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); FLDENV(); return cpu_state.abrt; } @@ -714,6 +722,7 @@ static int opFLDCW_a16(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr); tempw = geteaw(); if (cpu_state.abrt) return 1; @@ -727,6 +736,7 @@ static int opFLDCW_a32(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr); tempw = geteaw(); if (cpu_state.abrt) return 1; @@ -784,6 +794,7 @@ static int opFSTENV_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSTENV(); return cpu_state.abrt; } @@ -791,6 +802,7 @@ static int opFSTENV_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSTENV(); return cpu_state.abrt; } @@ -799,6 +811,7 @@ static int opFSTCW_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw(cpu_state.npxc); CLOCK_CYCLES(3); @@ -808,6 +821,7 @@ static int opFSTCW_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw(cpu_state.npxc); CLOCK_CYCLES(3); From 4e7a13f45263dc3a6c883cff0e777f3100f0f7e1 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 18 Jul 2018 22:19:09 +0100 Subject: [PATCH 014/181] Corrected effective address for POP 0x8f. Windows 95 now works on recompiler. --- src/codegen.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 512b4b3..2ab186f 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -110,7 +110,7 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin return op_ea_seg; } -static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { uint32_t new_eaaddr; @@ -146,11 +146,12 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin (*op_pc) += 4; break; } -// if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ -// { + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ + { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset); // addbyte(0x05); // addlong(stack_offset); -// } + } if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) op_ea_seg = &_ss; if (((sib >> 3) & 7) != 4) @@ -444,10 +445,10 @@ generate_call: (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) { - //int stack_offset = 0; + int stack_offset = 0; -// if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ -// stack_offset = (op_32 & 0x100) ? 4 : 2; + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; cpu_mod = (fetchdat >> 6) & 3; cpu_reg = (fetchdat >> 3) & 7; @@ -463,7 +464,7 @@ generate_call: } if (cpu_mod != 3 && (op_32 & 0x200)) { - op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); + op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); // has_ea = 1; } // op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); From 91143d3c683a7c9c10ca03613ae49d9b659807ba Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 22 Jul 2018 12:56:03 +0100 Subject: [PATCH 015/181] Move CPU segment structures into cpu_state structure. --- src/386.c | 8 +- src/386_dynarec.c | 12 +-- src/808x.c | 32 +++---- src/codegen.c | 23 +++-- src/codegen_backend.c | 2 +- src/ibm.h | 29 +++--- src/x86_ops_misc.h | 43 +++++---- src/x86_ops_mov_seg.h | 46 +++++----- src/x86_ops_prefix.h | 36 ++++---- src/x86_ops_rep.h | 42 ++++----- src/x86_ops_stack.h | 16 ++-- src/x86_ops_string.h | 60 ++++++------ src/x86seg.c | 206 +++++++++++++++++++++--------------------- 13 files changed, 279 insertions(+), 276 deletions(-) diff --git a/src/386.c b/src/386.c index cb78c4e..dc254d3 100644 --- a/src/386.c +++ b/src/386.c @@ -90,7 +90,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) { easeg = ss; ea_rseg = SS; - cpu_state.ea_seg = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } if (((sib >> 3) & 7) != 4) cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); @@ -104,7 +104,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) { easeg = ss; ea_rseg = SS; - cpu_state.ea_seg = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } if (cpu_mod == 1) { @@ -159,7 +159,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) { easeg = ss; ea_rseg = SS; - cpu_state.ea_seg = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } cpu_state.eaaddr &= 0xFFFF; } @@ -244,7 +244,7 @@ void exec386(int cycs) dontprint=0; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; fetchdat = fastreadl(cs + cpu_state.pc); diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 7224d09..32cceb2 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -99,7 +99,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) { easeg = ss; ea_rseg = SS; - cpu_state.ea_seg = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } if (((sib >> 3) & 7) != 4) cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); @@ -113,7 +113,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) { easeg = ss; ea_rseg = SS; - cpu_state.ea_seg = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } if (cpu_mod == 1) { @@ -168,7 +168,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) { easeg = ss; ea_rseg = SS; - cpu_state.ea_seg = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } cpu_state.eaaddr &= 0xFFFF; } @@ -553,7 +553,7 @@ void exec386_dynarec(int cycs) oldcpl=CPL; cpu_state.op32 = use32; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; fetchdat = fastreadl(cs + cpu_state.pc); @@ -711,7 +711,7 @@ inrecomp=0; oldcpl=CPL; cpu_state.op32 = use32; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; fetchdat = fastreadl(cs + cpu_state.pc); @@ -793,7 +793,7 @@ inrecomp=0; oldcpl=CPL; cpu_state.op32 = use32; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; codegen_endpc = (cs + cpu_state.pc) + 8; diff --git a/src/808x.c b/src/808x.c index 082e0b0..9f66d45 100644 --- a/src/808x.c +++ b/src/808x.c @@ -577,15 +577,15 @@ void dumpregs() printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); else printf("In %s mode\n",(msw&1)?"protected":"real"); - printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); - printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); - printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); + printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,cpu_state.seg_cs.limit,cpu_state.seg_cs.access, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high); + printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,cpu_state.seg_ds.limit,cpu_state.seg_ds.access, cpu_state.seg_ds.limit_low, cpu_state.seg_ds.limit_high); + printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,cpu_state.seg_es.limit,cpu_state.seg_es.access, cpu_state.seg_es.limit_low, cpu_state.seg_es.limit_high); if (is386) { - printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); - printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); + printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cpu_state.seg_fs.base,cpu_state.seg_fs.limit,cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, cpu_state.seg_fs.limit_high); + printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,cpu_state.seg_gs.limit,cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, cpu_state.seg_gs.limit_high); } - printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); + printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,cpu_state.seg_ss.limit,cpu_state.seg_ss.access, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high); printf("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); printf("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); printf("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); @@ -1195,7 +1195,7 @@ void execx86(int cycs) case 0x07: /*POP ES*/ if (cpu_state.ssegs) ss=oldss; tempw=readmemw(ss,SP); - loadseg(tempw,&_es); + loadseg(tempw,&cpu_state.seg_es); SP+=2; cycles-=12; break; @@ -1258,7 +1258,7 @@ void execx86(int cycs) case 0x0F: /*POP CS - 8088/8086 only*/ if (cpu_state.ssegs) ss=oldss; tempw=readmemw(ss,SP); - loadseg(tempw,&_cs); + loadseg(tempw,&cpu_state.seg_cs); SP+=2; cycles-=12; break; @@ -1317,7 +1317,7 @@ void execx86(int cycs) case 0x17: /*POP SS*/ if (cpu_state.ssegs) ss=oldss; tempw=readmemw(ss,SP); - loadseg(tempw,&_ss); + loadseg(tempw,&cpu_state.seg_ss); SP+=2; noint=1; cycles-=12; @@ -1382,7 +1382,7 @@ void execx86(int cycs) case 0x1F: /*POP DS*/ if (cpu_state.ssegs) ss=oldss; tempw=readmemw(ss,SP); - loadseg(tempw,&_ds); + loadseg(tempw,&cpu_state.seg_ds); if (cpu_state.ssegs) oldds=ds; SP+=2; cycles-=12; @@ -2088,20 +2088,20 @@ void execx86(int cycs) { case 0x00: /*ES*/ tempw=geteaw(); - loadseg(tempw,&_es); + loadseg(tempw,&cpu_state.seg_es); break; case 0x08: /*CS - 8088/8086 only*/ tempw=geteaw(); - loadseg(tempw,&_cs); + loadseg(tempw,&cpu_state.seg_cs); break; case 0x18: /*DS*/ tempw=geteaw(); - loadseg(tempw,&_ds); + loadseg(tempw,&cpu_state.seg_ds); if (cpu_state.ssegs) oldds=ds; break; case 0x10: /*SS*/ tempw=geteaw(); - loadseg(tempw,&_ss); + loadseg(tempw,&cpu_state.seg_ss); if (cpu_state.ssegs) oldss=ss; // printf("LOAD SS %04X %04X\n",tempw,SS); // printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4); @@ -2350,14 +2350,14 @@ void execx86(int cycs) fetchea(); cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); //geteaw(); tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); //geteaw2(); - loadseg(tempw,&_es); + loadseg(tempw,&cpu_state.seg_es); cycles-=24; break; case 0xC5: /*LDS*/ fetchea(); cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_ds); + loadseg(tempw,&cpu_state.seg_ds); if (cpu_state.ssegs) oldds=ds; cycles-=24; break; diff --git a/src/codegen.c b/src/codegen.c index 2ab186f..96db8a6 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -103,7 +103,7 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin if (mod1seg[cpu_rm] == &ss && !op_ssegs) { - op_ea_seg = &_ss; + op_ea_seg = &cpu_state.seg_ss; } } @@ -153,7 +153,7 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin // addlong(stack_offset); } if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &_ss; + op_ea_seg = &cpu_state.seg_ss; if (((sib >> 3) & 7) != 4) { switch (sib >> 6) @@ -186,7 +186,7 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin if (cpu_mod) { if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &_ss; + op_ea_seg = &cpu_state.seg_ss; if (cpu_mod == 1) { uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8)); @@ -258,13 +258,12 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t int opcode_shift = 0; int opcode_mask = 0x3ff; uint32_t op_32 = use32; - x86seg *op_ea_seg = &_ds; - int op_ssegs = 0; int over = 0; int test_modrm = 1; int pc_off = 0; - op_ea_seg = &_ds; + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; codegen_timing_start(); @@ -279,27 +278,27 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0x26: /*ES:*/ - op_ea_seg = &_es; + op_ea_seg = &cpu_state.seg_es; op_ssegs = 1; break; case 0x2e: /*CS:*/ - op_ea_seg = &_cs; + op_ea_seg = &cpu_state.seg_cs; op_ssegs = 1; break; case 0x36: /*SS:*/ - op_ea_seg = &_ss; + op_ea_seg = &cpu_state.seg_ss; op_ssegs = 1; break; case 0x3e: /*DS:*/ - op_ea_seg = &_ds; + op_ea_seg = &cpu_state.seg_ds; op_ssegs = 1; break; case 0x64: /*FS:*/ - op_ea_seg = &_fs; + op_ea_seg = &cpu_state.seg_fs; op_ssegs = 1; break; case 0x65: /*GS:*/ - op_ea_seg = &_gs; + op_ea_seg = &cpu_state.seg_gs; op_ssegs = 1; break; diff --git a/src/codegen_backend.c b/src/codegen_backend.c index afc6716..58c092e 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -301,7 +301,7 @@ void codegen_block_start_recompile(codeblock_t *block) codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; block->TOP = cpu_state.TOP; block->was_recompiled = 1; diff --git a/src/ibm.h b/src/ibm.h index 6177fef..70641c9 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -176,6 +176,8 @@ struct MMX_REG MM[8]; uint16_t old_npxc, new_npxc; + + x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs; } cpu_state; #define cycles cpu_state._cycles @@ -209,7 +211,6 @@ extern int ins,output; extern int cycdiff; x86seg gdt,ldt,idt,tr; -x86seg _cs,_ds,_es,_ss,_fs,_gs; x86seg _oldds; uint32_t pccache; @@ -218,20 +219,20 @@ uint8_t *pccache2; _cs,_ds,_es,_ss are the segment structures CS,DS,ES,SS is the 16-bit data cs,ds,es,ss are defines to the bases*/ -#define CS _cs.seg -#define DS _ds.seg -#define ES _es.seg -#define SS _ss.seg -#define FS _fs.seg -#define GS _gs.seg -#define cs _cs.base -#define ds _ds.base -#define es _es.base -#define ss _ss.base -#define seg_fs _fs.base -#define gs _gs.base +#define CS cpu_state.seg_cs.seg +#define DS cpu_state.seg_ds.seg +#define ES cpu_state.seg_es.seg +#define SS cpu_state.seg_ss.seg +#define FS cpu_state.seg_fs.seg +#define GS cpu_state.seg_gs.seg +#define cs cpu_state.seg_cs.base +#define ds cpu_state.seg_ds.base +#define es cpu_state.seg_es.base +#define ss cpu_state.seg_ss.base +//#define seg_fs _fs.base +#define gs cpu_state.seg_gs.base -#define CPL ((_cs.access>>5)&3) +#define CPL ((cpu_state.seg_cs.access>>5)&3) void loadseg(uint16_t seg, x86seg *s); void loadcs(uint16_t seg); diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index 354059d..7c220a0 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -800,22 +800,22 @@ static int opLOADALL(uint32_t fetchdat) CX = readmemw(0, 0x832); AX = readmemw(0, 0x834); es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16); - _es.access = readmemb(0, 0x839); - _es.limit = readmemw(0, 0x83A); + cpu_state.seg_es.access = readmemb(0, 0x839); + cpu_state.seg_es.limit = readmemw(0, 0x83A); cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16); - _cs.access = readmemb(0, 0x83F); - _cs.limit = readmemw(0, 0x840); + cpu_state.seg_cs.access = readmemb(0, 0x83F); + cpu_state.seg_cs.limit = readmemw(0, 0x840); ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16); - _ss.access = readmemb(0, 0x845); - _ss.limit = readmemw(0, 0x846); - if (_ss.base == 0 && _ss.limit_low == 0 && _ss.limit_high == 0xffffffff) + cpu_state.seg_ss.access = readmemb(0, 0x845); + cpu_state.seg_ss.limit = readmemw(0, 0x846); + if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; else cpu_cur_status |= CPU_STATUS_NOTFLATSS; ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16); - _ds.access = readmemb(0, 0x84B); - _ds.limit = readmemw(0, 0x84C); - if (_ds.base == 0 && _ds.limit_low == 0 && _ds.limit_high == 0xffffffff) + cpu_state.seg_ds.access = readmemb(0, 0x84B); + cpu_state.seg_ds.limit = readmemw(0, 0x84C); + if (cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; else cpu_cur_status |= CPU_STATUS_NOTFLATDS; @@ -856,8 +856,11 @@ static void loadall_load_segment(uint32_t addr, x86seg *s) s->base = readmeml(0, addr + 4); s->limit = readmeml(0, addr + 8); - if (s == &_cs) use32 = (segdat3 & 0x40) ? 0x300 : 0; - if (s == &_ss) stack32 = (segdat3 & 0x40) ? 1 : 0; + if (s == &cpu_state.seg_cs) + use32 = (segdat3 & 0x40) ? 0x300 : 0; + if (s == &cpu_state.seg_ss) + stack32 = (segdat3 & 0x40) ? 1 : 0; + cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32); if (use32) cpu_cur_status |= CPU_STATUS_USE32; @@ -866,14 +869,14 @@ static void loadall_load_segment(uint32_t addr, x86seg *s) set_segment_limit(s, segdat3); - if (s == &_ds) + if (s == &cpu_state.seg_ds) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; else cpu_cur_status |= CPU_STATUS_NOTFLATDS; } - if (s == &_ss) + if (s == &cpu_state.seg_ss) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -914,12 +917,12 @@ static int opLOADALL386(uint32_t fetchdat) loadall_load_segment(la_addr + 0x60, &idt); loadall_load_segment(la_addr + 0x6c, &gdt); loadall_load_segment(la_addr + 0x78, &ldt); - loadall_load_segment(la_addr + 0x84, &_gs); - loadall_load_segment(la_addr + 0x90, &_fs); - loadall_load_segment(la_addr + 0x9c, &_ds); - loadall_load_segment(la_addr + 0xa8, &_ss); - loadall_load_segment(la_addr + 0xb4, &_cs); - loadall_load_segment(la_addr + 0xc0, &_es); + loadall_load_segment(la_addr + 0x84, &cpu_state.seg_gs); + loadall_load_segment(la_addr + 0x90, &cpu_state.seg_fs); + loadall_load_segment(la_addr + 0x9c, &cpu_state.seg_ds); + loadall_load_segment(la_addr + 0xa8, &cpu_state.seg_ss); + loadall_load_segment(la_addr + 0xb4, &cpu_state.seg_cs); + loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); diff --git a/src/x86_ops_mov_seg.h b/src/x86_ops_mov_seg.h index ecaeba1..54a30cb 100644 --- a/src/x86_ops_mov_seg.h +++ b/src/x86_ops_mov_seg.h @@ -152,28 +152,28 @@ static int opMOV_seg_w_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*ES*/ - loadseg(new_seg, &_es); + loadseg(new_seg, &cpu_state.seg_es); break; case 0x18: /*DS*/ - loadseg(new_seg, &_ds); + loadseg(new_seg, &cpu_state.seg_ds); break; case 0x10: /*SS*/ - loadseg(new_seg, &_ss); + loadseg(new_seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; cpu_state.ssegs = 0; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; fetchdat = fastreadl(cs + cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return 1; case 0x20: /*FS*/ - loadseg(new_seg, &_fs); + loadseg(new_seg, &cpu_state.seg_fs); break; case 0x28: /*GS*/ - loadseg(new_seg, &_gs); + loadseg(new_seg, &cpu_state.seg_gs); break; } @@ -193,28 +193,28 @@ static int opMOV_seg_w_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*ES*/ - loadseg(new_seg, &_es); + loadseg(new_seg, &cpu_state.seg_es); break; case 0x18: /*DS*/ - loadseg(new_seg, &_ds); + loadseg(new_seg, &cpu_state.seg_ds); break; case 0x10: /*SS*/ - loadseg(new_seg, &_ss); + loadseg(new_seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; cpu_state.ssegs = 0; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; fetchdat = fastreadl(cs + cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return 1; case 0x20: /*FS*/ - loadseg(new_seg, &_fs); + loadseg(new_seg, &cpu_state.seg_fs); break; case 0x28: /*GS*/ - loadseg(new_seg, &_gs); + loadseg(new_seg, &cpu_state.seg_gs); break; } @@ -233,7 +233,7 @@ static int opLDS_w_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &_ds); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -249,7 +249,7 @@ static int opLDS_w_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &_ds); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -266,7 +266,7 @@ static int opLDS_l_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &_ds); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -283,7 +283,7 @@ static int opLDS_l_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &_ds); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -300,7 +300,7 @@ static int opLSS_w_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &_ss); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -316,7 +316,7 @@ static int opLSS_w_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmemw(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &_ss); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -333,7 +333,7 @@ static int opLSS_l_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &_ss); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -350,7 +350,7 @@ static int opLSS_l_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); addr = readmeml(easeg, cpu_state.eaaddr); seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &_ss); if (cpu_state.abrt) return 1; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -429,6 +429,6 @@ static int opLSS_l_a32(uint32_t fetchdat) return 0; \ } -opLsel(ES, _es) -opLsel(FS, _fs) -opLsel(GS, _gs) +opLsel(ES, cpu_state.seg_es) +opLsel(FS, cpu_state.seg_fs) +opLsel(GS, cpu_state.seg_gs) diff --git a/src/x86_ops_prefix.h b/src/x86_ops_prefix.h index 48147c7..8cfe95e 100644 --- a/src/x86_ops_prefix.h +++ b/src/x86_ops_prefix.h @@ -63,26 +63,26 @@ static int op ## name ## _l_a32(uint32_t fetchdat) \ return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ } -op_seg(CS, _cs, x86_opcodes, x86_opcodes) -op_seg(DS, _ds, x86_opcodes, x86_opcodes) -op_seg(ES, _es, x86_opcodes, x86_opcodes) -op_seg(FS, _fs, x86_opcodes, x86_opcodes) -op_seg(GS, _gs, x86_opcodes, x86_opcodes) -op_seg(SS, _ss, x86_opcodes, x86_opcodes) +op_seg(CS, cpu_state.seg_cs, x86_opcodes, x86_opcodes) +op_seg(DS, cpu_state.seg_ds, x86_opcodes, x86_opcodes) +op_seg(ES, cpu_state.seg_es, x86_opcodes, x86_opcodes) +op_seg(FS, cpu_state.seg_fs, x86_opcodes, x86_opcodes) +op_seg(GS, cpu_state.seg_gs, x86_opcodes, x86_opcodes) +op_seg(SS, cpu_state.seg_ss, x86_opcodes, x86_opcodes) -op_seg(CS_REPE, _cs, x86_opcodes_REPE, x86_opcodes) -op_seg(DS_REPE, _ds, x86_opcodes_REPE, x86_opcodes) -op_seg(ES_REPE, _es, x86_opcodes_REPE, x86_opcodes) -op_seg(FS_REPE, _fs, x86_opcodes_REPE, x86_opcodes) -op_seg(GS_REPE, _gs, x86_opcodes_REPE, x86_opcodes) -op_seg(SS_REPE, _ss, x86_opcodes_REPE, x86_opcodes) +op_seg(CS_REPE, cpu_state.seg_cs, x86_opcodes_REPE, x86_opcodes) +op_seg(DS_REPE, cpu_state.seg_ds, x86_opcodes_REPE, x86_opcodes) +op_seg(ES_REPE, cpu_state.seg_es, x86_opcodes_REPE, x86_opcodes) +op_seg(FS_REPE, cpu_state.seg_fs, x86_opcodes_REPE, x86_opcodes) +op_seg(GS_REPE, cpu_state.seg_gs, x86_opcodes_REPE, x86_opcodes) +op_seg(SS_REPE, cpu_state.seg_ss, x86_opcodes_REPE, x86_opcodes) -op_seg(CS_REPNE, _cs, x86_opcodes_REPNE, x86_opcodes) -op_seg(DS_REPNE, _ds, x86_opcodes_REPNE, x86_opcodes) -op_seg(ES_REPNE, _es, x86_opcodes_REPNE, x86_opcodes) -op_seg(FS_REPNE, _fs, x86_opcodes_REPNE, x86_opcodes) -op_seg(GS_REPNE, _gs, x86_opcodes_REPNE, x86_opcodes) -op_seg(SS_REPNE, _ss, x86_opcodes_REPNE, x86_opcodes) +op_seg(CS_REPNE, cpu_state.seg_cs, x86_opcodes_REPNE, x86_opcodes) +op_seg(DS_REPNE, cpu_state.seg_ds, x86_opcodes_REPNE, x86_opcodes) +op_seg(ES_REPNE, cpu_state.seg_es, x86_opcodes_REPNE, x86_opcodes) +op_seg(FS_REPNE, cpu_state.seg_fs, x86_opcodes_REPNE, x86_opcodes) +op_seg(GS_REPNE, cpu_state.seg_gs, x86_opcodes_REPNE, x86_opcodes) +op_seg(SS_REPNE, cpu_state.seg_ss, x86_opcodes_REPNE, x86_opcodes) static int op_66(uint32_t fetchdat) /*Data size select*/ { diff --git a/src/x86_ops_rep.h b/src/x86_ops_rep.h index 5b24beb..bd95991 100644 --- a/src/x86_ops_rep.h +++ b/src/x86_ops_rep.h @@ -9,7 +9,7 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) { \ uint8_t temp; \ \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ check_io_perm(DX); \ temp = inb(DX); \ writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ @@ -37,7 +37,7 @@ static int opREP_INSW_ ## size(uint32_t fetchdat) { \ uint16_t temp; \ \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ check_io_perm(DX); \ check_io_perm(DX+1); \ temp = inw(DX); \ @@ -66,7 +66,7 @@ static int opREP_INSL_ ## size(uint32_t fetchdat) { \ uint32_t temp; \ \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ check_io_perm(DX); \ check_io_perm(DX+1); \ check_io_perm(DX+2); \ @@ -182,13 +182,13 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) if (CNT_REG > 0) \ { \ SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ } \ while (CNT_REG > 0) \ { \ uint8_t temp; \ \ - CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ @@ -220,13 +220,13 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) if (CNT_REG > 0) \ { \ SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ } \ while (CNT_REG > 0) \ { \ uint16_t temp; \ \ - CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ @@ -258,13 +258,13 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) if (CNT_REG > 0) \ { \ SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ } \ while (CNT_REG > 0) \ { \ uint32_t temp; \ \ - CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ @@ -296,10 +296,10 @@ static int opREP_STOSB_ ## size(uint32_t fetchdat) if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ while (CNT_REG > 0) \ { \ - CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \ if (flags & D_FLAG) DEST_REG--; \ else DEST_REG++; \ @@ -326,10 +326,10 @@ static int opREP_STOSW_ ## size(uint32_t fetchdat) if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ while (CNT_REG > 0) \ { \ - CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+1); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG+1); \ writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \ if (flags & D_FLAG) DEST_REG -= 2; \ else DEST_REG += 2; \ @@ -356,10 +356,10 @@ static int opREP_STOSL_ ## size(uint32_t fetchdat) if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&_es); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ while (CNT_REG > 0) \ { \ - CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+3); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG+3); \ writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \ if (flags & D_FLAG) DEST_REG -= 4; \ else DEST_REG += 4; \ @@ -479,7 +479,7 @@ static int opREP_CMPSB_ ## size(uint32_t fetchdat) { \ uint8_t temp, temp2; \ SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&_es); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ @@ -509,7 +509,7 @@ static int opREP_CMPSW_ ## size(uint32_t fetchdat) { \ uint16_t temp, temp2; \ SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&_es); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ @@ -539,7 +539,7 @@ static int opREP_CMPSL_ ## size(uint32_t fetchdat) { \ uint32_t temp, temp2; \ SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&_es); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ @@ -569,7 +569,7 @@ static int opREP_SCASB_ ## size(uint32_t fetchdat) cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&_es); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\ @@ -602,7 +602,7 @@ static int opREP_SCASW_ ## size(uint32_t fetchdat) cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&_es); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\ @@ -635,7 +635,7 @@ static int opREP_SCASL_ ## size(uint32_t fetchdat) cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&_es); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\ diff --git a/src/x86_ops_stack.h b/src/x86_ops_stack.h index dbe333f..b7e827b 100644 --- a/src/x86_ops_stack.h +++ b/src/x86_ops_stack.h @@ -470,10 +470,10 @@ PUSH_SEG_OPS(FS); PUSH_SEG_OPS(GS); PUSH_SEG_OPS(SS); -POP_SEG_OPS(DS, &_ds); -POP_SEG_OPS(ES, &_es); -POP_SEG_OPS(FS, &_fs); -POP_SEG_OPS(GS, &_gs); +POP_SEG_OPS(DS, &cpu_state.seg_ds); +POP_SEG_OPS(ES, &cpu_state.seg_es); +POP_SEG_OPS(FS, &cpu_state.seg_fs); +POP_SEG_OPS(GS, &cpu_state.seg_gs); static int opPOP_SS_w(uint32_t fetchdat) @@ -481,14 +481,14 @@ static int opPOP_SS_w(uint32_t fetchdat) uint16_t temp_seg; uint32_t temp_esp = ESP; temp_seg = POP_W(); if (cpu_state.abrt) return 1; - loadseg(temp_seg, &_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } + loadseg(temp_seg, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } CLOCK_CYCLES(is486 ? 3 : 7); PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; cpu_state.ssegs = 0; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; fetchdat = fastreadl(cs + cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; @@ -501,14 +501,14 @@ static int opPOP_SS_l(uint32_t fetchdat) uint32_t temp_seg; uint32_t temp_esp = ESP; temp_seg = POP_L(); if (cpu_state.abrt) return 1; - loadseg(temp_seg & 0xffff, &_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } + loadseg(temp_seg & 0xffff, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } CLOCK_CYCLES(is486 ? 3 : 7); PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; cpu_state.ssegs = 0; - cpu_state.ea_seg = &_ds; + cpu_state.ea_seg = &cpu_state.seg_ds; fetchdat = fastreadl(cs + cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; diff --git a/src/x86_ops_string.h b/src/x86_ops_string.h index d76b3f8..3bdeace 100644 --- a/src/x86_ops_string.h +++ b/src/x86_ops_string.h @@ -3,7 +3,7 @@ static int opMOVSB_a16(uint32_t fetchdat) uint8_t temp; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememb(es, DI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { DI--; SI--; } @@ -17,7 +17,7 @@ static int opMOVSB_a32(uint32_t fetchdat) uint8_t temp; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememb(es, EDI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { EDI--; ESI--; } @@ -32,7 +32,7 @@ static int opMOVSW_a16(uint32_t fetchdat) uint16_t temp; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememw(es, DI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { DI -= 2; SI -= 2; } @@ -46,7 +46,7 @@ static int opMOVSW_a32(uint32_t fetchdat) uint16_t temp; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememw(es, EDI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } @@ -61,7 +61,7 @@ static int opMOVSL_a16(uint32_t fetchdat) uint32_t temp; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememl(es, DI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { DI -= 4; SI -= 4; } @@ -75,7 +75,7 @@ static int opMOVSL_a32(uint32_t fetchdat) uint32_t temp; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememl(es, EDI, temp); if (cpu_state.abrt) return 1; if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } @@ -91,7 +91,7 @@ static int opCMPSB_a16(uint32_t fetchdat) uint8_t src, dst; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); src = readmemb(cpu_state.ea_seg->base, SI); dst = readmemb(es, DI); if (cpu_state.abrt) return 1; setsub8(src, dst); @@ -106,7 +106,7 @@ static int opCMPSB_a32(uint32_t fetchdat) uint8_t src, dst; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); src = readmemb(cpu_state.ea_seg->base, ESI); dst = readmemb(es, EDI); if (cpu_state.abrt) return 1; setsub8(src, dst); @@ -122,7 +122,7 @@ static int opCMPSW_a16(uint32_t fetchdat) uint16_t src, dst; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); src = readmemw(cpu_state.ea_seg->base, SI); dst = readmemw(es, DI); if (cpu_state.abrt) return 1; setsub16(src, dst); @@ -137,7 +137,7 @@ static int opCMPSW_a32(uint32_t fetchdat) uint16_t src, dst; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); src = readmemw(cpu_state.ea_seg->base, ESI); dst = readmemw(es, EDI); if (cpu_state.abrt) return 1; setsub16(src, dst); @@ -153,7 +153,7 @@ static int opCMPSL_a16(uint32_t fetchdat) uint32_t src, dst; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); src = readmeml(cpu_state.ea_seg->base, SI); dst = readmeml(es, DI); if (cpu_state.abrt) return 1; setsub32(src, dst); @@ -168,7 +168,7 @@ static int opCMPSL_a32(uint32_t fetchdat) uint32_t src, dst; SEG_CHECK_READ(cpu_state.ea_seg); - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); src = readmeml(cpu_state.ea_seg->base, ESI); dst = readmeml(es, EDI); if (cpu_state.abrt) return 1; setsub32(src, dst); @@ -181,7 +181,7 @@ static int opCMPSL_a32(uint32_t fetchdat) static int opSTOSB_a16(uint32_t fetchdat) { - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); writememb(es, DI, AL); if (cpu_state.abrt) return 1; if (flags & D_FLAG) DI--; else DI++; @@ -191,7 +191,7 @@ static int opSTOSB_a16(uint32_t fetchdat) } static int opSTOSB_a32(uint32_t fetchdat) { - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); writememb(es, EDI, AL); if (cpu_state.abrt) return 1; if (flags & D_FLAG) EDI--; else EDI++; @@ -202,7 +202,7 @@ static int opSTOSB_a32(uint32_t fetchdat) static int opSTOSW_a16(uint32_t fetchdat) { - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); writememw(es, DI, AX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) DI -= 2; else DI += 2; @@ -212,7 +212,7 @@ static int opSTOSW_a16(uint32_t fetchdat) } static int opSTOSW_a32(uint32_t fetchdat) { - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); writememw(es, EDI, AX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) EDI -= 2; else EDI += 2; @@ -223,7 +223,7 @@ static int opSTOSW_a32(uint32_t fetchdat) static int opSTOSL_a16(uint32_t fetchdat) { - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); writememl(es, DI, EAX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) DI -= 4; else DI += 4; @@ -233,7 +233,7 @@ static int opSTOSL_a16(uint32_t fetchdat) } static int opSTOSL_a32(uint32_t fetchdat) { - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); writememl(es, EDI, EAX); if (cpu_state.abrt) return 1; if (flags & D_FLAG) EDI -= 4; else EDI += 4; @@ -329,7 +329,7 @@ static int opSCASB_a16(uint32_t fetchdat) { uint8_t temp; - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemb(es, DI); if (cpu_state.abrt) return 1; setsub8(AL, temp); if (flags & D_FLAG) DI--; @@ -342,7 +342,7 @@ static int opSCASB_a32(uint32_t fetchdat) { uint8_t temp; - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemb(es, EDI); if (cpu_state.abrt) return 1; setsub8(AL, temp); if (flags & D_FLAG) EDI--; @@ -356,7 +356,7 @@ static int opSCASW_a16(uint32_t fetchdat) { uint16_t temp; - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemw(es, DI); if (cpu_state.abrt) return 1; setsub16(AX, temp); if (flags & D_FLAG) DI -= 2; @@ -369,7 +369,7 @@ static int opSCASW_a32(uint32_t fetchdat) { uint16_t temp; - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemw(es, EDI); if (cpu_state.abrt) return 1; setsub16(AX, temp); if (flags & D_FLAG) EDI -= 2; @@ -383,7 +383,7 @@ static int opSCASL_a16(uint32_t fetchdat) { uint32_t temp; - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); temp = readmeml(es, DI); if (cpu_state.abrt) return 1; setsub32(EAX, temp); if (flags & D_FLAG) DI -= 4; @@ -396,7 +396,7 @@ static int opSCASL_a32(uint32_t fetchdat) { uint32_t temp; - SEG_CHECK_READ(&_es); + SEG_CHECK_READ(&cpu_state.seg_es); temp = readmeml(es, EDI); if (cpu_state.abrt) return 1; setsub32(EAX, temp); if (flags & D_FLAG) EDI -= 4; @@ -410,7 +410,7 @@ static int opINSB_a16(uint32_t fetchdat) { uint8_t temp; - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); temp = inb(DX); writememb(es, DI, temp); if (cpu_state.abrt) return 1; @@ -424,7 +424,7 @@ static int opINSB_a32(uint32_t fetchdat) { uint8_t temp; - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); temp = inb(DX); writememb(es, EDI, temp); if (cpu_state.abrt) return 1; @@ -439,7 +439,7 @@ static int opINSW_a16(uint32_t fetchdat) { uint16_t temp; - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); temp = inw(DX); @@ -454,7 +454,7 @@ static int opINSW_a32(uint32_t fetchdat) { uint16_t temp; - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); temp = inw(DX); @@ -470,7 +470,7 @@ static int opINSL_a16(uint32_t fetchdat) { uint32_t temp; - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); @@ -487,7 +487,7 @@ static int opINSL_a32(uint32_t fetchdat) { uint32_t temp; - SEG_CHECK_WRITE(&_es); + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); diff --git a/src/x86seg.c b/src/x86seg.c index 9840c0b..68b0d49 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -68,7 +68,7 @@ static void seg_reset(x86seg *s) s->limit = 0xFFFF; s->limit_low = 0; s->limit_high = 0xffff; - if (s == &_cs) + if (s == &cpu_state.seg_cs) { // TODO - When the PC is reset, initialization of the CS descriptor must be like the annotated line below. //s->base = AT ? (cpu_16bitbus ? 0xFF0000 : 0xFFFF0000) : 0xFFFF0; @@ -84,12 +84,12 @@ static void seg_reset(x86seg *s) void x86seg_reset() { - seg_reset(&_cs); - seg_reset(&_ds); - seg_reset(&_es); - seg_reset(&_fs); - seg_reset(&_gs); - seg_reset(&_ss); + seg_reset(&cpu_state.seg_cs); + seg_reset(&cpu_state.seg_ds); + seg_reset(&cpu_state.seg_es); + seg_reset(&cpu_state.seg_fs); + seg_reset(&cpu_state.seg_gs); + seg_reset(&cpu_state.seg_ss); } void x86_doabrt(int x86_abrt) @@ -97,7 +97,7 @@ void x86_doabrt(int x86_abrt) // ingpf = 1; CS = oldcs; cpu_state.pc = cpu_state.oldpc; - _cs.access = oldcpl << 5; + cpu_state.seg_cs.access = oldcpl << 5; // pclog("x86_doabrt - %02X %08X %04X:%08X %i\n", x86_abrt, abrt_error, CS, pc, ins); /* if (CS == 0x3433 && pc == 0x000006B0) @@ -238,14 +238,14 @@ static void do_seg_load(x86seg *s, uint16_t *segdat) } // if (output) pclog("SEG : base=%08x limit=%08x low=%08x high=%08x\n", s->base, s->limit, s->limit_low, s->limit_high); - if (s == &_ds) + if (s == &cpu_state.seg_ds) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; else cpu_cur_status |= CPU_STATUS_NOTFLATDS; } - if (s == &_ss) + if (s == &cpu_state.seg_ss) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -320,7 +320,7 @@ void loadseg(uint16_t seg, x86seg *s) // intcount++; if (!(seg&~3)) { - if (s==&_ss) + if (s==&cpu_state.seg_ss) { pclog("SS selector = NULL!\n"); x86ss(NULL,0); @@ -332,7 +332,7 @@ void loadseg(uint16_t seg, x86seg *s) s->seg=0; s->access = 0; s->base=-1; - if (s == &_ds) + if (s == &cpu_state.seg_ds) cpu_cur_status |= CPU_STATUS_NOTFLATDS; // pclog("NULL selector %s%s%s%s %04X(%06X):%06X\n",(s==&_ds)?"DS":"",(s==&_es)?"ES":"",(s==&_fs)?"FS":"",(s==&_gs)?"GS":"",CS,cs,pc); return; @@ -371,7 +371,7 @@ void loadseg(uint16_t seg, x86seg *s) segdat[2]=readmemw(0,addr+4); segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; dpl=(segdat[2]>>13)&3; - if (s==&_ss) + if (s==&cpu_state.seg_ss) { if (!(seg&~3)) { @@ -405,7 +405,7 @@ void loadseg(uint16_t seg, x86seg *s) set_stack32((segdat[3] & 0x40) ? 1 : 0); // pclog("Load SS %04x %04x %04x %04x\n", segdat[0], segdat[1], segdat[2], segdat[3]); } - else if (s!=&_cs) + else if (s!=&cpu_state.seg_cs) { if (output) pclog("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); if (output) pclog("Seg type %03X\n",segdat[2]&0x1F00); @@ -453,9 +453,9 @@ void loadseg(uint16_t seg, x86seg *s) } #endif s->checked = 0; - if (s == &_ds) + if (s == &cpu_state.seg_ds) codegen_flat_ds = 0; - if (s == &_ss) + if (s == &cpu_state.seg_ss) codegen_flat_ss = 0; } else @@ -463,23 +463,23 @@ void loadseg(uint16_t seg, x86seg *s) s->access = (3 << 5) | 2; s->base = seg << 4; s->seg = seg; - if (s == &_ss) + if (s == &cpu_state.seg_ss) set_stack32(0); s->checked = 1; - if (s == &_ds) + if (s == &cpu_state.seg_ds) codegen_flat_ds = 0; - if (s == &_ss) + if (s == &cpu_state.seg_ss) codegen_flat_ss = 0; } - if (s == &_ds) + if (s == &cpu_state.seg_ds) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; else cpu_cur_status |= CPU_STATUS_NOTFLATDS; } - if (s == &_ss) + if (s == &cpu_state.seg_ss) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -568,7 +568,7 @@ void loadcs(uint16_t seg) } set_use32(segdat[3] & 0x40); CS=(seg&~3)|CPL; - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); use32=(segdat[3]&0x40)?0x300:0; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); @@ -601,13 +601,13 @@ void loadcs(uint16_t seg) } else { - _cs.base=seg<<4; - _cs.limit=0xFFFF; - _cs.limit_low = 0; - _cs.limit_high = 0xffff; + cpu_state.seg_cs.base=seg<<4; + cpu_state.seg_cs.limit=0xFFFF; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - if (eflags&VM_FLAG) _cs.access=(3<<5) | 2; - else _cs.access=(0<<5) | 2; + if (eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; + else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); } } @@ -693,7 +693,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) CS = (seg & ~3) | CPL; segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8)); - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); /* if (segdat[3]&0x40) { @@ -797,7 +797,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) } case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ CS=seg2; - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -846,13 +846,13 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) } else { - _cs.base=seg<<4; - _cs.limit=0xFFFF; - _cs.limit_low = 0; - _cs.limit_high = 0xffff; + cpu_state.seg_cs.base=seg<<4; + cpu_state.seg_cs.limit=0xFFFF; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - if (eflags&VM_FLAG) _cs.access=(3<<5) | 2; - else _cs.access=(0<<5) | 2; + if (eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; + else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); cycles -= timing_jmp_rm; } @@ -1028,7 +1028,7 @@ void loadcscall(uint16_t seg) else /*On non-conforming segments, set RPL = CPL*/ seg = (seg & ~3) | CPL; CS=seg; - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); /* if (segdat[3]&0x40) { @@ -1205,7 +1205,7 @@ void loadcscall(uint16_t seg) if (stack32) ESP=newsp; else SP=newsp; - do_seg_load(&_ss, segdat2); + do_seg_load(&cpu_state.seg_ss, segdat2); if (output) pclog("Set access 1\n"); @@ -1216,7 +1216,7 @@ void loadcscall(uint16_t seg) #endif CS=seg2; - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -1320,7 +1320,7 @@ void loadcscall(uint16_t seg) PUSHW(oldpc); if (cpu_state.abrt) return; }*/ CS=seg2; - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -1363,13 +1363,13 @@ void loadcscall(uint16_t seg) } else { - _cs.base=seg<<4; - _cs.limit=0xFFFF; - _cs.limit_low = 0; - _cs.limit_high = 0xffff; + cpu_state.seg_cs.base=seg<<4; + cpu_state.seg_cs.limit=0xFFFF; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - if (eflags&VM_FLAG) _cs.access=(3<<5) | 2; - else _cs.access=(0<<5) | 2; + if (eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; + else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); } } @@ -1495,8 +1495,8 @@ void pmoderetf(int is32, uint16_t off) if (segdat[2] & 0x400) segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8)); CS = seg; - do_seg_load(&_cs, segdat); - _cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5); + do_seg_load(&cpu_state.seg_cs, segdat); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3] & 0x40); @@ -1630,7 +1630,7 @@ void pmoderetf(int is32, uint16_t off) set_stack32((segdat2[3] & 0x40) ? 1 : 0); if (stack32) ESP=newsp; else SP=newsp; - do_seg_load(&_ss, segdat2); + do_seg_load(&cpu_state.seg_ss, segdat2); #ifdef SEL_ACCESSED cpl_override = 1; @@ -1647,17 +1647,17 @@ void pmoderetf(int is32, uint16_t off) cpu_state.pc=newpc; CS=seg; - do_seg_load(&_cs, segdat); + do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3] & 0x40); if (stack32) ESP+=off; else SP+=off; - check_seg_valid(&_ds); - check_seg_valid(&_es); - check_seg_valid(&_fs); - check_seg_valid(&_gs); + check_seg_valid(&cpu_state.seg_ds); + check_seg_valid(&cpu_state.seg_es); + check_seg_valid(&cpu_state.seg_fs); + check_seg_valid(&cpu_state.seg_gs); // pclog("CPL0x800) cpu_state.pc=segdat[0]|(segdat[3]<<16); @@ -2086,10 +2086,10 @@ void pmodeiret(int is32) tempflags=POPW(); if (cpu_state.abrt) return; } cpu_state.pc=newpc; - _cs.base=seg<<4; - _cs.limit=0xFFFF; - _cs.limit_low = 0; - _cs.limit_high = 0xffff; + cpu_state.seg_cs.base=seg<<4; + cpu_state.seg_cs.limit=0xFFFF; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; CS=seg; flags=(flags&0x3000)|(tempflags&0xCFD5)|2; cycles -= timing_iret_rm; @@ -2155,31 +2155,31 @@ void pmodeiret(int is32) // pclog("Pop stack %04X:%04X\n",newss,newsp); eflags=tempflags>>16; cpu_cur_status |= CPU_STATUS_V86; - loadseg(segs[0],&_es); - do_seg_v86_init(&_es); - loadseg(segs[1],&_ds); - do_seg_v86_init(&_ds); + loadseg(segs[0],&cpu_state.seg_es); + do_seg_v86_init(&cpu_state.seg_es); + loadseg(segs[1],&cpu_state.seg_ds); + do_seg_v86_init(&cpu_state.seg_ds); cpu_cur_status |= CPU_STATUS_NOTFLATDS; - loadseg(segs[2],&_fs); - do_seg_v86_init(&_fs); - loadseg(segs[3],&_gs); - do_seg_v86_init(&_gs); + loadseg(segs[2],&cpu_state.seg_fs); + do_seg_v86_init(&cpu_state.seg_fs); + loadseg(segs[3],&cpu_state.seg_gs); + do_seg_v86_init(&cpu_state.seg_gs); // pclog("V86 IRET %04X:%08X\n",SS,ESP); // output=3; cpu_state.pc=newpc; - _cs.base=seg<<4; - _cs.limit=0xFFFF; - _cs.limit_low = 0; - _cs.limit_high = 0xffff; + cpu_state.seg_cs.base=seg<<4; + cpu_state.seg_cs.limit=0xFFFF; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - _cs.access=(3<<5) | 2; + cpu_state.seg_cs.access=(3<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); ESP=newsp; - loadseg(newss,&_ss); - do_seg_v86_init(&_ss); + loadseg(newss,&cpu_state.seg_ss); + do_seg_v86_init(&cpu_state.seg_ss); cpu_cur_status |= CPU_STATUS_NOTFLATSS; use32=0; cpu_cur_status &= ~CPU_STATUS_USE32; @@ -2292,8 +2292,8 @@ void pmodeiret(int is32) { // pclog("Same level\n"); CS=seg; - do_seg_load(&_cs, segdat); - _cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5); + do_seg_load(&cpu_state.seg_cs, segdat); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3]&0x40); @@ -2392,7 +2392,7 @@ void pmodeiret(int is32) set_stack32((segdat2[3] & 0x40) ? 1 : 0); if (stack32) ESP=newsp; else SP=newsp; - do_seg_load(&_ss, segdat2); + do_seg_load(&cpu_state.seg_ss, segdat2); #ifdef SEL_ACCESSED cpl_override = 1; @@ -2408,15 +2408,15 @@ void pmodeiret(int is32) segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8)); CS=seg; - do_seg_load(&_cs, segdat); - _cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5); + do_seg_load(&cpu_state.seg_cs, segdat); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat[3] & 0x40); - check_seg_valid(&_ds); - check_seg_valid(&_es); - check_seg_valid(&_fs); - check_seg_valid(&_gs); + check_seg_valid(&cpu_state.seg_ds); + check_seg_valid(&cpu_state.seg_es); + check_seg_valid(&cpu_state.seg_fs); + check_seg_valid(&cpu_state.seg_gs); cycles -= timing_iret_pm_outer; } cpu_state.pc=newpc; @@ -2643,7 +2643,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) // if (output) pclog("new_cs %04X\n",new_cs); CS=new_cs; - do_seg_load(&_cs, segdat2); + do_seg_load(&cpu_state.seg_cs, segdat2); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(segdat2[3] & 0x40); cpu_cur_status &= ~CPU_STATUS_V86; @@ -2659,15 +2659,15 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) EDI=new_edi; if (output) pclog("Load ES %04X\n",new_es); - loadseg(new_es,&_es); + loadseg(new_es,&cpu_state.seg_es); if (output) pclog("Load SS %04X\n",new_ss); - loadseg(new_ss,&_ss); + loadseg(new_ss,&cpu_state.seg_ss); if (output) pclog("Load DS %04X\n",new_ds); - loadseg(new_ds,&_ds); + loadseg(new_ds,&cpu_state.seg_ds); if (output) pclog("Load FS %04X\n",new_fs); - loadseg(new_fs,&_fs); + loadseg(new_fs,&cpu_state.seg_fs); if (output) pclog("Load GS %04X\n",new_gs); - loadseg(new_gs,&_gs); + loadseg(new_gs,&cpu_state.seg_gs); if (output) pclog("Resuming at %04X:%08X\n",CS,cpu_state.pc); } @@ -2842,7 +2842,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) // if (output) pclog("new_cs %04X\n",new_cs); CS=new_cs; - do_seg_load(&_cs, segdat2); + do_seg_load(&cpu_state.seg_cs, segdat2); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); set_use32(0); @@ -2856,15 +2856,15 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) EDI=new_edi | 0xFFFF0000; if (output) pclog("Load ES %04X\n",new_es); - loadseg(new_es,&_es); + loadseg(new_es,&cpu_state.seg_es); if (output) pclog("Load SS %04X\n",new_ss); - loadseg(new_ss,&_ss); + loadseg(new_ss,&cpu_state.seg_ss); if (output) pclog("Load DS %04X\n",new_ds); - loadseg(new_ds,&_ds); + loadseg(new_ds,&cpu_state.seg_ds); if (is386) { - loadseg(0,&_fs); - loadseg(0,&_gs); + loadseg(0,&cpu_state.seg_fs); + loadseg(0,&cpu_state.seg_gs); } if (output) pclog("Resuming at %04X:%08X\n",CS,cpu_state.pc); From f27b7f757a841d4878a6d5ff4cf90fb869dddc44 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 25 Jul 2018 20:16:58 +0100 Subject: [PATCH 016/181] Add recompiled versions of mem->reg, reg->mem and imm->mem versions of MOV. --- src/Makefile.am | 8 +- src/codegen.c | 47 ++ src/codegen.h | 4 + src/codegen_backend_arm.c | 144 +++++ src/codegen_backend_arm64.c | 153 +++++ src/codegen_backend_arm64_defs.h | 10 +- src/codegen_backend_arm64_ops.c | 613 +++++++++++++++++++++ src/codegen_backend_arm64_ops.h | 92 ++++ src/codegen_backend_arm64_uops.c | 675 ++++++++--------------- src/codegen_backend_arm_defs.h | 10 +- src/codegen_backend_arm_ops.c | 587 ++++++++++++++++++++ src/codegen_backend_arm_ops.h | 84 +++ src/codegen_backend_arm_uops.c | 588 +++++++------------- src/codegen_backend_x86-64.c | 192 +++++++ src/codegen_backend_x86-64_defs.h | 17 + src/codegen_backend_x86-64_ops.c | 888 ++++++++++++++++++++++++++++++ src/codegen_backend_x86-64_ops.h | 104 ++++ src/codegen_backend_x86-64_uops.c | 877 +++++++---------------------- src/codegen_backend_x86.c | 172 ++++++ src/codegen_backend_x86_defs.h | 8 + src/codegen_backend_x86_ops.c | 779 ++++++++++++++++++++++++++ src/codegen_backend_x86_ops.h | 100 ++++ src/codegen_backend_x86_uops.c | 810 +++++++-------------------- src/codegen_ir.c | 18 +- src/codegen_ir_defs.h | 74 ++- src/codegen_ops.c | 8 +- src/codegen_ops_mov.c | 229 +++++++- src/codegen_ops_mov.h | 13 + src/codegen_reg.c | 43 +- src/codegen_reg.h | 38 +- 30 files changed, 5225 insertions(+), 2160 deletions(-) create mode 100644 src/codegen_backend_arm64_ops.c create mode 100644 src/codegen_backend_arm64_ops.h create mode 100644 src/codegen_backend_arm_ops.c create mode 100644 src/codegen_backend_arm_ops.h create mode 100644 src/codegen_backend_x86-64_ops.c create mode 100644 src/codegen_backend_x86-64_ops.h create mode 100644 src/codegen_backend_x86_ops.c create mode 100644 src/codegen_backend_x86_ops.h diff --git a/src/Makefile.am b/src/Makefile.am index ab44ff7..18da9e0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,20 +70,20 @@ pcem_SOURCES += wx-sdl2-midi.c endif if CPU_I386 -pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_uops.c +pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_ops.c codegen_backend_x86_uops.c pcem_CFLAGS += -msse2 endif if CPU_X86_64 -pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_uops.c +pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_ops.c codegen_backend_x86-64_uops.c endif if CPU_ARM -pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_uops.c +pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_ops.c codegen_backend_arm_uops.c endif if CPU_ARM64 -pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_uops.c +pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c endif if USE_NETWORKING diff --git a/src/codegen.c b/src/codegen.c index 96db8a6..5bd88bb 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -45,6 +45,41 @@ void codegen_generate_reset() has_ea = 0; } +void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg) +{ + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; + + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, &block->data[BLOCK_GPF_OFFSET]); + + seg->checked = 1; +} +void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) +{ + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; + + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, &block->data[BLOCK_GPF_OFFSET]); + + seg->checked = 1; +} + static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { // pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat); @@ -203,6 +238,18 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin return op_ea_seg; } +x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +{ + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; + + if (op_32 & 0x200) + return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, 0); + + return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc); +} + static uint8_t opcode_modrm[256] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ diff --git a/src/codegen.h b/src/codegen.h index 8106c1c..9503b25 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -263,6 +263,10 @@ void codegen_generate_seg_restore(); void codegen_set_op32(); void codegen_flush(); void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); +struct ir_data_t; +x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32); +void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); extern int cpu_block_end; extern uint32_t codegen_endpc; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 41aeb71..09630ed 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -5,6 +5,7 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" +#include "codegen_backend_arm_ops.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -15,6 +16,14 @@ #include #endif +void *codegen_mem_load_byte; +void *codegen_mem_load_word; +void *codegen_mem_load_long; + +void *codegen_mem_store_byte; +void *codegen_mem_store_word; +void *codegen_mem_store_long; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_R4, @@ -22,6 +31,137 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_R6, }; +static void build_load_routine(codeblock_t *block, int size) +{ + uint32_t *branch_offset; + uint8_t *misaligned_offset; + + /*In - R0 = address + Out - R0 = data, R1 = abrt*/ + /*MOV R1, R0, LSR #12 + MOV R2, #readlookup2 + LDR R1, [R2, R1, LSL #2] + CMP R1, #-1 + BNE + + LDRB R0, [R1, R0] + MOV R1, #0 + MOV PC, LR + * STR LR, [SP, -4]! + BL readmemb386l + LDRB R1, cpu_state.abrt + LDR PC, [SP], #4 + */ + host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12); + host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2); + host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2); + if (size != 1) + { + host_arm_TST_IMM(block, REG_R0, size-1); + misaligned_offset = host_arm_BNE_(block); + } + host_arm_CMP_IMM(block, REG_R1, -1); + branch_offset = host_arm_BEQ_(block); + if (size == 1) + host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 2) + host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 4) + host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0); + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; + host_arm_STR_IMM_WB(block, REG_LR, REG_SP, -4); + if (size == 1) + host_arm_BL(block, (uintptr_t)readmemb386l); + else if (size == 2) + host_arm_BL(block, (uintptr_t)readmemwl); + else if (size == 4) + host_arm_BL(block, (uintptr_t)readmemll); + else + fatal("build_load_routine - unknown size %i\n", size); + host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); + host_arm_LDR_IMM_POST(block, REG_PC, REG_SP, 4); + + block_pos = (block_pos + 63) & ~63; +} + +static void build_store_routine(codeblock_t *block, int size) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset; + + /*In - R0 = address + Out - R0 = data, R1 = abrt*/ + /*MOV R1, R0, LSR #12 + MOV R2, #readlookup2 + LDR R1, [R2, R1, LSL #2] + CMP R1, #-1 + BNE + + LDRB R0, [R1, R0] + MOV R1, #0 + MOV PC, LR + * STR LR, [SP, -4]! + BL readmemb386l + LDRB R1, cpu_state.abrt + LDR PC, [SP], #4 + */ + host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12); + host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2); + host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2); + if (size != 1) + { + host_arm_TST_IMM(block, REG_R0, size-1); + misaligned_offset = host_arm_BNE_(block); + } + host_arm_CMP_IMM(block, REG_R2, -1); + branch_offset = host_arm_BEQ_(block); + if (size == 1) + host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 2) + host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 4) + host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0); + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; + host_arm_STR_IMM_WB(block, REG_LR, REG_SP, -4); + if (size == 1) + host_arm_BL(block, (uintptr_t)writememb386l); + else if (size == 2) + host_arm_BL(block, (uintptr_t)writememwl); + else if (size == 4) + host_arm_BL(block, (uintptr_t)writememll); + else + fatal("build_store_routine - unknown size %i\n", size); + host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); + host_arm_LDR_IMM_POST(block, REG_PC, REG_SP, 4); + + block_pos = (block_pos + 63) & ~63; +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4); + + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4); +} + void codegen_backend_init() { int c; @@ -57,6 +197,10 @@ void codegen_backend_init() } #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); + + block_current = BLOCK_SIZE; + block_pos = 0; + build_loadstore_routines(&codeblock[block_current]); } /*R11 - literal pool diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index e433f43..9df86f9 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -5,6 +5,7 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" +#include "codegen_backend_arm64_ops.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -15,6 +16,14 @@ #include #endif +void *codegen_mem_load_byte; +void *codegen_mem_load_word; +void *codegen_mem_load_long; + +void *codegen_mem_store_byte; +void *codegen_mem_store_word; +void *codegen_mem_store_long; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_X19, @@ -24,6 +33,145 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_X23 }; +static void build_load_routine(codeblock_t *block, int size) +{ + uint32_t *branch_offset; + uint8_t *misaligned_offset; + int offset; + + /*In - W0 = address + Out - W0 = data, W1 = abrt*/ + /*MOV W1, W0, LSR #12 + MOV X2, #readlookup2 + LDR X1, [X2, X1, LSL #3] + CMP X1, #-1 + BEQ + + LDRB W0, [X1, X0] + MOV W1, #0 + RET + * STP X29, X30, [SP, #-16] + BL readmemb386l + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); + offset = add_literal_q(block, (uintptr_t)readlookup2); + host_arm64_LDR_LITERAL_X(block, REG_X2, offset); + host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); + if (size != 1) + { + host_arm64_TST_IMM(block, REG_W0, size-1); + misaligned_offset = host_arm64_BNE_(block); + } + host_arm64_CMPX_IMM(block, REG_X1, -1); + branch_offset = host_arm64_BEQ_(block); + if (size == 1) + host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 2) + host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 4) + host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); + host_arm64_MOVZ_IMM(block, REG_W1, 0); + host_arm64_RET(block, REG_X30); + + host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + if (size != 1) + host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); + if (size == 1) + host_arm64_call(block, (uintptr_t)readmemb386l); + else if (size == 2) + host_arm64_call(block, (uintptr_t)readmemwl); + else if (size == 4) + host_arm64_call(block, (uintptr_t)readmemll); + else + fatal("build_load_routine - unknown size %i\n", size); + codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_RET(block, REG_X30); + + block_pos = (block_pos + 63) & ~63; +} + +static void build_store_routine(codeblock_t *block, int size) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset; + int offset; + + /*In - R0 = address, R1 = data + Out - R1 = abrt*/ + /*MOV W2, W0, LSR #12 + MOV X3, #writelookup2 + LDR X2, [X3, X2, LSL #3] + CMP X2, #-1 + BEQ + + STRB W1, [X2, X0] + MOV W1, #0 + RET + * STP X29, X30, [SP, #-16] + BL writememb386l + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); + offset = add_literal_q(block, (uintptr_t)writelookup2); + host_arm64_LDR_LITERAL_X(block, REG_X3, offset); + host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); + if (size != 1) + { + host_arm64_TST_IMM(block, REG_W0, size-1); + misaligned_offset = host_arm64_BNE_(block); + } + host_arm64_CMPX_IMM(block, REG_X2, -1); + branch_offset = host_arm64_BEQ_(block); + if (size == 1) + host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 2) + host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 4) + host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); + host_arm64_MOVZ_IMM(block, REG_X1, 0); + host_arm64_RET(block, REG_X30); + + host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + if (size != 1) + host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); + if (size == 1) + host_arm64_call(block, (uintptr_t)writememb386l); + else if (size == 2) + host_arm64_call(block, (uintptr_t)writememwl); + else if (size == 4) + host_arm64_call(block, (uintptr_t)writememll); + else + fatal("build_store_routine - unknown size %i\n", size); + codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_RET(block, REG_X30); + + block_pos = (block_pos + 63) & ~63; +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4); + + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4); +} + void codegen_backend_init() { int c; @@ -59,6 +207,11 @@ void codegen_backend_init() } #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); + + block_current = BLOCK_SIZE; + block_pos = 0; + codegen_reset_literal_pool(&codeblock[block_current]); + build_loadstore_routines(&codeblock[block_current]); } /*R11 - literal pool diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 7de61f0..48e58ec 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -75,4 +75,12 @@ #define REG_TEMP REG_X7 -#define CODEGEN_HOST_REGS 5 \ No newline at end of file +#define CODEGEN_HOST_REGS 5 + +extern void *codegen_mem_load_byte; +extern void *codegen_mem_load_word; +extern void *codegen_mem_load_long; + +extern void *codegen_mem_store_byte; +extern void *codegen_mem_store_word; +extern void *codegen_mem_store_long; \ No newline at end of file diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c new file mode 100644 index 0000000..4effa1a --- /dev/null +++ b/src/codegen_backend_arm64_ops.c @@ -0,0 +1,613 @@ +#ifdef __aarch64__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm64_defs.h" +#include "codegen_backend_arm64_ops.h" + + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +#define Rt(x) (x) +#define Rd(x) (x) +#define Rn(x) ((x) << 5) +#define Rt2(x) ((x) << 10) +#define Rm(x) ((x) << 16) + +#define shift_imm6(x) ((x) << 10) + +#define DATA_OFFSET_UP (1 << 23) +#define DATA_OFFSET_DOWN (0 << 23) + +#define COND_EQ (0x0) +#define COND_NE (0x1) + +#define OPCODE_SHIFT 24 +#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) +#define OPCODE_BCOND (0x54 << OPCODE_SHIFT) +#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) +#define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) +#define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) +#define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) +#define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) +#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) +#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) +#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) + +#define OPCODE_AND_IMM (0x024 << 23) +#define OPCODE_ANDS_IMM (0x0e4 << 23) +#define OPCODE_EOR_IMM (0x0a4 << 23) +#define OPCODE_MOVK_W (0x0e5 << 23) +#define OPCODE_MOVZ_W (0x0a5 << 23) +#define OPCODE_ORR_IMM (0x064 << 23) + +#define OPCODE_BFI (0x0cc << 22) +#define OPCODE_LDR_IMM_W (0x2e5 << 22) +#define OPCODE_LDRB_IMM_W (0x0e5 << 22) +#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) +#define OPCODE_STP_PREIDX_X (0x2a6 << 22) +#define OPCODE_STR_IMM_W (0x2e4 << 22) +#define OPCODE_STR_IMM_Q (0x3e4 << 22) +#define OPCODE_STRB_IMM (0x0e4 << 22) +#define OPCODE_UBFX (0x14c << 22) + +#define OPCODE_ADD_LSL (0x058 << 21) +#define OPCODE_ADD_LSR (0x05a << 21) +#define OPCODE_AND_ASR (0x054 << 21) +#define OPCODE_AND_LSL (0x050 << 21) +#define OPCODE_AND_ROR (0x056 << 21) +#define OPCODE_ANDS_LSL (0x350 << 21) +#define OPCODE_EOR_LSL (0x250 << 21) +#define OPCODE_ORR_LSL (0x150 << 21) +#define OPCODE_ORR_LSR (0x152 << 21) +#define OPCODE_SUB_LSL (0x258 << 21) +#define OPCODE_SUB_LSR (0x25a << 21) + +#define OPCODE_BLR (0xd63f0000) +#define OPCODE_LDR_REG (0xb8606800) +#define OPCODE_LDRB_REG (0x38606800) +#define OPCODE_LDRH_REG (0x78606800) +#define OPCODE_LDRX_REG_LSL3 (0xf8607800) +#define OPCODE_NOP (0xd503201f) +#define OPCODE_RET (0xd65f0000) +#define OPCODE_STR_REG (0xb8206800) +#define OPCODE_STRB_REG (0x38206800) +#define OPCODE_STRH_REG (0x78206800) + +#define DATPROC_SHIFT(sh) (sh << 10) +#define DATPROC_IMM_SHIFT(sh) (sh << 22) +#define MOV_WIDE_HW(hw) (hw << 21) + +#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) +#define IMM12(imm_data) ((imm_data) << 10) +#define IMM16(imm_data) ((imm_data) << 5) + +#define IMMN(immn) ((immn) << 22) +#define IMMR(immr) ((immr) << 16) +#define IMMS(imms) ((imms) << 10) + +#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) + +#define OFFSET12_B(offset) (offset << 10) +#define OFFSET12_W(offset) ((offset >> 2) << 10) +#define OFFSET12_Q(offset) ((offset >> 3) << 10) + +static int literal_offset = 0; +void codegen_reset_literal_pool(codeblock_t *block) +{ + literal_offset = 0; +} + +/*Returns true if offset fits into 19 bits*/ +static int offset_is_19bit(int offset) +{ + if (offset >= (1 << (18+2))) + return 0; + if (offset < -(1 << (18+2))) + return 0; + return 1; +} + +int add_literal(codeblock_t *block, uint32_t data) +{ + if (literal_offset >= 4096) + fatal("add_literal - literal pool full\n"); + + *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; + + literal_offset += 4; + + return literal_offset - 4; +} + +int add_literal_q(codeblock_t *block, uint64_t data) +{ + if (literal_offset & 4) + literal_offset += 4; + + if (literal_offset >= 4096-4) + fatal("add_literal - literal pool full\n"); + + *(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; + + literal_offset += 8; + + return literal_offset - 8; +} + +static inline int imm_is_imm16(uint32_t imm_data) +{ + if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) + return 1; + return 0; +} +static inline int imm_is_imm12(uint32_t imm_data) +{ + if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff)) + return 1; + return 0; +} + +void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) + { + host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); + } + else if (!(imm_data & 0xff000000)) + { + if (imm_data & 0xfff) + { + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else + { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); + } + else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } + else if (imm_data == 0x0000ff00) + { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); + } + else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } + else if (imm_data == 0x0000ff00) + { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ANDS_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} + +void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); +} + +void host_arm64_BLR(codeblock_t *block, int addr_reg) +{ + codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); +} + +uint32_t *host_arm64_BEQ_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_EQ); + return &block->data[block_pos-4]; +} +uint32_t *host_arm64_BNE_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_NE); + return &block->data[block_pos-4]; +} + +void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) +{ + int offset = (uintptr_t)dest - (uintptr_t)opcode; + *opcode |= OFFSET19(offset); +} + +void host_arm64_BEQ(codeblock_t *block, void *dest) +{ + uint32_t *opcode = host_arm64_BEQ_(block); + host_arm64_branch_set_offset(opcode, dest); +} + +void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) +{ + int offset = dest - (uintptr_t)&block->data[block_pos]; + if (!offset_is_19bit(offset)) + fatal("host_arm64_CBNZ - offset out of range %x\n", offset); + codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); +} + +void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) +{ + if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) + { + host_arm64_CMP_IMM(block, src_n_reg, -(int32_t)imm_data); + } + else if (!(imm_data & 0xfffff000)) + { + codegen_addlong(block, OPCODE_CMN_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } + else + fatal("CMN_IMM %08x\n", imm_data); +} +void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) +{ + if ((int64_t)imm_data < 0 && imm_data != (1ull << 63)) + { + host_arm64_CMPX_IMM(block, src_n_reg, -(int64_t)imm_data); + } + else if (!(imm_data & 0xfffffffffffff000ull)) + { + codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } + else + fatal("CMNX_IMM %08x\n", imm_data); +} + +void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) +{ + if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) + { + host_arm64_CMN_IMM(block, src_n_reg, -(int32_t)imm_data); + } + else if (!(imm_data & 0xfffff000)) + { + codegen_addlong(block, OPCODE_CMP_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } + else + fatal("CMP_IMM %08x\n", imm_data); +} +void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) +{ + if ((int64_t)imm_data < 0 && imm_data != (1ull << 63)) + { + host_arm64_CMNX_IMM(block, src_n_reg, -(int64_t)imm_data); + } + else if (!(imm_data & 0xfffffffffffff000ull)) + { + codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } + else + fatal("CMPX_IMM %08x\n", imm_data); +} + +void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +{ + if (!in_range7_x(offset)) + fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); +} + +void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_w(offset)) + fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); +} + +void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) +{ + int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; + + if (!offset_is_19bit(offset)) + fatal("host_arm64_CBNZ - offset out of range %x\n", offset); + + codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg)); +} +void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset) +{ + int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; + + if (!offset_is_19bit(offset)) + fatal("host_arm64_CBNZ - offset out of range %x\n", offset); + + codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg)); +} +void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} + +void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_b(offset)) + fatal("host_arm64_LDRB_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDRB_IMM_W | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); +} +void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} + +void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} + +void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} + +void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + if (dst_reg != src_m_reg) + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + int hw; + + if (!imm_is_imm16(imm_data)) + fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); + + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; + + codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); +} + +void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + int hw; + + if (!imm_is_imm16(imm_data)) + fatal("MOVK_IMM - imm not representable %08x\n", imm_data); + + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; + + codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); +} + +void host_arm64_NOP(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_NOP); +} + +void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else if (imm_data == 0xffff0000) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f)); + } + else if (imm_data == 0xffffff00) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); + } + else if (imm_data == 0xffff00ff) + { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_RET(codeblock_t *block, int reg) +{ + codegen_addlong(block, OPCODE_RET | Rn(reg)); +} + +void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +{ + if (!in_range7_x(offset)) + fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); +} + +void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_w(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); +} +void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_q(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); +} +void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); +} + +void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_b(offset)) + fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); +} +void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); +} + +void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); +} + +void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) + { + host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); + } + else if (!(imm_data & 0xff000000)) + { + if (imm_data & 0xfff) + { + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else + { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + +void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); +} + + +void host_arm64_call(codeblock_t *block, void *dst_addr) +{ + int offset = add_literal_q(block, (uintptr_t)dst_addr); + host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_BLR(block, REG_X16); +} + +void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) +{ + if (imm_is_imm16(imm_data)) + host_arm64_MOVZ_IMM(block, reg, imm_data); + else + { + host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); + } +} + +#endif \ No newline at end of file diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h new file mode 100644 index 0000000..6178c6b --- /dev/null +++ b/src/codegen_backend_arm64_ops.h @@ -0,0 +1,92 @@ +void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); +void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + +void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); +void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + +void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); + +void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); + +void host_arm64_BLR(codeblock_t *block, int addr_reg); + +void host_arm64_BEQ(codeblock_t *block, void *dest); + +uint32_t *host_arm64_BEQ_(codeblock_t *block); +uint32_t *host_arm64_BNE_(codeblock_t *block); + +void host_arm64_branch_set_offset(uint32_t *opcode, void *dest); + +void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); + +void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); +void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); + +void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); +void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); + +void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); +void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + +void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); + +void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset); +void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); +void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); + +void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); + +void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); + +void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); + +void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); + +void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); +void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data); + +void host_arm64_NOP(codeblock_t *block); + +void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); +void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + +void host_arm64_RET(codeblock_t *block, int reg); + +void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); + +void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); + +void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); + +void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); + +void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); +void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + +#define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data) + +void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); + +void host_arm64_call(codeblock_t *block, void *dst_addr); +void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); + + +#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) +#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) +#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) +#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7)) + + +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); + +int add_literal_q(codeblock_t *block, uint64_t data); \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index b641a4b..8b5aad0 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -4,459 +4,9 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" +#include "codegen_backend_arm64_ops.h" #include "codegen_ir_defs.h" -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -#define Rt(x) (x) -#define Rd(x) (x) -#define Rn(x) ((x) << 5) -#define Rt2(x) ((x) << 10) -#define Rm(x) ((x) << 16) - -#define shift_imm6(x) ((x) << 10) - -#define DATA_OFFSET_UP (1 << 23) -#define DATA_OFFSET_DOWN (0 << 23) - -#define COND_SHIFT 28 -#define COND_NE (0x1 << COND_SHIFT) -#define COND_AL (0xe << COND_SHIFT) - -#define OPCODE_SHIFT 24 -#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) -#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) -#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) -#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) -#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) - -#define OPCODE_AND_IMM (0x024 << 23) -#define OPCODE_EOR_IMM (0x0a4 << 23) -#define OPCODE_MOVK_W (0x0e5 << 23) -#define OPCODE_MOVZ_W (0x0a5 << 23) -#define OPCODE_ORR_IMM (0x064 << 23) - -#define OPCODE_BFI (0x0cc << 22) -#define OPCODE_LDR_IMM_W (0x2e5 << 22) -#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) -#define OPCODE_STP_PREIDX_X (0x2a6 << 22) -#define OPCODE_STR_IMM_W (0x2e4 << 22) -#define OPCODE_STR_IMM_Q (0x3e4 << 22) -#define OPCODE_STRB_IMM (0x0e4 << 22) -#define OPCODE_UBFX (0x14c << 22) - -#define OPCODE_ADD_LSL (0x058 << 21) -#define OPCODE_ADD_LSR (0x05a << 21) -#define OPCODE_AND_ASR (0x054 << 21) -#define OPCODE_AND_LSL (0x050 << 21) -#define OPCODE_AND_ROR (0x056 << 21) -#define OPCODE_EOR_LSL (0x250 << 21) -#define OPCODE_ORR_LSL (0x150 << 21) -#define OPCODE_ORR_LSR (0x152 << 21) -#define OPCODE_SUB_LSL (0x258 << 21) -#define OPCODE_SUB_LSR (0x25a << 21) - -#define OPCODE_BLR (0xd63f0000) -#define OPCODE_NOP (0xd503201f) -#define OPCODE_RET (0xd65f0000) - -#define DATPROC_SHIFT(sh) (sh << 10) -#define DATPROC_IMM_SHIFT(sh) (sh << 22) -#define MOV_WIDE_HW(hw) (hw << 21) - -#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) -#define IMM12(imm_data) ((imm_data) << 10) -#define IMM16(imm_data) ((imm_data) << 5) - -#define IMMN(immn) ((immn) << 22) -#define IMMR(immr) ((immr) << 16) -#define IMMS(imms) ((imms) << 10) - -#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) - -#define OFFSET12_B(offset) (offset << 10) -#define OFFSET12_W(offset) ((offset >> 2) << 10) -#define OFFSET12_Q(offset) ((offset >> 3) << 10) - -static int literal_offset = 0; -void codegen_reset_literal_pool(codeblock_t *block) -{ - literal_offset = 0; -} - -/*Returns true if offset fits into 19 bits*/ -static int offset_is_19bit(int offset) -{ - if (offset >= (1 << (18+2))) - return 0; - if (offset < -(1 << (18+2))) - return 0; - return 1; -} - -#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) -#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) -#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) -#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7)) - -int add_literal(codeblock_t *block, uint32_t data) -{ - if (literal_offset >= 4096) - fatal("add_literal - literal pool full\n"); - - *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 4; - - return literal_offset - 4; -} - -int add_literal_q(codeblock_t *block, uint64_t data) -{ - if (literal_offset & 4) - literal_offset += 4; - - if (literal_offset >= 4096-4) - fatal("add_literal - literal pool full\n"); - - *(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 8; - - return literal_offset - 8; -} - -static inline int imm_is_imm16(uint32_t imm_data) -{ - if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) - return 1; - return 0; -} -static inline int imm_is_imm12(uint32_t imm_data) -{ - if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff)) - return 1; - return 0; -} - -void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); -void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); - -void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) -{ - if (!imm_data) - host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); - else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) - { - host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xff000000)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - { - host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); - codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } -} -void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} -void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} -//12001c00 S=0 R=7 -void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) -{ - if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); - } - else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else if (imm_data == 0xffffff00) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); - } - else if (imm_data == 0xffff00ff) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); - } - else if (imm_data == 0x0000ff00) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } -} -void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} -void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} -void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} - -void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) -{ - codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); -} - -void host_arm64_BLR(codeblock_t *block, int addr_reg) -{ - codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); -} - -void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) -{ - int offset = dest - (uintptr_t)&block->data[block_pos]; - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); -} - -void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) -{ - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } -} -void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} - -void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) -{ - if (!in_range7_x(offset)) - fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); - codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); -} - -void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) -{ - if (!in_range12_w(offset)) - fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); -} - -void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) -{ - int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; - - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - - codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg)); -} -void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset) -{ - int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; - - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - - codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg)); -} - -void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) -{ - if (dst_reg != src_m_reg) - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} - -void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} - -void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) -{ - int hw; - - if (!imm_is_imm16(imm_data)) - fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); - - hw = (imm_data & 0xffff0000) ? 1 : 0; - if (hw) - imm_data >>= 16; - - codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); -} - -void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) -{ - int hw; - - if (!imm_is_imm16(imm_data)) - fatal("MOVK_IMM - imm not representable %08x\n", imm_data); - - hw = (imm_data & 0xffff0000) ? 1 : 0; - if (hw) - imm_data >>= 16; - - codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); -} - -void host_arm64_NOP(codeblock_t *block) -{ - codegen_addlong(block, OPCODE_NOP); -} - -void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) -{ - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else if (imm_data == 0xffff0000) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f)); - } - else if (imm_data == 0xffffff00) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); - } - else if (imm_data == 0xffff00ff) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } -} -void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} - -void host_arm64_RET(codeblock_t *block, int reg) -{ - codegen_addlong(block, OPCODE_RET | Rn(reg)); -} - -void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) -{ - if (!in_range7_x(offset)) - fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); - codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); -} - -void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) -{ - if (!in_range12_w(offset)) - fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); -} -void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) -{ - if (!in_range12_q(offset)) - fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); -} -void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) -{ - if (!in_range12_b(offset)) - fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); -} - -void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) -{ - if (!imm_data) - host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); - else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) - { - host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xff000000)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - { - host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); - codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } -} -void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} -void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) -{ - codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); -} - -void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) -{ - codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); -} - -void host_arm64_call(codeblock_t *block, void *dst_addr) -{ - int offset = add_literal_q(block, (uintptr_t)dst_addr); - host_arm64_LDR_LITERAL_X(block, REG_X16, offset); - host_arm64_BLR(block, REG_X16); -} - -void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) -{ - if (imm_is_imm16(imm_data)) - host_arm64_MOVZ_IMM(block, reg, imm_data); - else - { - host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); - } -} - #define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) #define REG_IS_L(size) (size == IREG_SIZE_L) @@ -605,7 +155,7 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) } else fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - + return 0; } @@ -617,6 +167,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_arm64_BEQ(block, uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); @@ -642,6 +208,186 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_ADD_IMM(block, REG_X0, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) + { + host_arm64_call(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_call(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_arm64_call(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); + } + else if (REG_IS_BH(dest_size)) + { + host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); + } + else if (REG_IS_L(dest_size)) + { + host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); + } + + return 0; +} +static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) + { + host_arm64_call(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_call(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_arm64_call(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); + } + else if (REG_IS_BH(dest_size)) + { + host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); + } + else if (REG_IS_L(dest_size)) + { + host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); + } + + return 0; +} + +static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + + host_arm64_ADD_IMM(block, REG_W0, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); + host_arm64_call(block, codegen_mem_store_byte); + } + else if (REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); + host_arm64_call(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); + host_arm64_call(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_arm64_MOV_REG(block, REG_W1, src_reg, 0); + host_arm64_call(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); + host_arm64_call(block, codegen_mem_store_byte); + } + else if (REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); + host_arm64_call(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); + host_arm64_call(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_arm64_MOV_REG(block, REG_W1, src_reg, 0); + host_arm64_call(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_byte); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_word); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_long); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -799,7 +545,7 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) } else fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - + return 0; } @@ -978,7 +724,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) } else fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - + return 0; } @@ -994,6 +740,15 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + + [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, @@ -1009,9 +764,19 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SUB & UOP_MASK] = codegen_SUB, [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +{ + if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_LDRB_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_8 - not in range\n"); +} + void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 1fadfa1..3ec520b 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -45,4 +45,12 @@ #define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \ REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) -#define CODEGEN_HOST_REGS 3 \ No newline at end of file +#define CODEGEN_HOST_REGS 3 + +extern void *codegen_mem_load_byte; +extern void *codegen_mem_load_word; +extern void *codegen_mem_load_long; + +extern void *codegen_mem_store_byte; +extern void *codegen_mem_store_word; +extern void *codegen_mem_store_long; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c new file mode 100644 index 0000000..f7772ae --- /dev/null +++ b/src/codegen_backend_arm_ops.c @@ -0,0 +1,587 @@ +#ifdef __ARM_EABI__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm_defs.h" +#include "codegen_backend_arm_ops.h" + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +#define Rm(x) (x) +#define Rd(x) ((x) << 12) +#define Rn(x) ((x) << 16) + +#define DATA_OFFSET_UP (1 << 23) +#define DATA_OFFSET_DOWN (0 << 23) + +#define COND_SHIFT 28 +#define COND_EQ (0x0 << COND_SHIFT) +#define COND_NE (0x1 << COND_SHIFT) +#define COND_AL (0xe << COND_SHIFT) + +#define OPCODE_SHIFT 20 +#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) +#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) +#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) +#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) +#define OPCODE_B (0xa0 << OPCODE_SHIFT) +#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) +#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) +#define OPCODE_BL (0xb0 << OPCODE_SHIFT) +#define OPCODE_CMN_IMM (0x37 << OPCODE_SHIFT) +#define OPCODE_CMN_REG (0x17 << OPCODE_SHIFT) +#define OPCODE_CMP_IMM (0x35 << OPCODE_SHIFT) +#define OPCODE_CMP_REG (0x15 << OPCODE_SHIFT) +#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) +#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) +#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) +#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) +#define OPCODE_LDR_IMM_POST (0x41 << OPCODE_SHIFT) +#define OPCODE_LDR_REG (0x79 << OPCODE_SHIFT) +#define OPCODE_LDRB_IMM (0x55 << OPCODE_SHIFT) +#define OPCODE_LDRB_REG (0x7d << OPCODE_SHIFT) +#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) +#define OPCODE_MOVT_IMM (0x34 << OPCODE_SHIFT) +#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) +#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) +#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) +#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) +#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) +#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) +#define OPCODE_STR_IMM_WB (0x52 << OPCODE_SHIFT) +#define OPCODE_STR_REG (0x78 << OPCODE_SHIFT) +#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) +#define OPCODE_STRB_REG (0x7c << OPCODE_SHIFT) +#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) +#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) +#define OPCODE_TST_IMM (0x31 << OPCODE_SHIFT) +#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) + +#define OPCODE_BFI 0xe7c00010 +#define OPCODE_BLX 0xe12fff30 +#define OPCODE_LDRH_REG 0xe19000b0 +#define OPCODE_STRH_REG 0xe18000b0 +#define OPCODE_UADD8 0xe6500f90 +#define OPCODE_UADD16 0xe6500f10 +#define OPCODE_USUB8 0xe6500ff0 +#define OPCODE_USUB16 0xe6500f70 +#define OPCODE_UXTB 0xe6ef0070 +#define OPCODE_UXTH 0xe6ff0070 + +#define B_OFFSET(x) (((x) >> 2) & 0xffffff) + +#define SHIFT_TYPE_SHIFT 5 +#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) +#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) +#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) +#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) + +#define SHIFT_TYPE_IMM (0 << 4) +#define SHIFT_TYPE_REG (1 << 4) + +#define SHIFT_IMM_SHIFT 7 +#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) + +#define BFI_lsb(lsb) ((lsb) << 7) +#define BFI_msb(msb) ((msb) << 16) + +#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) + +#define MOVT_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) +#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) + +static int literal_offset = 0; +void codegen_reset_literal_pool(codeblock_t *block) +{ + literal_offset = 0; +} + +int add_literal(codeblock_t *block, uint32_t data) +{ + int c; + + if (literal_offset >= 4096) + fatal("add_literal - literal pool full\n"); + + /*Search for pre-existing value*/ + for (c = 0; c < literal_offset; c += 4) + { + if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data) + return c; + } + + *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; + + literal_offset += 4; + + return literal_offset - 4; +} + + +static inline uint32_t arm_data_offset(int offset) +{ + if (offset < -0xffc || offset > 0xffc) + fatal("arm_data_offset out of range - %i\n", offset); + + if (offset >= 0) + return offset | DATA_OFFSET_UP; + return (-offset) | DATA_OFFSET_DOWN; +} + +static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) +{ + int shift = 0; +//pclog("get_arm_imm - imm_data=%08x\n", imm_data); + if (!(imm_data & 0xffff)) + { + shift += 16; + imm_data >>= 16; + } + if (!(imm_data & 0xff)) + { + shift += 8; + imm_data >>= 8; + } + if (!(imm_data & 0xf)) + { + shift += 4; + imm_data >>= 4; + } + if (!(imm_data & 0x3)) + { + shift += 2; + imm_data >>= 2; + } + if (imm_data > 0xff) /*Note - should handle rotation round the word*/ + return 0; +//pclog(" imm_data=%02x shift=%i\n", imm_data, shift); + *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); + return 1; +} + +static inline int in_range(void *addr, void *base) +{ + int diff = (uintptr_t)addr - (uintptr_t)base; + + if (diff < -4095 || diff > 4095) + return 0; + return 1; +} + +void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if ((int32_t)imm < 0 && imm != 0x80000000) + { + host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm); + } + else if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else if (get_arm_imm(~imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); +} + +void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} +void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + +void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + { + host_arm_MOV_IMM(block, REG_R3, dest_addr); + host_arm_BLX(block, REG_R3); + } + else + codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); +} +void host_arm_BLX(codeblock_t *block, int addr_reg) +{ + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); +} + +uint32_t *host_arm_BEQ_(codeblock_t *block) +{ + codegen_addlong(block, COND_EQ | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BNE_(codeblock_t *block) +{ + codegen_addlong(block, COND_NE | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} + +void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); + + codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset)); +} +void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); + + codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); +} + +void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if ((int32_t)imm < 0 && imm != 0x80000000) + { + host_arm_CMP_IMM(block, src_reg, -(int32_t)imm); + } + else if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_CMN_IMM | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0); + } +} +void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_CMN_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if ((int32_t)imm < 0 && imm != 0x80000000) + { + host_arm_CMN_IMM(block, src_reg, -(int32_t)imm); + } + else if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_CMP_IMM | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0); + } +} +void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_CMP_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +{ + codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); +} + +void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); +} +void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM_POST | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); +} +void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_LDR_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_LDRB_ABS(codeblock_t *block, int dst_reg, void *p) +{ + if (in_range(p, &cpu_state)) + host_arm_LDRB_IMM(block, dst_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("LDRB_ABS - not in range\n"); +} +void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_LDRB_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); +} +void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg)); +} + +void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); + } + else + { + host_arm_MOVW_IMM(block, dst_reg, imm & 0xffff); + if (imm >> 16) + host_arm_MOVT_IMM(block, dst_reg, imm >> 16); + } +} + +void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); +} +void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); +} + +void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +{ + codegen_addlong(block, COND_AL | OPCODE_MOVT_IMM | Rd(dst_reg) | MOVT_IMM(imm)); +} +void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +{ + codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); +} + +void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + +void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +{ + codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); +} + +void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); +} +void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_STR_IMM_WB | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); +} +void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_STR_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); +} +void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); +} + +void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg)); +} + +void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if ((int32_t)imm < 0 && imm != 0x80000000) + { + host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm); + } + else if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} + +void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} +void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} + +void host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm); + } + else + { + int offset = add_literal(block, imm); + host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_TST_REG(block, src_reg, REG_TEMP); + } +} +void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) +{ + codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); +} + +void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); +} + +void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} + +void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} + +#endif \ No newline at end of file diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h new file mode 100644 index 0000000..31aee46 --- /dev/null +++ b/src/codegen_backend_arm_ops.h @@ -0,0 +1,84 @@ +void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +#define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0) +void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); + +void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_BL(codeblock_t *block, uintptr_t dest_addr); +void host_arm_BLX(codeblock_t *block, int addr_reg); +uint32_t *host_arm_BEQ_(codeblock_t *block); +uint32_t *host_arm_BNE_(codeblock_t *block); +void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr); +void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr); + +void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm); +void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift); + +void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm); +void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift); + +void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); + +void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset); +void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset); +#define host_arm_LDR_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDR_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0) +void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift); + +void host_arm_LDRB_ABS(codeblock_t *block, int dst, void *p); +void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset); +#define host_arm_LDRB_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDRB_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0) +void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift); + +void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg); + +void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm); +#define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0) +void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm); +void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); + +void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift); + +void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); + +void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset); +void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset); +#define host_arm_STR_REG(block, src_reg, addr_reg, offset_reg) host_arm_STR_REG_LSL(block, src_reg, addr_reg, offset_reg, 0) +void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift); + +void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset); +#define host_arm_STRB_REG(block, src_reg, addr_reg, offset_reg) host_arm_STRB_REG_LSL(block, src_reg, addr_reg, offset_reg, 0) +void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift); + +void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg); + +void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +void host_arm_TST_IMM(codeblock_t *block, int src_reg1, uint32_t imm); +void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2); + +void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); +void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 17fd823..b6f5f41 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -4,125 +4,9 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" +#include "codegen_backend_arm_ops.h" #include "codegen_ir_defs.h" -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -#define Rm(x) (x) -#define Rd(x) ((x) << 12) -#define Rn(x) ((x) << 16) - -#define DATA_OFFSET_UP (1 << 23) -#define DATA_OFFSET_DOWN (0 << 23) - -#define COND_SHIFT 28 -#define COND_NE (0x1 << COND_SHIFT) -#define COND_AL (0xe << COND_SHIFT) - -#define OPCODE_SHIFT 20 -#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) -#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) -#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) -#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) -#define OPCODE_B (0xa0 << OPCODE_SHIFT) -#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) -#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) -#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) -#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) -#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) -#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) -#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) -#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) -#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) -#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) -#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) -#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) -#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) -#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) -#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) -#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) -#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) -#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) -#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) - -#define OPCODE_BFI 0xe7c00010 -#define OPCODE_BLX 0xe12fff30 -#define OPCODE_UADD8 0xe6500f90 -#define OPCODE_UADD16 0xe6500f10 -#define OPCODE_USUB8 0xe6500ff0 -#define OPCODE_USUB16 0xe6500f70 -#define OPCODE_UXTB 0xe6ef0070 -#define OPCODE_UXTH 0xe6ff0070 - -#define B_OFFSET(x) (((x) >> 2) & 0xffffff) - -#define SHIFT_TYPE_SHIFT 5 -#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) - -#define SHIFT_TYPE_IMM (0 << 4) -#define SHIFT_TYPE_REG (1 << 4) - -#define SHIFT_IMM_SHIFT 7 -#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) - -#define BFI_lsb(lsb) ((lsb) << 7) -#define BFI_msb(msb) ((msb) << 16) - -#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) - -#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) - -static int literal_offset = 0; -void codegen_reset_literal_pool(codeblock_t *block) -{ - literal_offset = 0; -} - -int add_literal(codeblock_t *block, uint32_t data) -{ - int c; - - if (literal_offset >= 4096) - fatal("add_literal - literal pool full\n"); - - /*Search for pre-existing value*/ - for (c = 0; c < literal_offset; c += 4) - { - if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data) - return c; - } - - *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 4; - - return literal_offset - 4; -} - - -static inline uint32_t arm_data_offset(int offset) -{ - if (offset < -0xffc || offset > 0xffc) - fatal("arm_data_offset out of range - %i\n", offset); - - if (offset >= 0) - return offset | DATA_OFFSET_UP; - return (-offset) | DATA_OFFSET_DOWN; -} - static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) { int shift = 0; @@ -163,261 +47,6 @@ static inline int in_range(void *addr, void *base) return 1; } -void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); - -void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) -{ - uint32_t arm_imm; - - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); - host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } -} - -void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); -} - -void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) -{ - uint32_t arm_imm; - - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else if (get_arm_imm(~imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); - host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } -} - -void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); -} - -void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) -{ - codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); -} - -void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); -} -void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); -} - -void host_arm_BLX(codeblock_t *block, int addr_reg) -{ - codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); -} - -void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) -{ - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; - - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); - - codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); -} - -void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) -{ - uint32_t arm_imm; - - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); - host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } -} - -void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); -} - -void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) -{ - codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); -} - -void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) -{ - codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); -} - -void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) -{ - uint32_t arm_imm; - - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); - } - else - { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, dst_reg, REG_LITERAL, offset); - } -} - -void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); -} -void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); -} - -void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) -{ - codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); -} - -void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); -} - -void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) -{ - uint32_t arm_imm; - - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); - host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } -} - -void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); -} - -void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); -} - -void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) -{ - codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); -} - -void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) -{ - codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); -} - -void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) -{ - codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); -} - -void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) -{ - uint32_t arm_imm; - - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); - host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } -} - -void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); -} -void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) -{ - codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); -} - -void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) -{ - codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); -} - -void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); -} - -void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); -} - -void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); -} - -void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); -} - -void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) -{ - codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); -} - -void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) -{ - codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); -} - void host_arm_call(codeblock_t *block, void *dst_addr) { int offset = add_literal(block, (uintptr_t)dst_addr); @@ -593,6 +222,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_arm_BEQ(block, uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { uint32_t arm_imm; @@ -646,6 +291,190 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) + { + host_arm_BL(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_arm_BL(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_arm_BL(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_arm_BFI(block, dest_reg, REG_R0, 0, 8); + } + else if (REG_IS_BH(dest_size)) + { + host_arm_BFI(block, dest_reg, REG_R0, 8, 8); + } + else if (REG_IS_W(dest_size)) + { + host_arm_BFI(block, dest_reg, REG_R0, 0, 16); + } + else if (REG_IS_L(dest_size)) + { + host_arm_MOV_REG(block, dest_reg, REG_R0); + } + + return 0; +} + +static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) + { + host_arm_BL(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_arm_BL(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_arm_BL(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_arm_BFI(block, dest_reg, REG_R0, 0, 8); + } + else if (REG_IS_BH(dest_size)) + { + host_arm_BFI(block, dest_reg, REG_R0, 8, 8); + } + else if (REG_IS_W(dest_size)) + { + host_arm_BFI(block, dest_reg, REG_R0, 0, 16); + } + else if (REG_IS_L(dest_size)) + { + host_arm_MOV_REG(block, dest_reg, REG_R0); + } + + return 0; +} + +static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + + host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) + { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (REG_IS_B(src_size)) + { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, codegen_mem_store_byte); + } + else if (REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8); + host_arm_BL(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, codegen_mem_store_byte); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, codegen_mem_store_word); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, codegen_mem_store_long); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1015,11 +844,20 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + + [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, @@ -1030,7 +868,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SUB & UOP_MASK] = codegen_SUB, [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 36b4567..deda8ef 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -3,6 +3,8 @@ #include "ibm.h" #include "codegen.h" #include "codegen_backend.h" +#include "codegen_backend_x86-64_defs.h" +#include "codegen_backend_x86-64_ops.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -13,6 +15,14 @@ #include #endif +void *codegen_mem_load_byte; +void *codegen_mem_load_word; +void *codegen_mem_load_long; + +void *codegen_mem_store_byte; +void *codegen_mem_store_word; +void *codegen_mem_store_long; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_EAX, @@ -22,6 +32,183 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = static void *mem_abrt_rout; +static void build_load_routine(codeblock_t *block, int size) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset; + + /*In - ESI = address + Out - ECX = data, ESI = abrt*/ + /*MOV ECX, ESI + SHR ESI, 12 + MOV RSI, [readlookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOVZX ECX, B[RSI+RCX] + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL readmemb386l + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2); + host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3); + if (size != 1) + { + host_x86_TEST32_REG_IMM(block, REG_ECX, size-1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); + branch_offset = host_x86_JZ_short(block); + if (size == 1) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 2) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 4) + host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); + else + fatal("build_load_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_RET(block); + + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + host_x86_PUSH(block, REG_RAX); + host_x86_PUSH(block, REG_RDX); +#if WIN64 + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); + //host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data); +#else + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); +#endif + if (size == 1) + { + host_x86_CALL(block, (void *)readmemb386l); + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + } + else if (size == 2) + { + host_x86_CALL(block, (void *)readmemwl); + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + } + else if (size == 4) + { + host_x86_CALL(block, (void *)readmemll); + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + } +#if WIN64 + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); +#endif + host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; +} + +static void build_store_routine(codeblock_t *block, int size) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset; + + /*In - ECX = data, ESI = address + Out - ESI = abrt + Corrupts EDI*/ + /*MOV EDI, ESI + SHR ESI, 12 + MOV ESI, [writelookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOV [RSI+RDI], ECX + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL writememb386l + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2); + host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3); + if (size != 1) + { + host_x86_TEST32_REG_IMM(block, REG_EDI, size-1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); + branch_offset = host_x86_JZ_short(block); + if (size == 1) + host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 2) + host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 4) + host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else + fatal("build_store_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_RET(block); + + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + host_x86_PUSH(block, REG_RAX); + host_x86_PUSH(block, REG_RDX); +#if WIN64 + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); + host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address +#else + //host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address + host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data +#endif + if (size == 1) + host_x86_CALL(block, (void *)writememb386l); + else if (size == 2) + host_x86_CALL(block, (void *)writememwl); + else if (size == 4) + host_x86_CALL(block, (void *)writememll); +#if WIN64 + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); +#endif + host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4); + + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4); +} + void codegen_backend_init() { int c; @@ -55,6 +242,11 @@ void codegen_backend_init() } #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); + + block_current = BLOCK_SIZE; + block_pos = 0; + build_loadstore_routines(&codeblock[block_current]); +// fatal("Here\n"); } static inline void call(codeblock_t *block, uintptr_t func) diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index dcb9a58..706c70d 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -6,3 +6,20 @@ #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 + +#define REG_RAX 0 +#define REG_RCX 1 +#define REG_RDX 2 +#define REG_RBX 3 +#define REG_RSP 4 +#define REG_RBP 5 +#define REG_RSI 6 +#define REG_RDI 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_R13 13 +#define REG_R14 14 +#define REG_R15 15 diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c new file mode 100644 index 0000000..f508e8a --- /dev/null +++ b/src/codegen_backend_x86-64_ops.c @@ -0,0 +1,888 @@ +#ifdef __amd64__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_x86-64_defs.h" +#include "codegen_backend_x86-64_ops.h" + +#define RM_OP_ADD 0x00 +#define RM_OP_OR 0x08 +#define RM_OP_AND 0x20 +#define RM_OP_SUB 0x28 +#define RM_OP_XOR 0x30 +#define RM_OP_CMP 0x38 + +#define RM_OP_SHR 0x28 + +static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +{ + block->data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte over! %i\n", block_pos); +// CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + block->data[block_pos++] = vald; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addword(codeblock_t *block, uint16_t val) +{ + *(uint16_t *)&block->data[block_pos] = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addquad(codeblock_t *block, uint64_t val) +{ + *(uint64_t *)&block->data[block_pos] = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static int is_imm8(uint32_t imm_data) +{ + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; +} + +static inline void call(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + codegen_addbyte(block, 0xE8); /*CALL*/ + codegen_addlong(block, (uint32_t)diff); + } + else + { + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ + codegen_addquad(block, func); + codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ + } +} + +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ +} +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else + fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); +} +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ +} + +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ +} +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ +} + +void host_x86_CALL(codeblock_t *block, void *p) +{ + call(block, (uintptr_t)p); +} + +void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + else + fatal("CMP64_REG_IMM not 8-bit imm\n"); +} + +void host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} +void host_x86_JZ(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + +uint8_t *host_x86_JNZ_short(codeblock_t *block) +{ + codegen_addbyte2(block, 0x75, 0); /*JNZ*/ + return &block->data[block_pos-1]; +} +uint8_t *host_x86_JZ_short(codeblock_t *block) +{ + codegen_addbyte2(block, 0x74, 0); /*JZ*/ + return &block->data[block_pos-1]; +} + +void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + if (offset) + { + codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ + codegen_addlong(block, offset); + } + else + codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ +} +void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG - bad reg\n"); + + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ + ((src_reg_b & 7) << 3) | (src_reg_a & 7)); +} +void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); + + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ + (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); +} + +void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ + codegen_addbyte(block, imm_data); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); + codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t)(uintptr_t)p); + codegen_addbyte(block, imm_data); + } +} +void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t)(uintptr_t)p); + codegen_addlong(block, imm_data); + } +} + +void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOV8_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOV32_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } + else if (offset < (1ull << 32)) + { + codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOV64_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); + codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} + +void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ +} +void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ +} +void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ +} + +void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOV32_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } + else if (offset < (1ull << 32)) + { + codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } + else + { + fatal("host_x86_MOV32_REG_ABS - out of range\n"); + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} + +void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ +} + +void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale) +{ + if ((dst_reg & 8) || (index_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + if (base_reg & 8) + codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ + else + codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ +} + +void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg >= 8) + fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ +} +void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); +} +void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); +} + +void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) +{ + if (reg & 8) + { + codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); + } +} + +void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV8_REG_REG - bad reg\n"); + + codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV16_REG_REG - bad reg\n"); + + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV32_REG_REG - bad reg\n"); + + codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} + +void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + if (!offset) + { + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else if (offset >= -80 || offset < 0x80) + { + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } +} + +void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); +} +void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); +} + +void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + +// if (dst_reg & 8) +// fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + if (dst_reg & 8) + codegen_addbyte(block, 0x44); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + else + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); +} + +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ +} +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ +} + +void host_x86_POP(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("POP reg & 8\n"); + codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ +} + +void host_x86_PUSH(codeblock_t *block, int src_reg) +{ + if (src_reg & 8) + fatal("PUSH reg & 8\n"); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ +} + +void host_x86_RET(codeblock_t *block) +{ + codegen_addbyte(block, 0xc3); /*RET*/ +} + +void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR32_IMM reg & 8\n"); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ +} +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else + fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); +} +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ +} + +#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) + +void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_TEST32_REG - bad reg\n"); + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("TEST32_REG_IMM reg & 8\n"); + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ +} +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ +} + +#endif diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h new file mode 100644 index 0000000..6070054 --- /dev/null +++ b/src/codegen_backend_x86-64_ops.h @@ -0,0 +1,104 @@ +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data); + +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_CALL(codeblock_t *block, void *p); + +void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); +void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data); + +void host_x86_JNZ(codeblock_t *block, void *p); +void host_x86_JZ(codeblock_t *block, void *p); + +uint8_t *host_x86_JNZ_short(codeblock_t *block); +uint8_t *host_x86_JZ_short(codeblock_t *block); + +void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset); +void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); + +void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); +void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); + +void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg); + +void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); + +void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); + +void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg); + +void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale); + +void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data); +void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data); +void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data); + +void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data); + +void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); + +void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg); + +void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); + +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_POP(codeblock_t *block, int src_reg); + +void host_x86_PUSH(codeblock_t *block, int src_reg); + +void host_x86_RET(codeblock_t *block); + +void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data); + +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg); +void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); + +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index ff1f31f..3e56105 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -4,6 +4,7 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" +#include "codegen_backend_x86-64_ops.h" #include "codegen_ir_defs.h" #define STACK_ARG0 (0) @@ -11,682 +12,6 @@ #define STACK_ARG2 (8) #define STACK_ARG3 (12) -#define RM_OP_ADD 0x00 -#define RM_OP_OR 0x08 -#define RM_OP_AND 0x20 -#define RM_OP_SUB 0x28 -#define RM_OP_XOR 0x30 - -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) -{ - block->data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } -} -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) -{ - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) -{ - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) -{ - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - block->data[block_pos++] = vald; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static inline void codegen_addword(codeblock_t *block, uint16_t val) -{ - *(uint16_t *)&block->data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static inline void codegen_addquad(codeblock_t *block, uint64_t val) -{ - *(uint64_t *)&block->data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static int is_imm8(uint32_t imm_data) -{ - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; -} - -static inline void call(codeblock_t *block, uintptr_t func) -{ - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; - - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - codegen_addbyte(block, 0xE8); /*CALL*/ - codegen_addlong(block, (uint32_t)diff); - } - else - { - codegen_addbyte2(block, 0x48, 0xb8); /*MOV RAX, func*/ - codegen_addquad(block, func); - codegen_addbyte2(block, 0xff, 0xd0); /*CALL RAX*/ - } -} - -static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ -} -static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -static void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ -} -static void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ -} -static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ -} - -static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ -} -static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -static void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ -} -static void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ -} -static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ -} - -static void host_x86_CALL(codeblock_t *block, void *p) -{ - call(block, (uintptr_t)p); -} - -static void host_x86_JNZ(codeblock_t *block, void *p) -{ - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); -} - -static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); - - codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ - (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); -} - -static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ - codegen_addbyte(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); - codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addbyte(block, imm_data); - } -} -static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); - codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addlong(block, imm_data); - } -} - -static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV8_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); - codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV32_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); - codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -static void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV64_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); - codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} - -static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (dst_reg & 8) - fatal("host_x86_MOV32_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else - { - fatal("host_x86_MOV32_REG_ABS - out of range\n"); - codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} - -static void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) -{ - if (reg >= 8) - fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); - codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ -} -static void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV16_REG_IMM reg & 8\n"); - codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ - codegen_addword(block, imm_data); -} -static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV32_REG_IMM reg & 8\n"); - codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ - codegen_addlong(block, imm_data); -} - -static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV64_REG_IMM reg & 8\n"); - codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ - codegen_addquad(block, imm_data); -} - -static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV8_REG_REG - bad reg\n"); - - codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); -} -static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV16_REG_REG - bad reg\n"); - - codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); -} -static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV32_REG_REG - bad reg\n"); - - codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); -} - -static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) -{ - if (!offset) - { - codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else if (offset >= -80 || offset < 0x80) - { - codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, offset); - codegen_addlong(block, imm_data); - } -} - -static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); - codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); - codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} - -static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ -} -static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -static void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ -} -static void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ -} -static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ -} - -static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ -} -static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -static void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ -} -static void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ -} -static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ -} - -#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) - -static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_TEST32_REG - bad reg\n"); - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ -} - -static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ -} -static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -static void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ -} -static void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ -} -static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ -} - #define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) #define REG_IS_L(size) (size == IREG_SIZE_L) @@ -807,6 +132,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_x86_JZ(block, uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { #if WIN64 @@ -836,6 +177,177 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} +static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (REG_IS_B(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); +// fatal("Here\n"); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} + +static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_byte); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_word); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_long); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1077,6 +589,15 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + + [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, @@ -1092,7 +613,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SUB & UOP_MASK] = codegen_SUB, [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 55430e0..b81bfce 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -3,6 +3,8 @@ #include "ibm.h" #include "codegen.h" #include "codegen_backend.h" +#include "codegen_backend_x86_defs.h" +#include "codegen_backend_x86_ops.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -13,6 +15,14 @@ #include #endif +void *codegen_mem_load_byte; +void *codegen_mem_load_word; +void *codegen_mem_load_long; + +void *codegen_mem_store_byte; +void *codegen_mem_store_word; +void *codegen_mem_store_long; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_EAX, @@ -22,6 +32,164 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = static void *mem_abrt_rout; +static void build_load_routine(codeblock_t *block, int size) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset; + + /*In - ESI = address + Out - ECX = data, ESI = abrt*/ + /*MOV ECX, ESI + SHR ESI, 12 + MOV ESI, [readlookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOVZX ECX, B[ESI+ECX] + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL readmemb386l + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2); + if (size != 1) + { + host_x86_TEST32_REG_IMM(block, REG_ECX, size-1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); + branch_offset = host_x86_JZ_short(block); + if (size == 1) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 2) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 4) + host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); + else + fatal("build_load_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_RET(block); + + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + host_x86_PUSH(block, REG_EAX); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + if (size == 1) + host_x86_CALL(block, (void *)readmemb386l); + else if (size == 2) + host_x86_CALL(block, (void *)readmemwl); + else if (size == 4) + host_x86_CALL(block, (void *)readmemll); + host_x86_POP(block, REG_ECX); + if (size == 1) + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + else if (size == 2) + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + else if (size == 4) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_POP(block, REG_EDX); + host_x86_POP(block, REG_EAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; +} + +static void build_store_routine(codeblock_t *block, int size) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset; + + /*In - ECX = data, ESI = address + Out - ESI = abrt + Corrupts EDI*/ + /*MOV EDI, ESI + SHR ESI, 12 + MOV ESI, [writelookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOV [ESI+EDI], ECX + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL writememb386l + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2); + if (size != 1) + { + host_x86_TEST32_REG_IMM(block, REG_EDI, size-1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); + branch_offset = host_x86_JZ_short(block); + if (size == 1) + host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 2) + host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 4) + host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else + fatal("build_store_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_RET(block); + + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + host_x86_PUSH(block, REG_EAX); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + host_x86_PUSH(block, REG_EDI); + if (size == 1) + host_x86_CALL(block, (void *)writememb386l); + else if (size == 2) + host_x86_CALL(block, (void *)writememwl); + else if (size == 4) + host_x86_CALL(block, (void *)writememll); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ECX); + host_x86_POP(block, REG_EDX); + host_x86_POP(block, REG_EAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4); + + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4); +} + void codegen_backend_init() { int c; @@ -67,6 +235,10 @@ void codegen_backend_init() addbyte(0x5d); /*POP EBP*/ addbyte(0x5b); /*POP EDX*/ addbyte(0xC3); /*RET*/ + + block_pos = 64; + build_loadstore_routines(&codeblock[block_current]); + //fatal("Here\n"); asm( "fstcw %0\n" diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index f28915e..37e4160 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -12,4 +12,12 @@ #define CODEGEN_HOST_REGS 3 +extern void *codegen_mem_load_byte; +extern void *codegen_mem_load_word; +extern void *codegen_mem_load_long; + +extern void *codegen_mem_store_byte; +extern void *codegen_mem_store_word; +extern void *codegen_mem_store_long; + #endif diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c new file mode 100644 index 0000000..1447338 --- /dev/null +++ b/src/codegen_backend_x86_ops.c @@ -0,0 +1,779 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_x86_defs.h" +#include "codegen_backend_x86_ops.h" + +#define RM_OP_ADD 0x00 +#define RM_OP_OR 0x08 +#define RM_OP_AND 0x20 +#define RM_OP_SUB 0x28 +#define RM_OP_XOR 0x30 +#define RM_OP_CMP 0x38 + +#define RM_OP_SHR 0x28 + +static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +{ + block->data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte over! %i\n", block_pos); +// CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} +static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +{ + block->data[block_pos++] = vala; + block->data[block_pos++] = valb; + block->data[block_pos++] = valc; + block->data[block_pos++] = vald; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addword(codeblock_t *block, uint16_t val) +{ + *(uint16_t *)&block->data[block_pos] = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + *(uint32_t *)&block->data[block_pos] = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static inline void codegen_addquad(codeblock_t *block, uint64_t val) +{ + *(uint64_t *)&block->data[block_pos] = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } +} + +static int is_imm8(uint32_t imm_data) +{ + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; +} + +void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} + +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ +} +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ +} + +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ +} +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ +} + +void host_x86_CALL(codeblock_t *block, void *p) +{ + codegen_addbyte(block, 0xe8); /*CALL*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + +void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} +void host_x86_JZ(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + +uint8_t *host_x86_JNZ_short(codeblock_t *block) +{ + codegen_addbyte2(block, 0x75, 0); /*JNZ*/ + return &block->data[block_pos-1]; +} +uint8_t *host_x86_JZ_short(codeblock_t *block) +{ + codegen_addbyte2(block, 0x74, 0); /*JZ*/ + return &block->data[block_pos-1]; +} + +void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + if (offset) + { + codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ + codegen_addlong(block, offset); + } + else + codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ +} + +void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ +} +void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ +} + +void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ + codegen_addbyte(block, imm_data); + } + else + { + codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addbyte(block, imm_data); + } +} +void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t)p); + codegen_addlong(block, imm_data); + } +} + +void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} +void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} + +void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ +} +void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ +} +void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ +} + +void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} + +void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) +{ + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ + codegen_addlong(block, (uint32_t)p); +} + +void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ +} + +void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ +} +void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (!imm_data) + { + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } + else + { + codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (!imm_data) + { + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } + else + { + codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); +} + +void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + if (!offset) + { + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else if (offset >= -80 || offset < 0x80) + { + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } +} + +void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } + else + { + codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } + else + { + codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} + +void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ +} +void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ +} + +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ +} + +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ +} +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_POP(codeblock_t *block, int src_reg) +{ + codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ +} + +void host_x86_PUSH(codeblock_t *block, int src_reg) +{ + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ +} + +void host_x86_RET(codeblock_t *block) +{ + codegen_addbyte(block, 0xc3); /*RET*/ +} + +#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) + +void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ +} +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ +} + +void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n"); + + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if (dst_reg != src_reg_a) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ +} + +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + + if (dst_reg == REG_EAX) + codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + else + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ +} +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +{ + if (dst_reg != src_reg) + fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); + + if (is_imm8(imm_data)) + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } + else + { + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +#endif diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h new file mode 100644 index 0000000..cf4a793 --- /dev/null +++ b/src/codegen_backend_x86_ops.h @@ -0,0 +1,100 @@ +void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void *p); + +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_CALL(codeblock_t *block, void *p); + +void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); + +void host_x86_JNZ(codeblock_t *block, void *p); +void host_x86_JZ(codeblock_t *block, void *p); + +uint8_t *host_x86_JNZ_short(codeblock_t *block); +uint8_t *host_x86_JZ_short(codeblock_t *block); + +void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset); +void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); + +void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); +void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); + +void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg); + +void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); + +void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); + +void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift); + +void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + +void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); + +void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); + +void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); + +void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_POP(codeblock_t *block, int src_reg); + +void host_x86_PUSH(codeblock_t *block, int src_reg); + +void host_x86_RET(codeblock_t *block); + +void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); +void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data); + +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); + +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 0f68a25..e043cc9 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -4,6 +4,7 @@ #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" +#include "codegen_backend_x86_ops.h" #include "codegen_ir_defs.h" #define STACK_ARG0 (0) @@ -11,616 +12,6 @@ #define STACK_ARG2 (8) #define STACK_ARG3 (12) -#define RM_OP_ADD 0x00 -#define RM_OP_OR 0x08 -#define RM_OP_AND 0x20 -#define RM_OP_SUB 0x28 -#define RM_OP_XOR 0x30 - -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) -{ - block->data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } -} -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) -{ - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) -{ - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) -{ - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - block->data[block_pos++] = vald; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static inline void codegen_addword(codeblock_t *block, uint16_t val) -{ - *(uint16_t *)&block->data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static inline void codegen_addquad(codeblock_t *block, uint64_t val) -{ - *(uint64_t *)&block->data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - -static int is_imm8(uint32_t imm_data) -{ - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; -} - -static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ -} -static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -static void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ -} -static void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ -} -static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ -} - -static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ -} -static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -static void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ -} -static void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ -} -static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ -} - -static void host_x86_CALL(codeblock_t *block, void *p) -{ - codegen_addbyte(block, 0xe8); /*CALL*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); -} - -static void host_x86_JNZ(codeblock_t *block, void *p) -{ - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); -} - -static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) -{ - codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ -} - -static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ - codegen_addbyte(block, imm_data); - } - else - { - codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addbyte(block, imm_data); - } -} -static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addlong(block, imm_data); - } -} - -static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ - } - else - { - codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} -static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} - -static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} - -static void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ -} -static void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (!imm_data) - { - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ - } - else - { - codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (!imm_data) - { - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ - } - else - { - codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); -} -static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); -} -static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); -} - -static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) -{ - if (!offset) - { - codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else if (offset >= -80 || offset < 0x80) - { - codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, offset); - codegen_addlong(block, imm_data); - } -} - -static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} - -static void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ -} -static void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ -} -static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ -} - -static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ -} -static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) - -static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ -} -static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -static void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ -} -static void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ -} -static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ -} - -static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} - -static void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ -} -static void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n"); - - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ -} -static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if (dst_reg != src_reg_a) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); - - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ -} - -static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); - - if (dst_reg == REG_EAX) - codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ - else - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ -} -static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) -{ - if (dst_reg != src_reg) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); - - if (is_imm8(imm_data)) - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ - else if (dst_reg == REG_EAX) - { - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - - /*void codegen_debug() { pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); @@ -752,6 +143,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_x86_JZ(block, uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); @@ -773,6 +180,176 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} +static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (REG_IS_B(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_long); + } + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } + else if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} + +static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (REG_IS_B(src_size)) + { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } + else if (REG_IS_W(src_size)) + { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } + else if (REG_IS_L(src_size)) + { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + +static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_byte); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_word); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_long); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1010,6 +587,15 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + + [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, @@ -1025,7 +611,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SUB & UOP_MASK] = codegen_SUB, [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM + [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 1d89807..8d81db8 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -27,9 +27,14 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) // pclog("uOP %i : %08x\n", c, uop->type); + if (uop->type & UOP_TYPE_BARRIER) + codegen_reg_flush_invalidate(ir, block); + else if (uop->type & UOP_TYPE_ORDER_BARRIER) + codegen_reg_flush(ir, block); + if (uop->type & UOP_TYPE_PARAMS_REGS) { - codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b); + codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); if (uop->src_reg_a.reg != IREG_INVALID) { uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); @@ -38,19 +43,22 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) { uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); } + if (uop->src_reg_c.reg != IREG_INVALID) + { + uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL); + } if (uop->dest_reg_a.reg != IREG_INVALID) { uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); } } - if (uop->type & UOP_TYPE_BARRIER) - codegen_reg_flush(ir, block); - + if (!uop_handlers[uop->type & UOP_MASK]) + fatal("!uop_handlers[uop->type & UOP_MASK]\n"); uop_handlers[uop->type & UOP_MASK](block, uop); } - codegen_reg_flush(ir, block); + codegen_reg_flush_invalidate(ir, block); codegen_backend_epilogue(block); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 04ee628..7a1d947 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -6,9 +6,17 @@ #define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8)) /*uOP is a barrier. All previous uOPs must have completed before this one executes. - All registers must have been written back or discarded*/ + All registers must have been written back or discarded. + This should be used when calling external functions that may change any emulated + registers.*/ #define UOP_TYPE_BARRIER (1 << 31) +/*uOP is a barrier. All previous uOPs must have completed before this one executes. + All registers must have been written back, but do not have to be discarded. + This should be used when calling functions that preserve registers, but can cause + the code block to exit (eg memory load/store functions).*/ +#define UOP_TYPE_ORDER_BARRIER (1 << 27) + /*uOP uses source and dest registers*/ #define UOP_TYPE_PARAMS_REGS (1 << 28) /*uOP uses pointer*/ @@ -62,8 +70,24 @@ #define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) /*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/ #define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) +/*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/ +#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/ +#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/ +#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/ +#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/ +#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/ +#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/ +#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) +/*UOP_CMP_JZ - if (src_reg_a == imm_data) then jump to ptr*/ +#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) -#define UOP_MAX 0x3b +#define UOP_MAX 0x49 #define UOP_MASK 0xffff @@ -73,10 +97,11 @@ typedef struct uop_t ir_reg_t dest_reg_a; ir_reg_t src_reg_a; ir_reg_t src_reg_b; + ir_reg_t src_reg_c; uint32_t imm_data; void *p; ir_host_reg_t dest_reg_a_real; - ir_host_reg_t src_reg_a_real, src_reg_b_real; + ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; } uop_t; #define UOP_NR_MAX 4096 @@ -99,7 +124,8 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop->dest_reg_a = invalid_ir_reg; uop->src_reg_a = invalid_ir_reg; uop->src_reg_b = invalid_ir_reg; - + uop->src_reg_c = invalid_ir_reg; + return uop; } @@ -179,6 +205,26 @@ static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int uop->imm_data = imm; } +static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->imm_data = imm; +} + +static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); +} + static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) { uop_t *uop = uop_alloc(ir); @@ -204,6 +250,16 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p uop->imm_data = imm; } +static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; + uop->imm_data = imm; +} + #define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) @@ -223,6 +279,16 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) + +#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) +#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg) +#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) +#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg) +#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) + #define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) #define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) #define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index caaf3ff..6fc74b4 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -22,10 +22,10 @@ RecompOpFn recomp_opcodes[512] = /*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -44,10 +44,10 @@ RecompOpFn recomp_opcodes[512] = /*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index b8bb8aa..c7d906d 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -36,43 +36,64 @@ uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; if ((fetchdat & 0xc0) == 0xc0) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = fetchdat & 7; uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); } else - return 0; + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); + } return op_pc + 1; } uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; if ((fetchdat & 0xc0) == 0xc0) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = fetchdat & 7; uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); } else - return 0; + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); + } return op_pc + 1; } uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; if ((fetchdat & 0xc0) == 0xc0) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = fetchdat & 7; uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); } else - return 0; + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); + } return op_pc + 1; } @@ -86,7 +107,15 @@ uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); } else - return 0; + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + CPU_BLOCK_END(); + } return op_pc + 1; } @@ -100,7 +129,14 @@ uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); } else - return 0; + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } return op_pc + 1; } @@ -114,7 +150,176 @@ uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); } else - return 0; + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } return op_pc + 1; } + +uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint8_t imm; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + imm = fastreadb(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_8(dest_reg), imm); + } + else + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadb(cs + op_pc + 1); + uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + return op_pc + 2; +} +uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint16_t imm; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + imm = fastreadw(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_16(dest_reg), imm); + } + else + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadw(cs + op_pc + 1); + uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + return op_pc + 3; +} +uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint32_t imm; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + imm = fastreadl(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_32(dest_reg), imm); + } + else + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadl(cs + op_pc + 1); + uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + return op_pc + 5; +} diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index cf8b31f..78442b4 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -1,9 +1,22 @@ uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 43027f3..28a08be 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -56,6 +56,13 @@ struct [IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins}, [IREG_cycles] = {REG_DWORD, &cpu_state._cycles}, + + [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base}, + [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base}, + [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base}, + [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base}, + [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base}, + [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base}, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will @@ -63,7 +70,7 @@ struct [IREG_temp0] = {REG_DWORD, NULL}, [IREG_temp1] = {REG_DWORD, NULL}, [IREG_temp2] = {REG_DWORD, NULL}, - [IREG_temp3] = {REG_DWORD, NULL} + [IREG_temp3] = {REG_DWORD, NULL}, }; void codegen_reg_reset() @@ -103,7 +110,7 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) //pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version); } -static void codegen_reg_writeback(codeblock_t *block, int c) +static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate) { int ir_reg = IREG_GET_REG(host_regs[c].reg); @@ -125,11 +132,12 @@ static void codegen_reg_writeback(codeblock_t *block, int c) fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); } - host_regs[c] = invalid_ir_reg; + if (invalidate) + host_regs[c] = invalid_ir_reg; host_reg_dirty[c] = 0; } -void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b) +void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) { int c; int dest_reference = 0; @@ -146,6 +154,8 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ dest_reference++; if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1) dest_reference++; + if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version-1) + dest_reference++; } for (c = 0; c < CODEGEN_HOST_REGS; c++) { @@ -161,6 +171,12 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n"); host_regs_locked |= (1 << c); } + if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_c.reg)) + { + if (host_regs[c].version != src_reg_c.version) + fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_c.version\n"); + host_regs_locked |= (1 << c); + } if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(dest_reg_a.reg)) { if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] == dest_reference)) @@ -196,7 +212,7 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in if (c == CODEGEN_HOST_REGS) fatal("codegen_reg_alloc_read_reg - out of registers\n"); if (host_reg_dirty[c]) - codegen_reg_writeback(block, c); + codegen_reg_writeback(block, c, 1); // pclog(" load %i\n", c); codegen_reg_load(block, c, ir_reg); host_regs_locked |= (1 << c); @@ -277,7 +293,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) if (c == CODEGEN_HOST_REGS) fatal("codegen_reg_alloc_write_reg - out of registers\n"); if (host_reg_dirty[c]) - codegen_reg_writeback(block, c); + codegen_reg_writeback(block, c, 1); } } @@ -289,6 +305,19 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) } void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) +{ + int c; + + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + if (!ir_reg_is_invalid(host_regs[c]) && host_reg_dirty[c]) + { + codegen_reg_writeback(block, c, 0); + } + } +} + +void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) { int c; @@ -296,7 +325,7 @@ void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) { if (!ir_reg_is_invalid(host_regs[c])) { - codegen_reg_writeback(block, c); + codegen_reg_writeback(block, c, 1); } } } diff --git a/src/codegen_reg.h b/src/codegen_reg.h index b8f4de5..1e3d339 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -42,13 +42,20 @@ enum IREG_ins = 19, IREG_cycles = 20, + IREG_CS_base = 21, + IREG_DS_base = 22, + IREG_ES_base = 23, + IREG_FS_base = 24, + IREG_GS_base = 25, + IREG_SS_base = 26, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - IREG_temp0 = 21, - IREG_temp1 = 22, - IREG_temp2 = 23, - IREG_temp3 = 24, + IREG_temp0 = 27, + IREG_temp1 = 28, + IREG_temp2 = 29, + IREG_temp3 = 30, IREG_COUNT, @@ -82,6 +89,24 @@ enum #define IREG_16(reg) ((reg) + IREG_AX) #define IREG_32(reg) ((reg) + IREG_EAX) +static inline int ireg_seg_base(x86seg *seg) +{ + if (seg == &cpu_state.seg_cs) + return IREG_CS_base; + if (seg == &cpu_state.seg_ds) + return IREG_DS_base; + if (seg == &cpu_state.seg_es) + return IREG_ES_base; + if (seg == &cpu_state.seg_fs) + return IREG_FS_base; + if (seg == &cpu_state.seg_gs) + return IREG_GS_base; + if (seg == &cpu_state.seg_ss) + return IREG_SS_base; + fatal("ireg_seg_base : unknown segment\n"); + return 0; +} + extern uint8_t reg_last_version[IREG_COUNT]; extern uint8_t reg_version_refcount[IREG_COUNT][256]; @@ -131,10 +156,13 @@ static inline ir_reg_t codegen_reg_write(int reg) struct ir_data_t; void codegen_reg_reset(); +/*Write back all dirty registers*/ void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block); +/*Write back and evict all registers*/ +void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block); /*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/ -void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b); +void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c); ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx); ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); From 5ca2533f3cf83c456f736bb5064381c9e8696bd4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 25 Jul 2018 20:17:42 +0100 Subject: [PATCH 017/181] Increase ARM64 work registers from 5 to 10. --- src/codegen_backend_arm64.c | 7 ++++++- src/codegen_backend_arm64_defs.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 9df86f9..99e1c23 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -30,7 +30,12 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_X20, REG_X21, REG_X22, - REG_X23 + REG_X23, + REG_X24, + REG_X25, + REG_X26, + REG_X27, + REG_X28 }; static void build_load_routine(codeblock_t *block, int size) diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 48e58ec..c818d89 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -75,7 +75,7 @@ #define REG_TEMP REG_X7 -#define CODEGEN_HOST_REGS 5 +#define CODEGEN_HOST_REGS 10 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; From cf508b050f6b2f7c85281e7473a43cc57aa15a4c Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 25 Jul 2018 20:18:03 +0100 Subject: [PATCH 018/181] End block when register version hits a maximum count. --- src/codegen_reg.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 1e3d339..4fd0dd8 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -120,6 +120,8 @@ extern ir_reg_t invalid_ir_reg; typedef uint8_t ir_host_reg_t; +#define REG_VERSION_MAX 250 + static inline ir_reg_t codegen_reg_read(int reg) { ir_reg_t ireg; @@ -132,6 +134,8 @@ static inline ir_reg_t codegen_reg_read(int reg) reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]++; if (!reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]) fatal("codegen_reg_read - refcount overflow\n"); + else if (reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version] > REG_VERSION_MAX) + CPU_BLOCK_END(); return ireg; } @@ -148,6 +152,8 @@ static inline ir_reg_t codegen_reg_write(int reg) reg_last_version[IREG_GET_REG(reg)]++; if (!reg_last_version[IREG_GET_REG(reg)]) fatal("codegen_reg_write - version overflow\n"); + else if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) + CPU_BLOCK_END(); reg_version_refcount[IREG_GET_REG(reg)][ireg.version] = 0; return ireg; From e64271f5bb5ed718d7f763838b9ba3a66b0283fe Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 27 Jul 2018 22:24:34 +0100 Subject: [PATCH 019/181] Added recompiled versions of mem->reg, reg->mem and imm->mem versions of ADD, AND, CMP, OR, SUB and XOR. --- src/codegen_backend_arm.c | 6 +- src/codegen_backend_arm64.c | 6 +- src/codegen_backend_arm64_ops.c | 11 + src/codegen_backend_arm64_ops.h | 2 + src/codegen_backend_arm64_uops.c | 22 +- src/codegen_backend_arm_uops.c | 40 +- src/codegen_backend_x86-64_ops.c | 42 +- src/codegen_backend_x86-64_ops.h | 4 + src/codegen_backend_x86-64_uops.c | 36 +- src/codegen_backend_x86.c | 12 +- src/codegen_backend_x86_ops.c | 36 +- src/codegen_backend_x86_ops.h | 4 + src/codegen_backend_x86_uops.c | 36 +- src/codegen_ir_defs.h | 4 + src/codegen_ops_arith.c | 1313 +++++++++++++++++++++-------- src/codegen_ops_logic.c | 427 ++++++++-- src/codegen_reg.c | 27 +- src/codegen_reg.h | 8 +- 18 files changed, 1524 insertions(+), 512 deletions(-) diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 09630ed..908c5e1 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -221,7 +221,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm_nop(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x20); host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); while (block_pos != BLOCK_START) host_arm_nop(block); @@ -229,7 +229,7 @@ void codegen_backend_prologue(codeblock_t *block) /*Entry code*/ host_arm_STMDB_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_LR); - host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x20); host_arm_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET); host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START); offset = add_literal(block, (uintptr_t)&cpu_state); @@ -238,7 +238,7 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10); + host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x20); host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); if (block_pos > ARM_LITERAL_POOL_OFFSET) diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 99e1c23..4ae98f0 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -237,7 +237,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_NOP(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48); host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); @@ -255,7 +255,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -48); offset = add_literal_q(block, (uintptr_t)&cpu_state); host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); @@ -263,7 +263,7 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48); host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 4effa1a..0a6b8f8 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -34,6 +34,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) +#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) @@ -43,6 +44,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) +#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) #define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_ANDS_IMM (0x0e4 << 23) @@ -63,6 +65,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ADD_LSL (0x058 << 21) #define OPCODE_ADD_LSR (0x05a << 21) +#define OPCODE_ADDX_LSL (0x458 << 21) #define OPCODE_AND_ASR (0x054 << 21) #define OPCODE_AND_LSL (0x050 << 21) #define OPCODE_AND_ROR (0x056 << 21) @@ -70,8 +73,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_ORR_LSR (0x152 << 21) +#define OPCODE_ORRX_LSL (0x550 << 21) #define OPCODE_SUB_LSL (0x258 << 21) #define OPCODE_SUB_LSR (0x25a << 21) +#define OPCODE_SUBX_LSL (0x658 << 21) #define OPCODE_BLR (0xd63f0000) #define OPCODE_LDR_REG (0xb8606800) @@ -444,6 +449,12 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + if (dst_reg != src_m_reg) + codegen_addlong(block, OPCODE_ORRX_LSL | Rd(dst_reg) | Rn(REG_XZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { int hw; diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 6178c6b..9fc993d 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -48,6 +48,8 @@ void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, in void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); + void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 8b5aad0..cd9f180 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -65,17 +65,17 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); @@ -809,4 +809,20 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) fatal("codegen_direct_write_ptr - not in range\n"); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (in_range12_w(stack_offset)) + host_arm64_LDR_IMM_W(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + if (in_range12_w(stack_offset)) + host_arm64_STR_IMM_W(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_write_32_stack - not in range\n"); +} + #endif diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index b6f5f41..0ec4c75 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -75,15 +75,15 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) { host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); - host_arm_UADD16(block, dest_reg, src_reg_a, REG_TEMP); + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { @@ -118,15 +118,15 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && src_reg == dest_reg) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_UADD16(block, dest_reg, src_reg, REG_TEMP); + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && src_reg == dest_reg) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) { @@ -905,4 +905,20 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) fatal("codegen_direct_write_ptr - not in range\n"); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_LDR_IMM(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_STR_IMM(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_write_32 - not in range\n"); +} + #endif diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index f508e8a..9262541 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -174,21 +174,21 @@ void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } @@ -501,6 +501,42 @@ void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int ba codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ } +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} + void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { if (reg >= 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 6070054..4b67841 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -62,11 +62,15 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); + void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 3e56105..d0efa31 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -26,15 +26,22 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + else + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -49,15 +56,22 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + else + host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_ADD16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_ADD8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -638,4 +652,14 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) host_x86_MOV64_ABS_REG(block, p, host_reg); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); +} + #endif diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index b81bfce..17f588f 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -253,18 +253,18 @@ void codegen_backend_prologue(codeblock_t *block) addbyte(0x55); /*PUSH EBP*/ addbyte(0x56); /*PUSH ESI*/ addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $16,%esp*/ + addbyte(0x83); /*SUBL $32,%esp*/ addbyte(0xEC); - addbyte(0x10); + addbyte(0x20); addbyte(0xBD); /*MOVL EBP, &cpu_state*/ addlong(((uintptr_t)&cpu_state) + 128); } void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0x83); /*ADDL $32,%esp*/ addbyte(0xC4); - addbyte(0x10); + addbyte(0x20); addbyte(0x5f); /*POP EDI*/ addbyte(0x5e); /*POP ESI*/ addbyte(0x5d); /*POP EBP*/ @@ -287,9 +287,9 @@ void codegen_backend_epilogue(codeblock_t *block) addbyte(0xe8); /*CALL x86gpf*/ addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0x83); /*ADDL $32,%esp*/ addbyte(0xC4); - addbyte(0x10); + addbyte(0x20); addbyte(0x5f); /*POP EDI*/ addbyte(0x5e); /*POP ESI*/ addbyte(0x5d); /*POP EBP*/ diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 1447338..bcc16ef 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -164,21 +164,21 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } @@ -420,6 +420,36 @@ void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } + else + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} + void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index cf4a793..8d3df16 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -40,12 +40,16 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg); + void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift); void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); + void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e043cc9..c5f3f80 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -36,15 +36,22 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + else + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -59,15 +66,22 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + else + host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_ADD16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_ADD8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -636,4 +650,14 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); +} + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); +} + #endif diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 7a1d947..a864468 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -304,4 +304,8 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); +void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset); + +void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); + #endif diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index 1e3f226..9e7fb43 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -49,14 +49,29 @@ uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -65,30 +80,61 @@ uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -97,30 +143,60 @@ uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -129,16 +205,32 @@ uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -184,14 +276,29 @@ uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); @@ -200,14 +307,29 @@ uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_temp0_B, IREG_8(src_reg)); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); @@ -216,14 +338,29 @@ uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); @@ -232,14 +369,29 @@ uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_16(src_reg)); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); @@ -248,14 +400,29 @@ uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; @@ -263,14 +430,29 @@ uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; @@ -318,14 +500,29 @@ uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -334,30 +531,61 @@ uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -366,30 +594,60 @@ uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -398,16 +656,32 @@ uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -415,70 +689,128 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; - uint8_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint8_t imm = fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint8_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; - case 0x08: /*OR*/ - imm = fastreadb(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; - uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; - case 0x20: /*AND*/ - imm = fastreadb(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; - uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; - case 0x28: /*SUB*/ - imm = fastreadb(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_temp0_B, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = fastreadb(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = fastreadb(cs + op_pc + 1); - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -486,70 +818,128 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch } uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; - uint16_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint16_t imm = fastreadw(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint16_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = fastreadw(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - case 0x08: /*OR*/ - imm = fastreadw(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x20: /*AND*/ - imm = fastreadw(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x28: /*SUB*/ - imm = fastreadw(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = fastreadw(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = fastreadw(cs + op_pc + 1); - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -557,69 +947,126 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; - uint32_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint32_t imm = fastreadl(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint32_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = fastreadl(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - case 0x08: /*OR*/ - imm = fastreadl(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - case 0x20: /*AND*/ - imm = fastreadl(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - case 0x28: /*SUB*/ - imm = fastreadl(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = fastreadl(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = fastreadl(cs + op_pc + 1); - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -628,70 +1075,128 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; - uint16_t imm; - - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - switch (fetchdat & 0x38) + if ((fetchdat & 0xc0) == 0xc0) { - case 0x00: /*ADD*/ + int dest_reg = fetchdat & 7; + uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + uint16_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - case 0x08: /*OR*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x20: /*AND*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; - case 0x28: /*SUB*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; + default: + return 0; + } } codegen_flags_changed = 1; @@ -699,69 +1204,127 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; uint32_t imm; - if ((fetchdat & 0xc0) != 0xc0) + if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ return 0; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*OR*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: /*AND*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SUB*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - case 0x38: /*CMP*/ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; + switch (fetchdat & 0x38) + { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - default: - return 0; + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } } codegen_flags_changed = 1; diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index ad74d7e..df4a3de 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -43,12 +43,25 @@ uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -57,26 +70,55 @@ uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -85,26 +127,55 @@ uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -113,14 +184,30 @@ uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -161,12 +248,25 @@ uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 } uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -175,26 +275,55 @@ uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -203,42 +332,87 @@ uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_res, dest_reg); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; @@ -279,12 +453,25 @@ uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 } uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -293,26 +480,55 @@ uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -321,42 +537,87 @@ uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7, dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_res, dest_reg); codegen_flags_changed = 1; return op_pc + 1; } uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7, dest_reg = fetchdat & 7; + int src_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); codegen_flags_changed = 1; return op_pc + 1; diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 28a08be..8bbf3ca 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -67,10 +67,10 @@ struct /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - [IREG_temp0] = {REG_DWORD, NULL}, - [IREG_temp1] = {REG_DWORD, NULL}, - [IREG_temp2] = {REG_DWORD, NULL}, - [IREG_temp3] = {REG_DWORD, NULL}, + [IREG_temp0] = {REG_DWORD, (void *)16}, + [IREG_temp1] = {REG_DWORD, (void *)20}, + [IREG_temp2] = {REG_DWORD, (void *)24}, + [IREG_temp3] = {REG_DWORD, (void *)28}, }; void codegen_reg_reset() @@ -99,7 +99,10 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { case REG_DWORD: - codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_32_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; default: @@ -113,19 +116,27 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate) { int ir_reg = IREG_GET_REG(host_regs[c].reg); + void *p = ireg_data[ir_reg].p; switch (ireg_data[ir_reg].native_size) { case REG_BYTE: - codegen_direct_write_8(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + if ((uintptr_t)p < 256) + fatal("codegen_reg_writeback - REG_BYTE %p\n", p); + codegen_direct_write_8(block, p, codegen_host_reg_list[c]); break; case REG_DWORD: - codegen_direct_write_32(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + if ((uintptr_t)p < 256) + codegen_direct_write_32_stack(block, (int)p, codegen_host_reg_list[c]); + else + codegen_direct_write_32(block, p, codegen_host_reg_list[c]); break; case REG_POINTER: - codegen_direct_write_ptr(block, ireg_data[ir_reg].p, codegen_host_reg_list[c]); + if ((uintptr_t)p < 256) + fatal("codegen_reg_writeback - REG_POINTER %p\n", p); + codegen_direct_write_ptr(block, p, codegen_host_reg_list[c]); break; default: diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 4fd0dd8..c57a0e5 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -82,7 +82,13 @@ enum IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, - IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, + + IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, + IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, + + IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, + IREG_temp1_B = IREG_temp1 + IREG_SIZE_B }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) From ab359ca9c5bbdea55e2f26dcf9878947083b212f Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 27 Jul 2018 22:25:03 +0100 Subject: [PATCH 020/181] Removed rogue CPU_BLOCK_END() from ropMOV_r_b() --- src/codegen_ops_mov.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index c7d906d..7073578 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -114,7 +114,6 @@ uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - CPU_BLOCK_END(); } return op_pc + 1; From a7d006b637c62331595a0f7bc4dac7a06fffc059 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 2 Aug 2018 22:06:10 +0100 Subject: [PATCH 021/181] Rewrote timer code. The new code is based on timestamps, rather than delays. This eliminates the need to update every timer in timer_process(), which cost a non-trivial amount of CPU time on low-end machines. This involved changes to every user of the timer code, so this change almost certainly introduces bugs. --- src/386.c | 9 +- src/386_dynarec.c | 4 +- src/808x.c | 18 +++- src/cpu.h | 2 +- src/disc.c | 18 ++-- src/disc.h | 6 +- src/esdi_at.c | 60 ++++-------- src/fdc.c | 123 +++++++++---------------- src/fdd.c | 9 +- src/fdd.h | 2 +- src/gameport.c | 23 ++--- src/hdd_esdi.c | 46 +++++---- src/ibm.h | 13 +-- src/ide.c | 76 +++++---------- src/ide.h | 3 +- src/ide_atapi.c | 42 ++++----- src/intel.c | 14 +-- src/joystick_sw_pad.c | 53 ++++------- src/keyboard_amstrad.c | 7 +- src/keyboard_at.c | 15 ++- src/keyboard_olim24.c | 7 +- src/keyboard_pcjr.c | 8 +- src/keyboard_xt.c | 11 ++- src/lpt_dac.c | 2 - src/lpt_dss.c | 8 +- src/mfm_at.c | 50 +++------- src/mfm_xebec.c | 38 ++++---- src/mouse_serial.c | 8 +- src/nethandler.c | 6 +- src/nvr.c | 34 ++++--- src/nvr_tc8521.c | 7 +- src/pit.c | 194 ++++++++++++++++++++------------------ src/pit.h | 2 +- src/scsi_53c400.c | 31 ++++--- src/scsi_aha1540.c | 8 +- src/scsi_cd.c | 47 ++++------ src/scsi_hd.c | 14 ++- src/scsi_zip.c | 14 ++- src/serial.c | 12 +-- src/serial.h | 4 +- src/sound.c | 9 +- src/sound_ad1848.c | 18 +++- src/sound_ad1848.h | 3 +- src/sound_adlibgold.c | 13 +-- src/sound_audiopci.c | 7 +- src/sound_gus.c | 27 +++--- src/sound_opl.c | 45 ++++----- src/sound_opl.h | 3 +- src/sound_pas16.c | 44 +++++---- src/sound_ps1.c | 13 ++- src/sound_pssj.c | 12 ++- src/sound_sb_dsp.c | 104 ++++++++++++--------- src/sound_sb_dsp.h | 7 +- src/timer.c | 205 ++++++++++++++++++++++------------------- src/timer.h | 166 ++++++++++++++++++++++++--------- src/vid_cga.c | 22 +++-- src/vid_cga.h | 4 +- src/vid_colorplus.c | 6 +- src/vid_compaq_cga.c | 10 +- src/vid_ega.c | 16 ++-- src/vid_ega.h | 4 +- src/vid_genius.c | 14 +-- src/vid_hercules.c | 14 +-- src/vid_incolor.c | 14 +-- src/vid_mda.c | 14 +-- src/vid_olivetti_m24.c | 19 ++-- src/vid_pc1512.c | 13 +-- src/vid_pc1640.c | 71 +++++++------- src/vid_pc200.c | 1 - src/vid_pcjr.c | 13 +-- src/vid_s3.c | 2 +- src/vid_svga.c | 14 +-- src/vid_svga.h | 4 +- src/vid_t1000.c | 16 ++-- src/vid_t3100e.c | 16 ++-- src/vid_tandy.c | 13 +-- src/vid_tandysl.c | 13 +-- src/vid_voodoo.c | 28 +++--- src/vid_wy700.c | 14 +-- 79 files changed, 1048 insertions(+), 1031 deletions(-) diff --git a/src/386.c b/src/386.c index dc254d3..25bb653 100644 --- a/src/386.c +++ b/src/386.c @@ -222,12 +222,11 @@ void exec386(int cycs) // output=3; while (cycles>0) { - int cycle_period = (timer_count >> TIMER_SHIFT) + 1; + int cycle_period = (timer_target - (uint32_t)tsc) + 1; x86_was_reset = 0; cycdiff=0; oldcyc=cycles; - timer_start_period(cycles << TIMER_SHIFT); // pclog("%i %02X\n", ins, ram[8]); while (cycdiff < cycle_period) { @@ -257,7 +256,7 @@ dontprint=0; if (output == 3) { - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]); + pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask); } cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -381,7 +380,7 @@ dontprint=0; } tsc += cycdiff; - - timer_end_period(cycles << TIMER_SHIFT); + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); } } diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 32cceb2..3f905bd 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -528,7 +528,6 @@ void exec386_dynarec(int cycs) cycles += cyc_period; cycles_start = cycles; - timer_start_period(cycles << TIMER_SHIFT); // output=3; while (cycles>0) { @@ -945,7 +944,8 @@ inrecomp=0; } } } - timer_end_period(cycles << TIMER_SHIFT); + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); cycles_main -= (cycles_start - cycles); } } diff --git a/src/808x.c b/src/808x.c index 9f66d45..eaeffa6 100644 --- a/src/808x.c +++ b/src/808x.c @@ -25,7 +25,7 @@ #include "x87.h" #include "paths.h" -int xt_cpu_multi; +uint64_t xt_cpu_multi; int nmi = 0; int nmi_auto_clear = 0; @@ -821,13 +821,24 @@ static void setsbc16(uint16_t a, uint16_t b) } int current_diff = 0; + +/*XT systems use the XT master oscillator (14.318 MHz) rather than the CPU clock + at the base timer frequency. Because there isn't an integer relationship + between the two frequencies, use fixed point arithmetic when updating TSC.*/ +static uint64_t tsc_frac = 0; + void clockhardware() { int diff = cycdiff - cycles - current_diff; current_diff += diff; - - timer_end_period(cycles*xt_cpu_multi); + + tsc_frac += (uint64_t)diff * xt_cpu_multi; + + tsc += (tsc_frac >> 32); + tsc_frac &= 0xffffffff; + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); } static int takeint = 0; @@ -1104,7 +1115,6 @@ void execx86(int cycs) // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; } // if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime); cycdiff=cycles; - timer_start_period(cycles*xt_cpu_multi); current_diff = 0; cycles-=nextcyc; // if (instime) pclog("Cycles %i %i\n",cycles,cycdiff); diff --git a/src/cpu.h b/src/cpu.h index ef21835..ca6242f 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -140,7 +140,7 @@ void cpu_WRMSR(); extern int cpu_use_dynarec; -extern int xt_cpu_multi; +extern uint64_t xt_cpu_multi; extern int isa_cycles; #define ISA_CYCLES(x) (x * isa_cycles) diff --git a/src/disc.c b/src/disc.c index d4fa316..b2e0a0c 100644 --- a/src/disc.c +++ b/src/disc.c @@ -9,7 +9,7 @@ #include "timer.h" int disc_drivesel = 0; -int disc_poll_time = 16; +pc_timer_t disc_poll_timer; int disc_track[2]; int writeprot[2], fwriteprot[2]; @@ -22,9 +22,6 @@ int curdrive = 0; //char discfns[2][260] = {"", ""}; int defaultwriteprot = 0; -int fdc_time; -int disc_time; - int fdc_ready; int drive_empty[2] = {1, 1}; @@ -137,7 +134,7 @@ int disc_hole(int drive) void disc_poll() { - disc_poll_time += disc_period * TIMER_USEC; + timer_advance_u64(&disc_poll_timer, disc_period * TIMER_USEC); if (disc_drivesel < 2 && drives[disc_drivesel].poll) drives[disc_drivesel].poll(); @@ -209,7 +206,7 @@ void disc_reset() curdrive = 0; disc_period = 32; - timer_add(disc_poll, &disc_poll_time, &motoron, NULL); + timer_add(&disc_poll_timer, disc_poll, NULL, 0); for (drive = 0; drive < 2; drive++) { @@ -295,3 +292,12 @@ void disc_set_drivesel(int drive) disc_drivesel = drive; } + +void disc_set_motor_enable(int motor_enable) +{ + if (motor_enable && !motoron) + timer_set_delay_u64(&disc_poll_timer, disc_period * TIMER_USEC); + else if (!motor_enable) + timer_disable(&disc_poll_timer); + motoron = motor_enable; +} diff --git a/src/disc.h b/src/disc.h index a0214e4..d8e33a5 100644 --- a/src/disc.h +++ b/src/disc.h @@ -30,8 +30,7 @@ void disc_stop(int drive); int disc_empty(int drive); void disc_set_rate(int drive, int drvden, int rate); void disc_set_drivesel(int drive); -extern int disc_time; -extern int disc_poll_time; +void disc_set_motor_enable(int motor_enable); extern int disc_drivesel; void fdc_callback(); @@ -45,8 +44,7 @@ void fdc_writeprotect(); int fdc_getdata(int last); void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2); void fdc_indexpulse(); -/*extern int fdc_time; -extern int fdc_ready; +/*extern int fdc_ready; extern int fdc_indexcount;*/ extern int motorspin; diff --git a/src/esdi_at.c b/src/esdi_at.c index ae8d81e..c14ab7a 100644 --- a/src/esdi_at.c +++ b/src/esdi_at.c @@ -74,7 +74,7 @@ typedef struct esdi_t uint16_t buffer[256]; int irqstat; - int callback; + pc_timer_t callback_timer; esdi_drive_t drives[2]; @@ -224,18 +224,14 @@ void esdi_write(uint16_t port, uint8_t val, void *p) // pclog("Restore\n"); esdi->command &= ~0x0f; /*Mask off step rate*/ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case CMD_SEEK: // pclog("Seek to cylinder %i\n", esdi->cylinder); esdi->command &= ~0x0f; /*Mask off step rate*/ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; default: @@ -243,9 +239,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) { case CMD_NOP: esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case CMD_READ: case CMD_READ+1: @@ -256,9 +250,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) fatal("Read with ECC\n"); case 0xa0: esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case CMD_WRITE: case CMD_WRITE+1: @@ -275,9 +267,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) // pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",esdi->secount,esdi->sector,esdi->cylinder,esdi->head); esdi->command &= ~1; esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200 * IDE_TIME); break; case CMD_FORMAT: @@ -288,33 +278,25 @@ void esdi_write(uint16_t port, uint8_t val, void *p) case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 30*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 30*IDE_TIME); break; case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case 0xe0: /*???*/ case CMD_READ_PARAMETERS: esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; default: pclog("Bad esdi command %02X\n", val); case 0xe8: /*???*/ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; } } @@ -323,9 +305,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) case 0x3F6: /* Device control */ if ((esdi->fdisk & 4) && !(val & 4)) { - timer_clock(); - esdi->callback = 500*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 500*IDE_TIME); esdi->reset = 1; esdi->status = STAT_BUSY; // pclog("esdi Reset\n"); @@ -333,9 +313,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) if (val & 4) { /*Drive held in reset*/ - timer_clock(); - esdi->callback = 0; - timer_update_outstanding(); + timer_disable(&esdi->callback_timer); esdi->status = STAT_BUSY; } esdi->fdisk = val; @@ -357,9 +335,7 @@ void esdi_writew(uint16_t port, uint16_t val, void *p) { esdi->pos = 0; esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 6*IDE_TIME); } } @@ -428,9 +404,7 @@ uint16_t esdi_readw(uint16_t port, void *p) { esdi_next_sector(esdi); esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 6*IDE_TIME); } } } @@ -446,7 +420,7 @@ void esdi_callback(void *p) off64_t addr; // pclog("esdi_callback: command=%02x reset=%i\n", esdi->command, esdi->reset); - esdi->callback = 0; + if (esdi->reset) { esdi->status = STAT_READY | STAT_DSC; @@ -586,7 +560,7 @@ void esdi_callback(void *p) esdi_next_sector(esdi); esdi->secount = (esdi->secount - 1) & 0xff; if (esdi->secount) - esdi->callback = 6*IDE_TIME; + timer_set_delay_u64(&esdi->callback_timer, 6*IDE_TIME); else { esdi->pos = 0; @@ -804,7 +778,7 @@ void *wd1007vse1_init() io_sethandler(0x01f1, 0x0007, esdi_read, NULL, NULL, esdi_write, NULL, NULL, esdi); io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, esdi_write, NULL, NULL, esdi); - timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); + timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); return esdi; } diff --git a/src/fdc.c b/src/fdc.c index bec48bc..883cf01 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -10,8 +10,6 @@ #include "pic.h" #include "timer.h" -extern int motoron; - static int fdc_reset_stat = 0; /*FDC*/ typedef struct FDC @@ -39,7 +37,7 @@ typedef struct FDC int pcjr, ps1; - int watchdog_timer; + pc_timer_t watchdog_timer; int watchdog_count; int data_ready; @@ -65,6 +63,8 @@ typedef struct FDC uint8_t fifobuf[16]; int int_pending; + + pc_timer_t timer; } FDC; static FDC fdc; @@ -151,12 +151,11 @@ static void fdc_watchdog_poll(void *p) fdc->watchdog_count--; if (fdc->watchdog_count) - fdc->watchdog_timer += 1000 * TIMER_USEC; + timer_advance_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); else { // pclog("Watchdog timed out\n"); - fdc->watchdog_timer = 0; if (fdc->dor & 0x20) picint(1 << 6); } @@ -332,25 +331,19 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) { if ((fdc.dor & 0x40) && !(val & 0x40)) { - fdc.watchdog_timer = 1000 * TIMER_USEC; + timer_set_delay_u64(&fdc.watchdog_timer, 1000 * TIMER_USEC); fdc.watchdog_count = 1000; picintc(1 << 6); // pclog("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC); } if ((val & 0x80) && !(fdc.dor & 0x80)) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); discint=-1; fdc_reset(); } - motoron = val & 0x01; + disc_set_motor_enable(val & 0x01); fdc.drive = 0; -/* if (motoron) - output = 3; - else - output = 0;*/ } else { @@ -361,15 +354,11 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) } if ((val&4) && !(fdc.dor&4)) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); discint=-1; fdc_reset(); } - timer_process(); - motoron = (val & 0xf0) ? 1 : 0; - timer_update_outstanding(); + disc_set_motor_enable((val & 0xf0) ? 1 : 0); fdc.drive = val & 3; } fdc.dor=val; @@ -386,9 +375,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) case 4: if (val & 0x80) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); discint=-1; fdc_reset(); } @@ -471,7 +458,6 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) // printf("Sense interrupt status %i\n",curdrive); fdc.lastdrive = fdc.drive; // fdc.stat = 0x10 | (fdc.stat & 0xf); -// fdc_time=1024; discint = 8; fdc.pos = 0; fdc_callback(); @@ -480,9 +466,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) { fdc.stat=0x10; discint=0xfc; - timer_process(); - disctime = 200 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 100 * TIMER_USEC); } break; case 10: /*Read sector ID*/ @@ -553,9 +537,7 @@ bad_command: // exit(-1); fdc.stat=0x10; discint=0xfc; - timer_process(); - disctime = 200 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 100 * TIMER_USEC); break; } } @@ -564,12 +546,12 @@ bad_command: fdc.params[fdc.pnum++]=val; if (fdc.pnum==fdc.ptot) { + uint64_t time; + // pclog("Got all params %02X\n", fdc.command); fdc.stat=0x30; discint=fdc.command&0x1F; - timer_process(); - disctime = 1024 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); // fdc.drive = fdc.params[0] & 3; disc_drivesel = fdc.drive & 1; fdc_reset_stat = 0; @@ -587,7 +569,7 @@ bad_command: fdc.track[fdc.drive]=fdc.params[1]; // pclog("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.track[fdc.drive], fdc.head, fdc.sector, fdc.eot[fdc.drive]); disc_readsector(fdc.drive, SECTOR_FIRST, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); - disctime = 0; + timer_disable(&fdc.timer); readflash_set(READFLASH_FDC, fdc.drive); fdc.inread = 1; break; @@ -597,7 +579,7 @@ bad_command: fdc.specify[0] = fdc.params[0]; fdc.specify[1] = fdc.params[1]; fdc.dma = (fdc.specify[1] & 1) ^ 1; - disctime = 0; + timer_disable(&fdc.timer); break; case 5: /*Write data*/ @@ -612,7 +594,7 @@ bad_command: fdc.rw_track = fdc.params[1]; disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); - disctime = 0; + timer_disable(&fdc.timer); fdc.written = 0; readflash_set(READFLASH_FDC, fdc.drive); fdc.pos = 0; @@ -633,15 +615,17 @@ bad_command: fdc.rw_track = fdc.params[1]; disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); - disctime = 0; + timer_disable(&fdc.timer); readflash_set(READFLASH_FDC, fdc.drive); fdc.inread = 1; break; case 7: /*Recalibrate*/ fdc.stat = 1 << fdc.drive; - disctime = 0; - fdd_seek(fdc.drive, SEEK_RECALIBRATE); + timer_disable(&fdc.timer); + time = fdd_seek(fdc.drive, SEEK_RECALIBRATE); + if (time) + timer_set_delay_u64(&fdc.timer, time); break; case 0x0d: /*Format*/ @@ -655,14 +639,16 @@ bad_command: case 0xf: /*Seek*/ fdc.stat = 1 << fdc.drive; fdc.head = (fdc.params[0] & 4) ? 1 : 0; - disctime = 0; - fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); + timer_disable(&fdc.timer); + time = fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); + if (time) + timer_set_delay_u64(&fdc.timer, time); // pclog("Seek to %i\n", fdc.params[1]); break; case 10: /*Read sector ID*/ fdc_rate(fdc.drive); - disctime = 0; + timer_disable(&fdc.timer); fdc.head = (fdc.params[0] & 4) ? 1 : 0; // pclog("Read sector ID %i %i\n", fdc.rate, fdc.drive); disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate); @@ -771,9 +757,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) } if (discint==0xA) { - timer_process(); - disctime = 1024 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); } fdc.stat &= 0xf0; break; @@ -805,8 +789,7 @@ void fdc_callback() int doseek = 0; int drive; - disctime = 0; -// pclog("fdc_callback %i %i\n", discint, disctime); +// pclog("fdc_callback %i\n", discint); // if (fdc.inread) // rpclog("c82c711_fdc_callback : while inread! %08X %i %02X %i\n", discint, fdc.drive, fdc.st0, ins); switch (discint) @@ -870,7 +853,6 @@ void fdc_callback() fdc.stat = (fdc.stat & 0xf) | 0xd0; paramstogo = 1; discint = 0; - disctime = 0; return; case 5: /*Write data*/ if (!fdc.in_seek_mt) @@ -983,9 +965,7 @@ void fdc_callback() fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdc.head?4:0); fdc.int_pending = 1; discint=-3; - timer_process(); - disctime = 2048 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 2048 * TIMER_USEC); // printf("Recalibrate complete!\n"); fdc.stat = 0x80 | (1 << fdc.drive); return; @@ -1006,7 +986,6 @@ void fdc_callback() paramstogo = 2; discint = 0; - disctime = 0; return; case 0x0d: /*Format track*/ @@ -1015,26 +994,20 @@ void fdc_callback() { // ioc_fiq(IOC_FIQ_DISC_DATA); fdc.format_state = 2; - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); } else if (fdc.format_state == 2) { temp = fdc_getdata(fdc.pos == ((fdc.params[2] * 4) - 1)); if (temp == -1) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); return; } fdc.format_dat[fdc.pos++] = temp; if (fdc.pos == (fdc.params[2] * 4)) fdc.format_state = 3; - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); } else if (fdc.format_state == 3) { @@ -1070,9 +1043,7 @@ void fdc_callback() fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdc.head?4:0); fdc.int_pending = 1; discint=-3; - timer_process(); - disctime = 2048 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); fdc.stat = 0x80 | (1 << fdc.drive); // pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); return; @@ -1088,7 +1059,6 @@ void fdc_callback() fdc.res[10] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0); paramstogo=10; discint=0; - disctime = 0; return; case 0x10: /*Version*/ @@ -1096,13 +1066,11 @@ void fdc_callback() fdc.res[10] = 0x90; paramstogo=1; discint=0; - disctime = 0; return; case 0x12: fdc.perp = fdc.params[0]; fdc.stat = 0x80; - disctime = 0; // picint(0x40); return; case 0x13: /*Configure*/ @@ -1112,7 +1080,6 @@ void fdc_callback() fdc.tfifo = (fdc.params[1] & 0xF) + 1; pclog("FIFO is now %02X, threshold is %02X\n", fdc.fifo, fdc.tfifo); fdc.stat = 0x80; - disctime = 0; // picint(0x40); return; case 0x14: /*Unlock*/ @@ -1121,7 +1088,6 @@ void fdc_callback() fdc.res[10] = 0; paramstogo=1; discint=0; - disctime = 0; return; case 0x94: /*Lock*/ fdc.lock = 1; @@ -1129,7 +1095,6 @@ void fdc_callback() fdc.res[10] = 0x10; paramstogo=1; discint=0; - disctime = 0; return; case 0x18: /*NSC*/ @@ -1137,7 +1102,6 @@ void fdc_callback() fdc.res[10] = 0x73; paramstogo=1; discint=0; - disctime = 0; return; case 0xfc: /*Invalid*/ @@ -1149,7 +1113,6 @@ void fdc_callback() fdc.res[10] = fdc.st0; paramstogo=1; discint=0; - disctime = 0; return; } // printf("Bad FDC disc int %i\n",discint); @@ -1160,7 +1123,7 @@ void fdc_callback() void fdc_overrun() { disc_sector_stop(); - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1234,13 +1197,13 @@ int fdc_data(uint8_t data) void fdc_finishread() { fdc.inread = 0; - disctime = 200 * TIMER_USEC; + timer_set_delay_u64(&fdc.timer, 200 * TIMER_USEC); // rpclog("fdc_finishread\n"); } void fdc_notfound() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1257,7 +1220,7 @@ void fdc_notfound() void fdc_datacrcerror() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1274,7 +1237,7 @@ void fdc_datacrcerror() void fdc_headercrcerror() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1291,7 +1254,7 @@ void fdc_headercrcerror() void fdc_writeprotect() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1380,7 +1343,7 @@ void fdc_indexpulse() void fdc_init() { - timer_add(fdc_callback, &disctime, &disctime, NULL); + timer_add(&fdc.timer, fdc_callback, NULL, 0); fdc.dskchg_activelow = 0; fdc.enable_3f1 = 1; @@ -1404,7 +1367,7 @@ void fdc_add() void fdc_add_pcjr() { io_sethandler(0x00f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc); + timer_add(&fdc.watchdog_timer, fdc_watchdog_poll, &fdc, 0); fdc.pcjr = 1; fdc.ps1 = 0; } diff --git a/src/fdd.c b/src/fdd.c index 69a196f..9c2c3fa 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -76,15 +76,12 @@ static struct int fdd_swap = 0; -void fdd_seek(int drive, int track_diff) +uint64_t fdd_seek(int drive, int track_diff) { drive ^= fdd_swap; if (drive >= 2) - { - disctime = 5000; - return; - } + return 1000 * TIMER_USEC; fdd[drive].track += track_diff; @@ -99,7 +96,7 @@ void fdd_seek(int drive, int track_diff) fdc_discchange_clear(drive); disc_seek(drive, fdd[drive].track); - disctime = 5000; + return 1000 * TIMER_USEC; } void fdd_disc_changed(int drive) diff --git a/src/fdd.h b/src/fdd.h index 5581b73..76071a1 100644 --- a/src/fdd.h +++ b/src/fdd.h @@ -1,5 +1,5 @@ #define SEEK_RECALIBRATE -999 -void fdd_seek(int drive, int track_diff); +uint64_t fdd_seek(int drive, int track_diff); int fdd_track0(int drive); int fdd_getrpm(int drive); void fdd_set_densel(int densel); diff --git a/src/gameport.c b/src/gameport.c index 5d16123..fbf142a 100644 --- a/src/gameport.c +++ b/src/gameport.c @@ -69,7 +69,7 @@ char *joystick_get_pov_name(int joystick, int id) typedef struct gameport_axis_t { - int count; + pc_timer_t timer; int axis_nr; struct gameport_t *gameport; } gameport_axis_t; @@ -86,7 +86,7 @@ typedef struct gameport_t static gameport_t *gameport_global = NULL; -static int gameport_time(int axis) +static uint64_t gameport_time(int axis) { if (axis == AXIS_NOT_PRESENT) return 0; @@ -101,14 +101,13 @@ void gameport_write(uint16_t addr, uint8_t val, void *p) { gameport_t *gameport = (gameport_t *)p; - timer_clock(); gameport->state |= 0x0f; // pclog("gameport_write : joysticks_present=%i\n", joysticks_present); - gameport->axis[0].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0)); - gameport->axis[1].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1)); - gameport->axis[2].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2)); - gameport->axis[3].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3)); + timer_set_delay_u64(&gameport->axis[0].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0))); + timer_set_delay_u64(&gameport->axis[1].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1))); + timer_set_delay_u64(&gameport->axis[2].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2))); + timer_set_delay_u64(&gameport->axis[3].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3))); gameport->joystick->write(gameport->joystick_dat); @@ -120,7 +119,6 @@ uint8_t gameport_read(uint16_t addr, void *p) gameport_t *gameport = (gameport_t *)p; uint8_t ret; - timer_clock(); // if (joysticks_present) ret = gameport->state | gameport->joystick->read(gameport->joystick_dat);//0xf0; // else @@ -139,7 +137,6 @@ void gameport_timer_over(void *p) gameport_t *gameport = axis->gameport; gameport->state &= ~(1 << axis->axis_nr); - axis->count = 0; if (axis == &gameport->axis[0]) gameport->joystick->a0_over(gameport->joystick_dat); @@ -161,10 +158,10 @@ void *gameport_init_common() gameport->axis[2].axis_nr = 2; gameport->axis[3].axis_nr = 3; - timer_add(gameport_timer_over, &gameport->axis[0].count, &gameport->axis[0].count, &gameport->axis[0]); - timer_add(gameport_timer_over, &gameport->axis[1].count, &gameport->axis[1].count, &gameport->axis[1]); - timer_add(gameport_timer_over, &gameport->axis[2].count, &gameport->axis[2].count, &gameport->axis[2]); - timer_add(gameport_timer_over, &gameport->axis[3].count, &gameport->axis[3].count, &gameport->axis[3]); + timer_add(&gameport->axis[0].timer, gameport_timer_over, &gameport->axis[0], 0); + timer_add(&gameport->axis[1].timer, gameport_timer_over, &gameport->axis[1], 0); + timer_add(&gameport->axis[2].timer, gameport_timer_over, &gameport->axis[2], 0); + timer_add(&gameport->axis[3].timer, gameport_timer_over, &gameport->axis[3], 0); gameport->joystick = joystick_list[joystick_type]; gameport->joystick_dat = gameport->joystick->init(); diff --git a/src/hdd_esdi.c b/src/hdd_esdi.c index 23e1f75..9465af1 100644 --- a/src/hdd_esdi.c +++ b/src/hdd_esdi.c @@ -58,7 +58,7 @@ typedef struct esdi_t int cmd_state; int in_reset; - int callback; + pc_timer_t callback_timer; uint32_t rba; @@ -163,7 +163,7 @@ static void esdi_write(uint16_t port, uint8_t val, void *p) { // pclog("ESDI reset\n"); esdi->in_reset = 1; - esdi->callback = ESDI_TIME * 50; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME * 50); esdi->status = STATUS_BUSY; } esdi->basic_ctrl = val; @@ -195,7 +195,7 @@ static void esdi_write(uint16_t port, uint8_t val, void *p) case ATTN_RESET: // pclog("ESDI reset\n"); esdi->in_reset = 1; - esdi->callback = ESDI_TIME * 50; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME * 50); esdi->status = STATUS_BUSY; break; @@ -311,7 +311,7 @@ static void esdi_writew(uint16_t port, uint16_t val, void *p) if ((esdi->cmd_data[0] & CMD_DEVICE_SEL) != esdi->cmd_dev) fatal("Command device mismatch with attn\n"); esdi->command = esdi->cmd_data[0] & CMD_MASK; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->status = STATUS_BUSY; esdi->data_pos = 0; } @@ -421,8 +421,6 @@ static void esdi_callback(void *p) esdi_t *esdi = (esdi_t *)p; hdd_file_t *hdd_file; - esdi->callback = 0; - // pclog("esdi_callback: in_reset=%i command=%x\n", esdi->in_reset, esdi->command); if (esdi->in_reset) { @@ -464,7 +462,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -472,7 +470,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -492,7 +490,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -506,7 +504,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -551,7 +549,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -559,7 +557,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -572,7 +570,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -591,7 +589,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -739,7 +737,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -747,7 +745,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -762,7 +760,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -774,7 +772,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -803,7 +801,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -811,7 +809,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -824,7 +822,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -837,7 +835,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -917,7 +915,7 @@ static void *esdi_init() hdd_load(&esdi->hdd_file[0], 0, ide_fn[0]); hdd_load(&esdi->hdd_file[1], 1, ide_fn[1]); - timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); + timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); mca_add(esdi_mca_read, esdi_mca_write, esdi); @@ -925,7 +923,7 @@ static void *esdi_init() esdi->pos_regs[1] = 0xdd; esdi->in_reset = 1; - esdi->callback = ESDI_TIME * 50; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME * 50); esdi->status = STATUS_BUSY; return esdi; diff --git a/src/ibm.h b/src/ibm.h index 70641c9..e852ac1 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -2,6 +2,8 @@ #include #include +#include "timer.h" + #ifdef ABS #undef ABS #endif @@ -296,7 +298,7 @@ typedef struct PIT_nr typedef struct PIT { uint32_t l[3]; - int c[3]; + pc_timer_t timer[3]; uint8_t m[3]; uint8_t ctrl,ctrls[3]; int wp,rm[3],wm[3]; @@ -378,7 +380,6 @@ PIC pic,pic2; extern int pic_intpending; -int disctime; char discfns[2][256]; int driveempty[2]; @@ -527,10 +528,10 @@ extern int changeframecount; /*Sound*/ int ppispeakon; -float CGACONST; -float MDACONST; -float VGACONST1,VGACONST2; -float RTCCONST; +extern uint64_t CGACONST; +extern uint64_t MDACONST; +extern uint64_t VGACONST1,VGACONST2; +extern uint64_t RTCCONST; int gated,speakval,speakon; diff --git a/src/ide.c b/src/ide.c index 5d1a29b..44e74a7 100644 --- a/src/ide.c +++ b/src/ide.c @@ -1,4 +1,4 @@ -#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define IDE_TIME (10 * TIMER_USEC) #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -98,7 +98,7 @@ int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size); int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size); void (*ide_bus_master_set_irq)(int channel); -int idecallback[2] = {0, 0}; +pc_timer_t ide_timer[2]; int cur_ide[2]; @@ -268,7 +268,6 @@ void resetide(void) ide_drives[d].board = (d & 2) ? 1 : 0; } - idecallback[0]=idecallback[1]=0; if (hdd_controller_current_is_ide()) { for (d = 0; d < 4; d++) @@ -324,12 +323,10 @@ void writeidew(int ide_board, uint16_t val) { ide->pos=0; ide->atastat = BUSY_STAT; - timer_process(); if (ide->command == WIN_WRITE_MULTIPLE) callbackide(ide_board); else - idecallback[ide_board] = 6 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 6 * IDE_TIME); } } } @@ -428,8 +425,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) if (IDE_DRIVE_IS_CDROM(ide_other)) ide_other->cylinder=0xEB14; - idecallback[ide_board] = 0; - timer_update_outstanding(); + timer_disable(&ide_timer[ide_board]); return; } @@ -460,18 +456,14 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SRST: /* ATAPI Device Reset */ if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT; else ide->atastat = READY_STAT; - timer_process(); - idecallback[ide_board]=100*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 100*IDE_TIME); return; case WIN_RESTORE: case WIN_SEEK: // pclog("WIN_RESTORE start\n"); ide->atastat = READY_STAT; - timer_process(); - idecallback[ide_board]=100*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 100*IDE_TIME); return; case WIN_READ_MULTIPLE: @@ -495,9 +487,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); #endif ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); ide->do_initial_read = 1; return; @@ -530,9 +520,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); #endif ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_VERIFY: @@ -542,9 +530,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); #endif ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_FORMAT: @@ -556,18 +542,14 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SPECIFY: /* Initialize Drive Parameters */ ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=30*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 30*IDE_TIME); // pclog("SPECIFY\n"); // output=1; return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_PIDENTIFY: /* Identify Packet Device */ @@ -576,10 +558,8 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SETIDLE1: /* Idle */ case WIN_CHECK_POWER_MODE: ide->atastat = BUSY_STAT; - timer_process(); callbackide(ide_board); // idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); return; case WIN_IDENTIFY: /* Identify Device */ @@ -587,9 +567,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) // output=3; // timetolive=500; ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_PACKETCMD: /* ATAPI Packet */ @@ -597,9 +575,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) atapi_command_start(&ide->atapi, ide->cylprecomp); ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board] = IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], IDE_TIME); ide->atapi.bus_state = 0; return; @@ -618,9 +594,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case 0x3F6: /* Device control */ if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { - timer_process(); - idecallback[ide_board]=500*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 500*IDE_TIME); ide->reset = ide_other->reset = 1; ide->atastat = ide_other->atastat = BUSY_STAT; // pclog("IDE Reset %i\n", ide_board); @@ -628,9 +602,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) if (val & 4) { /*Drive held in reset*/ - timer_process(); - idecallback[ide_board] = 0; - timer_update_outstanding(); + timer_disable(&ide_timer[ide_board]); ide->atastat = ide_other->atastat = BUSY_STAT; } ide->fdisk = ide_other->fdisk = val; @@ -794,12 +766,10 @@ uint16_t readidew(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - timer_process(); if (ide->command == WIN_READ_MULTIPLE) callbackide(ide_board); else - idecallback[ide_board] = 6 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 6 * IDE_TIME); // pclog("set idecallback\n"); // callbackide(ide_board); } @@ -936,7 +906,7 @@ void callbackide(int ide_board) if (ide_bus_master_read_data) { if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512)) - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { /*DMA successful*/ @@ -948,7 +918,7 @@ void callbackide(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); } else { @@ -1014,7 +984,7 @@ void callbackide(int ide_board) if (ide_bus_master_write_data) { if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512)) - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { /*DMA successful*/ @@ -1027,7 +997,7 @@ void callbackide(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); } else { @@ -1201,13 +1171,11 @@ abort_cmd: void ide_callback_pri() { - idecallback[0] = 0; callbackide(0); } void ide_callback_sec() { - idecallback[1] = 0; callbackide(1); } @@ -1292,8 +1260,8 @@ static void *ide_init() ide_pri_enable(); ide_sec_enable(); - timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL); - timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); + timer_add(&ide_timer[0], ide_callback_pri, NULL, 0); + timer_add(&ide_timer[1], ide_callback_sec, NULL, 0); return (void *)-1; } diff --git a/src/ide.h b/src/ide.h index cb497ea..aed1200 100644 --- a/src/ide.h +++ b/src/ide.h @@ -2,6 +2,7 @@ #define __IDE__ #include "device.h" +#include "timer.h" struct IDE; @@ -26,7 +27,7 @@ extern void (*ide_bus_master_set_irq)(int channel); extern int ideboard; -extern int idecallback[2]; +extern pc_timer_t ide_timer[2]; extern char ide_fn[7][512]; diff --git a/src/ide_atapi.c b/src/ide_atapi.c index 1760a43..ab4330e 100644 --- a/src/ide_atapi.c +++ b/src/ide_atapi.c @@ -4,7 +4,7 @@ #include "scsi.h" #include "timer.h" -#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define IDE_TIME (100 * TIMER_USEC) #define ATAPI_STATE_IDLE 0 #define ATAPI_STATE_COMMAND 1 @@ -35,7 +35,7 @@ void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val) if (atapi_dev->command_pos >= 12) { atapi_dev->state = ATAPI_STATE_GOT_COMMAND; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -47,7 +47,7 @@ void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val) { atapi_dev->bus_state = 0; atapi_dev->state = ATAPI_STATE_WRITE_DATA; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; } @@ -73,7 +73,7 @@ uint16_t atapi_data_read(atapi_device_t *atapi_dev) if (atapi_dev->data_read_pos >= atapi_dev->data_write_pos) { atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6*IDE_TIME); } break; } @@ -199,7 +199,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { // pclog("SEND_COMMAND timed out %x\n", scsi_bus_read(&atapi_dev->bus)); atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); break; } @@ -209,7 +209,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { // pclog("SEND_COMMAND - bus state changed %x\n", bus_state); atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); break; } @@ -261,20 +261,20 @@ void atapi_process_packet(atapi_device_t *atapi_dev) if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) { atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->data_write_pos = atapi_dev->data_read_pos; atapi_dev->bus_state = 0; atapi_dev->state = ATAPI_STATE_WRITE_DATA; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } } else { atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } } else @@ -312,7 +312,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -344,7 +344,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -387,7 +387,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -433,18 +433,18 @@ void atapi_process_packet(atapi_device_t *atapi_dev) if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) { atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } } else { atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } } else @@ -490,7 +490,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) } atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 1 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1 * IDE_TIME); } break; @@ -529,7 +529,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) ide_irq_raise(atapi_dev->ide); } else - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -537,12 +537,12 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) { - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6*IDE_TIME); } } break; @@ -551,13 +551,13 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) { - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->bus_state = 0; atapi_dev->state = ATAPI_STATE_WRITE_DATA; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } } break; diff --git a/src/intel.c b/src/intel.c index 21e91b1..85ebcbf 100644 --- a/src/intel.c +++ b/src/intel.c @@ -45,11 +45,10 @@ void batman_brdconfig_write(uint16_t port, uint8_t val, void *p) } static uint16_t batman_timer_latch; -static int batman_timer = 0; +static pc_timer_t batman_timer; static void batman_timer_over(void *p) { - batman_timer = 0; } static void batman_timer_write(uint16_t addr, uint8_t val, void *p) @@ -58,7 +57,7 @@ static void batman_timer_write(uint16_t addr, uint8_t val, void *p) batman_timer_latch = (batman_timer_latch & 0xff) | (val << 8); else batman_timer_latch = (batman_timer_latch & 0xff00) | val; - batman_timer = batman_timer_latch * TIMER_USEC; + timer_set_delay_u64(&batman_timer, batman_timer_latch * TIMER_USEC); } static uint8_t batman_timer_read(uint16_t addr, void *p) @@ -67,12 +66,7 @@ static uint8_t batman_timer_read(uint16_t addr, void *p) cycles -= (int)PITCONST; - timer_clock(); - - if (batman_timer < 0) - return 0; - - batman_timer_latch = batman_timer / TIMER_USEC; + batman_timer_latch = timer_get_remaining_us(&batman_timer); if (addr & 1) return batman_timer_latch >> 8; @@ -87,7 +81,7 @@ void intel_batman_init() io_sethandler(0x0078, 0x0002, batman_timer_read, NULL, NULL, batman_timer_write, NULL, NULL, NULL); io_sethandler(0x0092, 0x0001, batman_brdconfig, NULL, NULL, batman_brdconfig_write, NULL, NULL, NULL); batman_port_92 = 0; - timer_add(batman_timer_over, &batman_timer, &batman_timer, NULL); + timer_add(&batman_timer, batman_timer_over, NULL, 0); } diff --git a/src/joystick_sw_pad.c b/src/joystick_sw_pad.c index c0d0e8b..b5aab34 100644 --- a/src/joystick_sw_pad.c +++ b/src/joystick_sw_pad.c @@ -30,13 +30,13 @@ typedef struct { - int poll_time; + pc_timer_t poll_timer; int poll_left; int poll_clock; uint64_t poll_data; int poll_mode; - int trigger_time; + pc_timer_t trigger_timer; int data_mode; } sw_data; @@ -44,33 +44,22 @@ static void sw_timer_over(void *p) { sw_data *sw = (sw_data *)p; - while (sw->poll_time <= 0 && sw->poll_left) - { - sw->poll_clock = !sw->poll_clock; + sw->poll_clock = !sw->poll_clock; - if (sw->poll_clock) - { - sw->poll_data >>= (sw->poll_mode ? 3 : 1); - sw->poll_left--; - } - - if (sw->poll_left == 1 && !sw->poll_clock) - sw->poll_time += TIMER_USEC * 160; - else if (sw->poll_left) - sw->poll_time += TIMER_USEC * 5; - else - sw->poll_time = 0; + if (sw->poll_clock) + { + sw->poll_data >>= (sw->poll_mode ? 3 : 1); + sw->poll_left--; } - - if (!sw->poll_left) - sw->poll_time = 0; + + if (sw->poll_left == 1 && !sw->poll_clock) + timer_advance_u64(&sw->poll_timer, TIMER_USEC * 160); + else if (sw->poll_left) + timer_advance_u64(&sw->poll_timer, TIMER_USEC * 5); } static void sw_trigger_timer_over(void *p) { - sw_data *sw = (sw_data *)p; - - sw->trigger_time = 0; } static int sw_parity(uint16_t data) @@ -91,8 +80,8 @@ static void *sw_init() sw_data *sw = (sw_data *)malloc(sizeof(sw_data)); memset(sw, 0, sizeof(sw_data)); - timer_add(sw_timer_over, &sw->poll_time, &sw->poll_time, sw); - timer_add(sw_trigger_timer_over, &sw->trigger_time, &sw->trigger_time, sw); + timer_add(&sw->poll_timer, sw_timer_over, sw, 0); + timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0); return sw; } @@ -112,7 +101,7 @@ static uint8_t sw_read(void *p) if (!JOYSTICK_PRESENT(0)) return 0xff; - if (sw->poll_time) + if (timer_is_enabled(&sw->poll_timer)) { if (sw->poll_clock) temp |= 0x10; @@ -135,7 +124,7 @@ static uint8_t sw_read(void *p) static void sw_write(void *p) { sw_data *sw = (sw_data *)p; - int time_since_last = sw->trigger_time / TIMER_USEC; + int time_since_last = timer_get_remaining_us(&sw->trigger_timer); if (!JOYSTICK_PRESENT(0)) return; @@ -145,7 +134,7 @@ static void sw_write(void *p) if (!sw->poll_left) { sw->poll_clock = 1; - sw->poll_time = TIMER_USEC * 50; + timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 50); if (time_since_last > 9900 && time_since_last < 9940) { @@ -213,10 +202,8 @@ static void sw_write(void *p) } } } - - sw->trigger_time = 0; - - timer_update_outstanding(); + + timer_disable(&sw->trigger_timer); } static int sw_read_axis(void *p, int axis) @@ -231,7 +218,7 @@ static void sw_a0_over(void *p) { sw_data *sw = (sw_data *)p; - sw->trigger_time = TIMER_USEC * 10000; + timer_set_delay_u64(&sw->trigger_timer, TIMER_USEC * 10000); } joystick_if_t joystick_sw_pad = diff --git a/src/keyboard_amstrad.c b/src/keyboard_amstrad.c index e7647f4..31b0eb4 100644 --- a/src/keyboard_amstrad.c +++ b/src/keyboard_amstrad.c @@ -26,6 +26,8 @@ struct uint8_t key_waiting; uint8_t pa; uint8_t pb; + + pc_timer_t send_delay_timer; } keyboard_amstrad; static uint8_t key_queue[16]; @@ -35,7 +37,7 @@ static uint8_t amstrad_systemstat_1, amstrad_systemstat_2; void keyboard_amstrad_poll() { - keybsenddelay += (1000 * TIMER_USEC); + timer_advance_u64(&keyboard_amstrad.send_delay_timer, (1000 * TIMER_USEC)); if (keyboard_amstrad.wantirq) { keyboard_amstrad.wantirq = 0; @@ -77,7 +79,6 @@ void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); speaker_update(); speaker_gated = val & 1; @@ -174,5 +175,5 @@ void keyboard_amstrad_init() keyboard_send = keyboard_amstrad_adddata; keyboard_poll = keyboard_amstrad_poll; - timer_add(keyboard_amstrad_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_amstrad.send_delay_timer, keyboard_amstrad_poll, NULL, 1); } diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 17d9af5..2f06842 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -48,10 +48,12 @@ struct void (*mouse_write)(uint8_t val, void *p); void *mouse_p; - int refresh_time; + pc_timer_t refresh_timer; int refresh; int is_ps2; + + pc_timer_t send_delay_timer; } keyboard_at; static uint8_t key_ctrl_queue[16]; @@ -65,7 +67,7 @@ int mouse_queue_start = 0, mouse_queue_end = 0; void keyboard_at_poll() { - keybsenddelay += (100 * TIMER_USEC); + timer_advance_u64(&keyboard_at.send_delay_timer, (100 * TIMER_USEC)); if (keyboard_at.out_new != -1 && !keyboard_at.last_irq) { @@ -336,9 +338,6 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) case 0x61: ppi.pb = val; - timer_process(); - timer_update_outstanding(); - speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; @@ -626,7 +625,7 @@ void keyboard_at_reset() static void at_refresh(void *p) { keyboard_at.refresh = !keyboard_at.refresh; - keyboard_at.refresh_time += PS2_REFRESH_TIME; + timer_advance_u64(&keyboard_at.refresh_timer, PS2_REFRESH_TIME); } void keyboard_at_init() @@ -641,7 +640,7 @@ void keyboard_at_init() keyboard_at.mouse_p = NULL; keyboard_at.is_ps2 = 0; - timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_at.send_delay_timer, keyboard_at_poll, NULL, 1); } void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) @@ -652,6 +651,6 @@ void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) void keyboard_at_init_ps2() { - timer_add(at_refresh, &keyboard_at.refresh_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_at.refresh_timer, at_refresh, NULL, 1); keyboard_at.is_ps2 = 1; } diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index e86241d..a34d830 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -34,6 +34,8 @@ struct uint8_t params[16]; int mouse_mode; + + pc_timer_t send_delay_timer; } keyboard_olim24; static uint8_t key_queue[16]; @@ -43,7 +45,7 @@ static uint8_t mouse_scancodes[7]; void keyboard_olim24_poll() { - keybsenddelay += (1000 * TIMER_USEC); + timer_advance_u64(&keyboard_olim24.send_delay_timer, (1000 * TIMER_USEC)); //pclog("poll %i\n", keyboard_olim24.wantirq); if (keyboard_olim24.wantirq) { @@ -147,7 +149,6 @@ void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); speaker_update(); speaker_gated = val & 1; @@ -345,5 +346,5 @@ void keyboard_olim24_init() keyboard_send = keyboard_olim24_adddata; keyboard_poll = keyboard_olim24_poll; - timer_add(keyboard_olim24_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_olim24.send_delay_timer, keyboard_olim24_poll, NULL, 1); } diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c index 13f443b..c7119c2 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -32,6 +32,8 @@ struct uint8_t pa; uint8_t pb; + + pc_timer_t send_delay_timer; } keyboard_pcjr; static uint8_t key_queue[16]; @@ -39,8 +41,7 @@ static int key_queue_start = 0, key_queue_end = 0; void keyboard_pcjr_poll() { - keybsenddelay += (220 * TIMER_USEC); - + timer_advance_u64(&keyboard_pcjr.send_delay_timer, (220 * TIMER_USEC)); if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched) { @@ -127,7 +128,6 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv) keyboard_pcjr.pb = val; timer_process(); - timer_update_outstanding(); speaker_update(); speaker_gated = val & 1; @@ -205,5 +205,5 @@ void keyboard_pcjr_init() keyboard_send = keyboard_pcjr_adddata; keyboard_poll = keyboard_pcjr_poll; - timer_add(keyboard_pcjr_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_pcjr.send_delay_timer, keyboard_pcjr_poll, NULL, 1); } diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index a36e707..d2bef2e 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -36,6 +36,8 @@ struct int tandy; int pb2_turbo; + + pc_timer_t send_delay_timer; } keyboard_xt; static uint8_t key_queue[16]; @@ -43,7 +45,7 @@ static int key_queue_start = 0, key_queue_end = 0; void keyboard_xt_poll() { - keybsenddelay += (1000 * TIMER_USEC); + timer_advance_u64(&keyboard_xt.send_delay_timer, (1000 * TIMER_USEC)); if (!(keyboard_xt.pb & 0x40) && romset != ROM_TANDY) return; if (keyboard_xt.wantirq) @@ -124,8 +126,7 @@ void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); - + if (keyboard_xt.pb2_turbo) cpu_set_turbo((val & 4) ? 0 : 1); @@ -236,7 +237,7 @@ void keyboard_xt_init() keyboard_xt.tandy = 0; keyboard_xt.pb2_turbo = (romset == ROM_GENXT || romset == ROM_DTKXT || romset == ROM_AMIXT || romset == ROM_PXXT) ? 1 : 0; - timer_add(keyboard_xt_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_xt.send_delay_timer, keyboard_xt_poll, NULL, 1); } void keyboard_tandy_init() @@ -248,5 +249,5 @@ void keyboard_tandy_init() keyboard_poll = keyboard_xt_poll; keyboard_xt.tandy = (romset != ROM_TANDY) ? 1 : 0; - timer_add(keyboard_xt_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_xt.send_delay_timer, keyboard_xt_poll, NULL, 1); } diff --git a/src/lpt_dac.c b/src/lpt_dac.c index d12f249..7a6fe82 100644 --- a/src/lpt_dac.c +++ b/src/lpt_dac.c @@ -30,8 +30,6 @@ static void dac_write_data(uint8_t val, void *p) { lpt_dac_t *lpt_dac = (lpt_dac_t *)p; - timer_clock(); - if (lpt_dac->is_stereo) { if (lpt_dac->channel) diff --git a/src/lpt_dss.c b/src/lpt_dss.c index 0f53edd..767658a 100644 --- a/src/lpt_dss.c +++ b/src/lpt_dss.c @@ -12,7 +12,7 @@ typedef struct dss_t uint8_t dac_val; - int time; + pc_timer_t timer; int16_t buffer[MAXSOUNDBUFLEN]; int pos; @@ -29,8 +29,6 @@ static void dss_write_data(uint8_t val, void *p) { dss_t *dss = (dss_t *)p; - timer_clock(); - if ((dss->write_idx - dss->read_idx) < 16) { dss->fifo[dss->write_idx & 15] = val; @@ -82,7 +80,7 @@ static void dss_callback(void *p) dss->read_idx++; } - dss->time += (TIMER_USEC * (1000000.0 / 7000.0)); + timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0))); } static void *dss_init() @@ -91,7 +89,7 @@ static void *dss_init() memset(dss, 0, sizeof(dss_t)); sound_add_handler(dss_get_buffer, dss); - timer_add(dss_callback, &dss->time, TIMER_ALWAYS_ENABLED, dss); + timer_add(&dss->timer, dss_callback, dss, 1); return dss; } diff --git a/src/mfm_at.c b/src/mfm_at.c index 1084229..e3ad873 100644 --- a/src/mfm_at.c +++ b/src/mfm_at.c @@ -70,7 +70,7 @@ typedef struct mfm_t uint16_t buffer[256]; int irqstat; - int callback; + pc_timer_t callback_timer; mfm_drive_t drives[2]; } mfm_t; @@ -215,18 +215,14 @@ void mfm_write(uint16_t port, uint8_t val, void *p) // pclog("Restore\n"); mfm->command &= ~0x0f; /*Mask off step rate*/ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; case CMD_SEEK: // pclog("Seek to cylinder %i\n", mfm->cylinder); mfm->command &= ~0x0f; /*Mask off step rate*/ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; default: @@ -239,9 +235,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) if (val & 2) fatal("Read with ECC\n"); mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; case CMD_WRITE: case CMD_WRITE+1: @@ -258,9 +252,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) // pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",mfm->secount,mfm->sector,mfm->cylinder,mfm->head); mfm->command &= ~1; mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200 * IDE_TIME); break; case CMD_FORMAT: @@ -271,24 +263,18 @@ void mfm_write(uint16_t port, uint8_t val, void *p) case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 30*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 30*IDE_TIME); break; case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; default: pclog("Bad MFM command %02X\n", val); mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; } } @@ -297,9 +283,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) case 0x3F6: /* Device control */ if ((mfm->fdisk & 4) && !(val & 4)) { - timer_clock(); - mfm->callback = 500*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 500*IDE_TIME); mfm->reset = 1; mfm->status = STAT_BUSY; // pclog("MFM Reset\n"); @@ -307,9 +291,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) if (val & 4) { /*Drive held in reset*/ - timer_clock(); - mfm->callback = 0; - timer_update_outstanding(); + timer_disable(&mfm->callback_timer); mfm->status = STAT_BUSY; } mfm->fdisk = val; @@ -331,9 +313,7 @@ void mfm_writew(uint16_t port, uint16_t val, void *p) { mfm->pos = 0; mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 6*IDE_TIME); } } @@ -402,9 +382,7 @@ uint16_t mfm_readw(uint16_t port, void *p) { mfm_next_sector(mfm); mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 6*IDE_TIME); } } } @@ -430,7 +408,7 @@ void mfm_callback(void *p) off64_t addr; // pclog("mfm_callback: command=%02x reset=%i\n", mfm->command, mfm->reset); - mfm->callback = 0; + if (mfm->reset) { mfm->status = STAT_READY | STAT_DSC; @@ -562,7 +540,7 @@ void *mfm_init() io_sethandler(0x01f1, 0x0007, mfm_read, NULL, NULL, mfm_write, NULL, NULL, mfm); io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, mfm_write, NULL, NULL, mfm); - timer_add(mfm_callback, &mfm->callback, &mfm->callback, mfm); + timer_add(&mfm->callback_timer, mfm_callback, mfm, 0); return mfm; } diff --git a/src/mfm_xebec.c b/src/mfm_xebec.c index 7c185f2..a60651e 100644 --- a/src/mfm_xebec.c +++ b/src/mfm_xebec.c @@ -51,7 +51,7 @@ typedef struct xebec_t { rom_t bios_rom; - int callback; + pc_timer_t callback_timer; int state; @@ -143,7 +143,7 @@ static uint8_t xebec_read(uint16_t port, void *p) // pclog("Read all data\n"); xebec->status = STAT_BSY; xebec->state = STATE_SENT_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } break; @@ -190,7 +190,7 @@ static void xebec_write(uint16_t port, uint8_t val, void *p) { xebec->status = STAT_BSY; xebec->state = STATE_START_COMMAND; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); // pclog("Command %02x\n", xebec->command[0]); } break; @@ -207,7 +207,7 @@ static void xebec_write(uint16_t port, uint8_t val, void *p) // pclog("Got data\n"); xebec->status = STAT_BSY; xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } break; @@ -314,13 +314,11 @@ static void xebec_callback(void *p) xebec_t *xebec = (xebec_t *)p; mfm_drive_t *drive; - xebec->callback = 0; - xebec->drive_sel = (xebec->command[1] & 0x20) ? 1 : 0; xebec->completion_byte = xebec->drive_sel & 0x20; drive = &xebec->drives[xebec->drive_sel]; - + switch (xebec->command[0]) { case CMD_TEST_DRIVE_READY: @@ -448,7 +446,7 @@ static void xebec_callback(void *p) readflash_set(READFLASH_HDC, xebec->drive_sel); } if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else { xebec->status = STAT_BSY | STAT_IO | STAT_REQ; @@ -468,12 +466,12 @@ static void xebec_callback(void *p) { pclog("CMD_READ_SECTORS out of data!\n"); xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); return; } } xebec->state = STATE_SENT_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } else fatal("Read sectors no DMA! - shouldn't get here\n"); @@ -505,7 +503,7 @@ static void xebec_callback(void *p) xebec->state = STATE_SEND_DATA; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else { xebec->status = STAT_BSY | STAT_IO | STAT_REQ; @@ -535,7 +533,7 @@ static void xebec_callback(void *p) xebec->data_pos = 0; xebec->data_len = 512; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else xebec->status = STAT_BSY | STAT_REQ; break; @@ -552,7 +550,7 @@ static void xebec_callback(void *p) { pclog("CMD_WRITE_SECTORS out of data!\n"); xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); return; } @@ -560,7 +558,7 @@ static void xebec_callback(void *p) } xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } else fatal("Write sectors no DMA! - should never get here\n"); @@ -595,7 +593,7 @@ static void xebec_callback(void *p) { xebec->state = STATE_RECEIVE_DATA; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else xebec->status = STAT_BSY | STAT_REQ; } @@ -653,7 +651,7 @@ static void xebec_callback(void *p) xebec->data_pos = 0; xebec->data_len = 512; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else xebec->status = STAT_BSY | STAT_REQ; break; @@ -671,7 +669,7 @@ static void xebec_callback(void *p) { pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n"); xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); return; } @@ -679,7 +677,7 @@ static void xebec_callback(void *p) } xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } else fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n"); @@ -829,7 +827,7 @@ static void *xebec_init() io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec); - timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec); + timer_add(&xebec->callback_timer, xebec_callback, xebec, 0); return xebec; } @@ -880,7 +878,7 @@ static void *dtc_5150x_init() io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec); - timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec); + timer_add(&xebec->callback_timer, xebec_callback, xebec, 0); return xebec; } diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 9964153..b8bd187 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -7,7 +7,8 @@ typedef struct mouse_serial_t { - int mousepos, mousedelay; + int mousepos; + pc_timer_t mousedelay_timer; int oldb; SERIAL *serial; } mouse_serial_t; @@ -52,14 +53,13 @@ void mouse_serial_rcr(struct SERIAL *serial, void *p) mouse_serial_t *mouse = (mouse_serial_t *)p; mouse->mousepos = -1; - mouse->mousedelay = 5000 * (1 << TIMER_SHIFT); + timer_set_delay_u64(&mouse->mousedelay_timer, TIMER_USEC * 5000); } void mousecallback(void *p) { mouse_serial_t *mouse = (mouse_serial_t *)p; - mouse->mousedelay = 0; if (mouse->mousepos == -1) { mouse->mousepos = 0; @@ -75,7 +75,7 @@ void *mouse_serial_init() mouse->serial = &serial1; serial1.rcr_callback = mouse_serial_rcr; serial1.rcr_callback_p = mouse; - timer_add(mousecallback, &mouse->mousedelay, &mouse->mousedelay, mouse); + timer_add(&mouse->mousedelay_timer, mousecallback, mouse, 0); return mouse; } diff --git a/src/nethandler.c b/src/nethandler.c index dec5c8a..f06ef46 100644 --- a/src/nethandler.c +++ b/src/nethandler.c @@ -91,7 +91,7 @@ static struct static int vlan_handlers_num; -static int vlan_poller_time = 0; +static pc_timer_t vlan_poller_timer; void vlan_handler(void (*poller)(void *p), void *p) //void vlan_handler(int (*can_receive)(void *p), void (*receive)(void *p, const uint8_t *buf, int size), void *p) @@ -106,7 +106,7 @@ void vlan_poller(void *priv) { int c; - vlan_poller_time += (int)((double)TIMER_USEC * (1000000.0 / 8.0 / 1500.0)); + timer_advance_u64(&vlan_poller_timer, (uint64_t)((double)TIMER_USEC * (1000000.0 / 8.0 / 1500.0))); for (c = 0; c < vlan_handlers_num; c++) vlan_handlers[c].poller(vlan_handlers[c].priv); @@ -114,7 +114,7 @@ void vlan_poller(void *priv) void vlan_reset() { - timer_add(vlan_poller, &vlan_poller_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&vlan_poller_timer, vlan_poller, NULL, 1); vlan_handlers_num = 0; } diff --git a/src/nvr.c b/src/nvr.c index 32510aa..fa8c1f4 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -19,9 +19,10 @@ int nvraddr; int nvr_dosave = 0; -static int nvr_onesec_time = 0, nvr_onesec_cnt = 0; +static pc_timer_t nvr_onesec_timer; +static int nvr_onesec_cnt = 0; -static int rtctime; +static pc_timer_t rtc_timer; FILE *nvrfopen(char *fn, char *mode) { @@ -62,10 +63,9 @@ void getnvrtime() void nvr_recalc() { int c; - int newrtctime; + c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT)); - if (rtctime>newrtctime) rtctime=newrtctime; + timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); } void nvr_rtc(void *p) @@ -73,11 +73,11 @@ void nvr_rtc(void *p) int c; if (!(nvrram[RTC_REGA] & RTC_RS)) { - rtctime=0x7fffffff; + timer_disable(&rtc_timer); return; } c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + timer_advance_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); // pclog("RTCtime now %f\n",rtctime); nvrram[RTC_REGC] |= RTC_PF; if (nvrram[RTC_REGB] & RTC_PIE) @@ -98,7 +98,7 @@ int nvr_check_alarm(int nvraddr) return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE); } -int nvr_update_end_count = 0; +pc_timer_t nvr_update_end_timer; void nvr_update_end(void *p) { @@ -130,8 +130,6 @@ void nvr_update_end(void *p) } // pclog("RTC onesec\n"); - - nvr_update_end_count = 0; } void nvr_onesec(void *p) @@ -144,11 +142,11 @@ void nvr_onesec(void *p) nvr_update_status = RTC_UIP; rtc_tick(); - nvr_update_end_count = (int)((244.0 + 1984.0) * TIMER_USEC); + timer_set_delay_u64(&nvr_update_end_timer, (uint64_t)((244.0 + 1984.0) * TIMER_USEC)); } nvr_onesec_cnt = 0; } - nvr_onesec_time += (int)(10000 * TIMER_USEC); + timer_advance_u64(&nvr_onesec_timer, (uint64_t)(10000 * TIMER_USEC)); } void writenvr(uint16_t addr, uint8_t val, void *priv) @@ -174,10 +172,10 @@ void writenvr(uint16_t addr, uint8_t val, void *priv) if (val & RTC_RS) { c = 1 << ((val & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); } else - rtctime = 0x7fffffff; + timer_disable(&rtc_timer); } else { @@ -333,7 +331,7 @@ void loadnvr() nvrram[RTC_REGA] = 6; nvrram[RTC_REGB] = RTC_2412; c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); } void savenvr() { @@ -408,8 +406,8 @@ void savenvr() void nvr_init() { io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL); - timer_add(nvr_rtc, &rtctime, TIMER_ALWAYS_ENABLED, NULL); - timer_add(nvr_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL); - timer_add(nvr_update_end, &nvr_update_end_count, &nvr_update_end_count, NULL); + timer_add(&rtc_timer, nvr_rtc, NULL, 1); + timer_add(&nvr_onesec_timer, nvr_onesec, NULL, 1); + timer_add(&nvr_update_end_timer, nvr_update_end, NULL, 0); } diff --git a/src/nvr_tc8521.c b/src/nvr_tc8521.c index f221c00..6396d30 100644 --- a/src/nvr_tc8521.c +++ b/src/nvr_tc8521.c @@ -11,7 +11,8 @@ #include "config.h" #include "nmi.h" -static int nvr_onesec_time = 0, nvr_onesec_cnt = 0; +static pc_timer_t nvr_onesec_timer; +static int nvr_onesec_cnt = 0; static void tc8521_onesec(void *p) { @@ -21,7 +22,7 @@ static void tc8521_onesec(void *p) tc8521_tick(); nvr_onesec_cnt = 0; } - nvr_onesec_time += (int)(10000 * TIMER_USEC); + timer_advance_u64(&nvr_onesec_timer, 10000 * TIMER_USEC); } void write_tc8521(uint16_t addr, uint8_t val, void *priv) @@ -96,5 +97,5 @@ void tc8521_savenvr() void nvr_tc8521_init() { io_sethandler(0x2C0, 0x10, read_tc8521, NULL, NULL, write_tc8521, NULL, NULL, NULL); - timer_add(tc8521_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&nvr_onesec_timer, tc8521_onesec, NULL, 1); } diff --git a/src/pit.c b/src/pit.c index dd27729..11a9829 100644 --- a/src/pit.c +++ b/src/pit.c @@ -21,7 +21,12 @@ //Tyrian writes 4300 or 17512 int displine; -double PITCONST; +uint64_t PITCONST; +uint64_t CGACONST; +uint64_t MDACONST; +uint64_t VGACONST1, VGACONST2; +uint64_t RTCCONST; + float cpuclock; float isa_timing, bus_timing; @@ -30,23 +35,23 @@ void setpitclock(float clock) { // printf("PIT clock %f\n",clock); cpuclock=clock; - PITCONST=clock/1193182.0; - CGACONST=(clock/(19687503.0/11.0)); - MDACONST=(clock/2032125.0); - VGACONST1=(clock/25175000.0); - VGACONST2=(clock/28322000.0); + PITCONST = (uint64_t)(clock / 1193182.0 * (float)(1ull << 32)); + CGACONST = (uint64_t)((clock / (19687503.0/11.0)) * (float)(1ull << 32)); + MDACONST = (uint64_t)((clock / 2032125.0) * (float)(1ull << 32)); + VGACONST1 = (uint64_t)((clock / 25175000.0) * (float)(1ull << 32)); + VGACONST2 = (uint64_t)((clock / 28322000.0) * (float)(1ull << 32)); isa_timing = clock/8000000.0; bus_timing = clock/(double)cpu_busspeed; video_updatetiming(); // pclog("PITCONST=%f CGACONST=%f\n", PITCONST, CGACONST); // pclog("CPUMULTI=%g\n", ((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed)); - xt_cpu_multi = (int)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)cpu_get_speed()); + xt_cpu_multi = (uint64_t)((14318184.0*(double)(1ull << 32)) / (double)cpu_get_speed()); // pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock); /* if (video_recalctimings) video_recalctimings();*/ - RTCCONST=clock/32768.0; - TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); + RTCCONST = (uint64_t)((clock / 32768.0) * (float)(1ull << 32)); + TIMER_USEC = (uint64_t)((clock / 1000000.0) * (float)(1ull << 32)); device_speed_changed(); } @@ -55,9 +60,9 @@ void setpitclock(float clock) void pit_reset(PIT *pit) { memset(pit, 0, sizeof(PIT)); - pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFF*PITCONST; - pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFF*PITCONST; - pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFF*PITCONST; + pit->l[0] = 0xFFFF; + pit->l[1] = 0xFFFF; + pit->l[2] = 0xFFFF; pit->m[0] = pit->m[1] = pit->m[2] = 0; pit->ctrls[0] = pit->ctrls[1] = pit->ctrls[2] = 0; pit->thit[0]=1; @@ -66,11 +71,6 @@ void pit_reset(PIT *pit) pit->using_timer[0] = pit->using_timer[1] = pit->using_timer[2] = 1; } -void clearpit() -{ - pit.c[0]=(pit.l[0]<<2); -} - float pit_timer0_freq() { if (pit.l[0]) @@ -85,18 +85,52 @@ static void pit_set_out(PIT *pit, int t, int out) pit->out[t] = out; } +static int pit_read_timer(PIT *pit, int t) +{ +// pclog("pit_read_timer: t=%i using_timer=%i m=%i enabled=%i\n", t, pit->using_timer[t], pit->m[t], timer_is_enabled(&pit->timer[t])); + if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t]) && timer_is_enabled(&pit->timer[t])) + { + int read = (int)((timer_get_remaining_u64(&pit->timer[t])) / PITCONST); +// pclog(" read %i %08x %016llx\n", t, read, timer_get_remaining_u64(&pit->timer[t])); + if (pit->m[t] == 2) + read++; + if (read < 0) + read = 0; + if (read > 0x10000) + read = 0x10000; + if (pit->m[t] == 3) + read <<= 1; + return read; + } + if (pit->m[t] == 2) + return pit->count[t] + 1; + return pit->count[t]; +} + +/*Dump timer count back to pit->count[], and disable timer. This should be used + when stopping a PIT timer, to ensure the correct value can be read back.*/ +static void pit_dump_and_disable_timer(PIT *pit, int t) +{ + if (pit->using_timer[t] && timer_is_enabled(&pit->timer[t])) + { + pit->count[t] = pit_read_timer(pit, t); + timer_disable(&pit->timer[t]); + } +} + static void pit_load(PIT *pit, int t) { int l = pit->l[t] ? pit->l[t] : 0x10000; - timer_clock(); + pit->newcount[t] = 0; pit->disabled[t] = 0; -// pclog("pit_load: t=%i l=%x\n", t, l); +// pclog("pit_load: t=%i l=%x m=%i %016llx\n", t, l, pit->m[t], PITCONST); switch (pit->m[t]) { case 0: /*Interrupt on terminal count*/ pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = pit->gate[t]; @@ -108,7 +142,8 @@ static void pit_load(PIT *pit, int t) if (pit->initial[t]) { pit->count[t] = l - 1; - pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)((l - 1) * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -118,12 +153,13 @@ static void pit_load(PIT *pit, int t) if (pit->initial[t]) { pit->count[t] = l; - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } pit->enabled[t] = pit->gate[t]; -// pclog("pit_load: square wave mode c=%x\n", pit->c[t]); +// pclog("pit_load: square wave mode c=%x\n", ); break; case 4: /*Software triggered stobe*/ if (!pit->thit[t] && !pit->initial[t]) @@ -131,7 +167,8 @@ static void pit_load(PIT *pit, int t) else { pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit->thit[t] = 0; } @@ -143,7 +180,9 @@ static void pit_load(PIT *pit, int t) } pit->initial[t] = 0; pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; - timer_update_outstanding(); + if (pit->using_timer[t] && !pit->running[t]) + pit_dump_and_disable_timer(pit, t); + // pclog("pit_load: t=%i running=%i thit=%i enabled=%i m=%i l=%x c=%g gate=%i\n", t, pit.running[t], pit.thit[t], pit.enabled[t], pit.m[t], pit.l[t], pit.c[t], pit.gate[t]); } @@ -161,6 +200,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) { case 0: /*Interrupt on terminal count*/ case 4: /*Software triggered stobe*/ + if (pit->using_timer[t] && !pit->running[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit->enabled[t] = gate; break; case 1: /*Hardware retriggerable one-shot*/ @@ -168,7 +209,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = 1; @@ -178,7 +220,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l - 1; - pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -188,7 +231,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -197,23 +241,21 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) } pit->gate[t] = gate; pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; + if (pit->using_timer[t] && !pit->running[t]) + pit_dump_and_disable_timer(pit, t); // pclog("pit_set_gate: t=%i gate=%i\n", t, gate); } void pit_set_gate(PIT *pit, int t, int gate) { +// pclog("pit_set_gate: t=%i gate=%i\n", t, gate); if (pit->disabled[t]) { pit->gate[t] = gate; return; } - timer_process(); - pit_set_gate_no_timer(pit, t, gate); - - timer_update_outstanding(); -// pclog("pit_set_gate: t=%i gate=%i\n", t, gate); } static void pit_over(PIT *pit, int t) @@ -222,11 +264,12 @@ static void pit_over(PIT *pit, int t) if (pit->disabled[t]) { pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); return; } -// if (!t) pclog("pit_over: t=%i l=%x c=%x %i hit=%i\n", t, pit->l[t], pit.c[t], pit.c[t] >> TIMER_SHIFT, pit.thit[t]); +// if (t == 2) pclog("pit_over: t=%i l=%x c=%llx hit=%i %016llx\n", t, pit->l[t], timer_get_remaining_u64(&pit->timer[t]), pit->thit[t], tsc); switch (pit->m[t]) { case 0: /*Interrupt on terminal count*/ @@ -235,11 +278,13 @@ static void pit_over(PIT *pit, int t) pit_set_out(pit, t, 1); pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); break; case 2: /*Rate generator*/ pit->count[t] += l; - pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit_set_out(pit, t, 1); break; @@ -248,13 +293,15 @@ static void pit_over(PIT *pit, int t) { pit_set_out(pit, t, 0); pit->count[t] += (l >> 1); - pit->c[t] += (int)(((l >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)((l >> 1) * PITCONST)); } else { pit_set_out(pit, t, 1); pit->count[t] += ((l + 1) >> 1); - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST)); } // if (!t) pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); break; @@ -268,13 +315,15 @@ static void pit_over(PIT *pit, int t) { pit->newcount[t] = 0; pit->count[t] += l; - pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); } else { pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); } break; case 5: /*Hardware triggered strove*/ @@ -285,54 +334,20 @@ static void pit_over(PIT *pit, int t) } pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); break; } pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; -} - -int pit_get_timer_0() -{ - int read = (int)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; -//pclog("pit_get_timer_0: t=%i using_timer=%i m=%i\n", 0, pit.using_timer[0], pit.m[0]); - if (pit.m[0] == 2) - read++; - if (read < 0) - read = 0; - if (read > 0x10000) - read = 0x10000; - if (pit.m[0] == 3) - read <<= 1; - return read; -} - -static int pit_read_timer(PIT *pit, int t) -{ - timer_clock(); -// pclog("pit_read_timer: t=%i using_timer=%i m=%i\n", t, pit.using_timer[t], pit.m[t]); - if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t])) - { - int read = (int)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; - if (pit->m[t] == 2) - read++; - if (read < 0) - read = 0; - if (read > 0x10000) - read = 0x10000; - if (pit->m[t] == 3) - read <<= 1; - return read; - } - if (pit->m[t] == 2) - return pit->count[t] + 1; - return pit->count[t]; + if (pit->using_timer[t] && !pit->running[t]) + pit_dump_and_disable_timer(pit, t); } void pit_write(uint16_t addr, uint8_t val, void *p) { PIT *pit = (PIT *)p; int t; -// /*if (val != 0x40) */pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins, pit->gate[0]); +// /*if (val != 0x40) */pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,cpu_state.pc,ins, pit->gate[0]); switch (addr&3) { @@ -456,7 +471,7 @@ uint8_t pit_read(uint16_t addr, void *p) PIT *pit = (PIT *)p; int t; uint8_t temp = 0xff; -// printf("Read PIT %04X ",addr); +// printf("Read PIT %04X\n",addr); switch (addr&3) { case 0: case 1: case 2: /*Timers*/ @@ -537,11 +552,12 @@ void pit_set_using_timer(PIT *pit, int t, int using_timer) timer_process(); if (pit->using_timer[t] && !using_timer) pit->count[t] = pit_read_timer(pit, t); - if (!pit->using_timer[t] && using_timer) - pit->c[t] = (int)((pit->count[t] << TIMER_SHIFT) * PITCONST); + pit->running[t] = pit->enabled[t] && using_timer && !pit->disabled[t]; + if (!pit->using_timer[t] && using_timer && pit->running[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(pit->count[t] * PITCONST)); + else if (!pit->running[t]) + timer_disable(&pit->timer[t]); pit->using_timer[t] = using_timer; - pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; - timer_update_outstanding(); } void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)) @@ -633,9 +649,9 @@ void pit_init() pit.pit_nr[2].nr = 2; pit.pit_nr[0].pit = pit.pit_nr[1].pit = pit.pit_nr[2].pit = &pit; - timer_add(pit_timer_over, &pit.c[0], &pit.running[0], (void *)&pit.pit_nr[0]); - timer_add(pit_timer_over, &pit.c[1], &pit.running[1], (void *)&pit.pit_nr[1]); - timer_add(pit_timer_over, &pit.c[2], &pit.running[2], (void *)&pit.pit_nr[2]); + timer_add(&pit.timer[0], pit_timer_over, (void *)&pit.pit_nr[0], 0); + timer_add(&pit.timer[1], pit_timer_over, (void *)&pit.pit_nr[1], 0); + timer_add(&pit.timer[2], pit_timer_over, (void *)&pit.pit_nr[2], 0); pit_set_out_func(&pit, 0, pit_irq0_timer); pit_set_out_func(&pit, 1, pit_null_timer); @@ -656,7 +672,7 @@ void pit_ps2_init() pit2.pit_nr[0].nr = 0; pit2.pit_nr[0].pit = &pit2; - timer_add(pit_timer_over, &pit2.c[0], &pit2.running[0], (void *)&pit2.pit_nr[0]); + timer_add(&pit2.timer[0], pit_timer_over, (void *)&pit2.pit_nr[0], 0); pit_set_out_func(&pit, 0, pit_irq0_ps2); pit_set_out_func(&pit2, 0, pit_nmi_ps2); diff --git a/src/pit.h b/src/pit.h index 2bed738..b314a93 100644 --- a/src/pit.h +++ b/src/pit.h @@ -1,4 +1,4 @@ -extern double PITCONST; +extern uint64_t PITCONST; void pit_init(); void pit_ps2_init(); void pit_reset(); diff --git a/src/scsi_53c400.c b/src/scsi_53c400.c index ffc3a59..03629eb 100644 --- a/src/scsi_53c400.c +++ b/src/scsi_53c400.c @@ -8,9 +8,8 @@ #include "scsi_53c400.h" #include "timer.h" -#define POLL_TIME_US 10 +#define POLL_TIME_US 1 #define MAX_BYTES_TRANSFERRED_PER_POLL 50 -/*10us poll period with 50 bytes transferred per poll = 5MB/sec*/ typedef struct ncr5380_t { @@ -57,8 +56,7 @@ typedef struct lcs6821n_t int ncr5380_dma_enabled; - int dma_callback; - int dma_enabled; + pc_timer_t dma_timer; int ncr_busy; } lcs6821n_t; @@ -96,13 +94,24 @@ enum DMA_INITIATOR_RECEIVE }; +static void set_dma_enable(lcs6821n_t *scsi, int enable) +{ + if (enable) + { + if (!timer_is_enabled(&scsi->dma_timer)) + timer_set_delay_u64(&scsi->dma_timer, TIMER_USEC * POLL_TIME_US); + } + else + timer_disable(&scsi->dma_timer); +} + static void ncr53c400_dma_changed(ncr5380_t *ncr, int mode, int enable) { lcs6821n_t *scsi = (lcs6821n_t *)ncr->p; scsi->ncr5380_dma_enabled = (mode && enable); - scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); + set_dma_enable(scsi, scsi->ncr5380_dma_enabled && scsi->block_count_loaded); } void ncr5380_reset(ncr5380_t *ncr) @@ -424,7 +433,7 @@ static void lcs6821n_write(uint32_t addr, uint8_t val, void *p) case 0x3981: /*Block counter register*/ scsi->block_count = val; scsi->block_count_loaded = 1; - scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); + set_dma_enable(scsi, scsi->ncr5380_dma_enabled && scsi->block_count_loaded); if (scsi->status_ctrl & CTRL_DATA_DIR) { scsi->buffer_host_pos = 128; @@ -533,7 +542,7 @@ static void ncr53c400_dma_callback(void *p) int bytes_transferred = 0; //pclog("dma_Callback poll\n"); - scsi->dma_callback += POLL_TIME_US; + timer_advance_u64(&scsi->dma_timer, TIMER_USEC * POLL_TIME_US); switch (scsi->ncr.dma_mode) { @@ -600,7 +609,7 @@ static void ncr53c400_dma_callback(void *p) if (!scsi->block_count) { scsi->block_count_loaded = 0; - scsi->dma_enabled = 0; + set_dma_enable(scsi, 0); // scsi->buffer_host_pos = 128; // scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; @@ -665,7 +674,7 @@ static void ncr53c400_dma_callback(void *p) if (!scsi->block_count) { scsi->block_count_loaded = 0; - scsi->dma_enabled = 0; + set_dma_enable(scsi, 0); // output=3; ncr->isr |= STATUS_END_OF_DMA; @@ -717,7 +726,7 @@ static void *scsi_53c400_init(char *bios_fn) scsi_bus_init(&scsi->ncr.bus); - timer_add(ncr53c400_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi); + timer_add(&scsi->dma_timer, ncr53c400_dma_callback, scsi, 0); return scsi; } @@ -757,7 +766,7 @@ static void *scsi_t130b_init(char *bios_fn) scsi_bus_init(&scsi->ncr.bus); - timer_add(ncr53c400_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi); + timer_add(&scsi->dma_timer, ncr53c400_dma_callback, scsi, 0); return scsi; } diff --git a/src/scsi_aha1540.c b/src/scsi_aha1540.c index 9174ffc..f3bb9b6 100644 --- a/src/scsi_aha1540.c +++ b/src/scsi_aha1540.c @@ -126,7 +126,7 @@ typedef struct aha154x_t int bios_cmd_state; - int timer; + pc_timer_t timer; int current_mbo; int current_mbo_is_bios; @@ -2165,7 +2165,7 @@ static void aha154x_callback(void *p) { aha154x_t *scsi = (aha154x_t *)p; - scsi->timer += TIMER_USEC * POLL_TIME_US; + timer_advance_u64(&scsi->timer, TIMER_USEC * POLL_TIME_US); // pclog("poll %i\n", scsi->cmd_state); process_cmd(scsi); @@ -2253,7 +2253,7 @@ static void *scsi_aha1542c_init(char *bios_fn) scsi->ccb_state = CCB_STATE_IDLE; scsi->scsi_state = SCSI_STATE_IDLE; - timer_add(aha154x_callback, &scsi->timer, TIMER_ALWAYS_ENABLED, scsi); + timer_add(&scsi->timer, aha154x_callback, scsi, 1); addr = device_get_config_int("addr"); io_sethandler(addr, 0x0004, @@ -2298,7 +2298,7 @@ static void *scsi_bt545s_init(char *bios_fn) scsi->ccb_state = CCB_STATE_IDLE; scsi->scsi_state = SCSI_STATE_IDLE; - timer_add(aha154x_callback, &scsi->timer, TIMER_ALWAYS_ENABLED, scsi); + timer_add(&scsi->timer, aha154x_callback, scsi, 1); addr = device_get_config_int("addr"); io_sethandler(addr, 0x0004, diff --git a/src/scsi_cd.c b/src/scsi_cd.c index de2363e..5abe1f3 100644 --- a/src/scsi_cd.c +++ b/src/scsi_cd.c @@ -164,7 +164,7 @@ typedef struct scsi_cd_data_t int blocks; int cmd_pos, new_cmd_pos; - int callback; + pc_timer_t callback_timer; int wait_time; scsi_bus_t *bus; @@ -269,21 +269,18 @@ void cd_set_speed(int speed) static void scsi_cd_callback(void *p) { scsi_cd_data_t *data = p; - + if (data->cmd_pos == CMD_POS_WAIT) { data->wait_time--; if (!data->wait_time) { - data->callback = 0; data->cmd_pos = data->new_cmd_pos; scsi_bus_kick(data->bus); } else - data->callback = 1000 * TIMER_USEC; + timer_advance_u64(&data->callback_timer, 1000 * TIMER_USEC); } - else - data->callback = 0; } //#define SECTOR_TIME 13333 /*Time between sectors on 1x drive*/ @@ -397,7 +394,7 @@ static void *scsi_cd_init(scsi_bus_t *bus, int id) memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */ page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; - timer_add(scsi_cd_callback, &data->callback, &data->callback, data); + timer_add(&data->callback_timer, scsi_cd_callback, data, 0); cd_data = data; cd_set_speed(cd_speed); @@ -697,7 +694,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_COMPLETE; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -761,7 +758,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_COMPLETE; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -862,7 +859,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_START_SECTOR; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -875,23 +872,21 @@ static int scsi_cd_command(uint8_t *cdb, void *p) } if (data->cmd_pos == CMD_POS_START_SECTOR) { - uint64_t time = (((uint64_t)SECTOR_TIME * (uint64_t)TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; + uint64_t time = (((uint64_t)SECTOR_TIME * TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_TRANSFER; - - if (time > 0x7fffffffull) + + if (time > (TIMER_USEC * 1000ull)) { - data->wait_time = (int)(time / ((uint64_t)TIMER_USEC * 1000ull)); - data->callback = (int)(time % ((uint64_t)TIMER_USEC * 1000ull));; + data->wait_time = (int)(time / (TIMER_USEC * 1000ull)); + timer_set_delay_u64(&data->callback_timer, time % (TIMER_USEC * 1000ull)); } else { - data->callback = time; + timer_set_delay_u64(&data->callback_timer, time); data->wait_time = 1; } - if (data->callback == 0) - data->callback = 1; return SCSI_PHASE_COMMAND; } @@ -969,7 +964,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_START_SECTOR; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -982,23 +977,21 @@ static int scsi_cd_command(uint8_t *cdb, void *p) } if (data->cmd_pos == CMD_POS_START_SECTOR) { - uint64_t time = (((uint64_t)SECTOR_TIME * (uint64_t)TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; + uint64_t time = (((uint64_t)SECTOR_TIME * TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_TRANSFER; - if (time > 0x7fffffffull) + if (time > (TIMER_USEC * 1000ull)) { - data->wait_time = (int)(time / ((uint64_t)TIMER_USEC * 1000ull)); - data->callback = (int)(time % ((uint64_t)TIMER_USEC * 1000ull));; + data->wait_time = (int)(time / (TIMER_USEC * 1000ull)); + timer_set_delay_u64(&data->callback_timer, time % (TIMER_USEC * 1000ull)); } else { - data->callback = time; + timer_set_delay_u64(&data->callback_timer, time); data->wait_time = 1; } - if (data->callback == 0) - data->callback = 1; return SCSI_PHASE_COMMAND; } @@ -1372,7 +1365,7 @@ atapi_out: data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_COMPLETE; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } diff --git a/src/scsi_hd.c b/src/scsi_hd.c index f314ebf..074bdba 100644 --- a/src/scsi_hd.c +++ b/src/scsi_hd.c @@ -47,7 +47,7 @@ typedef struct scsi_hd_data int hd_id; - int callback; + pc_timer_t callback_timer; scsi_bus_t *bus; } scsi_hd_data; @@ -56,8 +56,6 @@ static void scsi_hd_callback(void *p) { scsi_hd_data *data = p; - data->callback = 0; - if (data->cmd_pos == CMD_POS_WAIT) { data->cmd_pos = data->new_cmd_pos; @@ -80,7 +78,7 @@ static void *scsi_hd_init(scsi_bus_t *bus, int id) data->hd_id = id; data->bus = bus; - timer_add(scsi_hd_callback, &data->callback, &data->callback, data); + timer_add(&data->callback_timer, scsi_hd_callback, data, 0); return data; } @@ -464,7 +462,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_6: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -524,7 +522,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_10: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -585,7 +583,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; @@ -644,7 +642,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; diff --git a/src/scsi_zip.c b/src/scsi_zip.c index 91956e2..8f81700 100644 --- a/src/scsi_zip.c +++ b/src/scsi_zip.c @@ -68,7 +68,7 @@ typedef struct scsi_zip_data int hd_id; - int callback; + pc_timer_t callback_timer; scsi_bus_t *bus; @@ -176,8 +176,6 @@ static void scsi_zip_callback(void *p) { scsi_zip_data *data = p; - data->callback = 0; - if (data->cmd_pos == CMD_POS_WAIT) { data->cmd_pos = data->new_cmd_pos; @@ -194,7 +192,7 @@ static void *scsi_zip_init(scsi_bus_t *bus, int id) data->hd_id = id; data->bus = bus; - timer_add(scsi_zip_callback, &data->callback, &data->callback, data); + timer_add(&data->callback_timer, scsi_zip_callback, data, 0); zip_data = data; return data; @@ -689,7 +687,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_6: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -750,7 +748,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_10: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -819,7 +817,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; @@ -887,7 +885,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; diff --git a/src/serial.c b/src/serial.c index f638e22..2866f7c 100644 --- a/src/serial.c +++ b/src/serial.c @@ -35,7 +35,7 @@ void serial_update_ints(SERIAL *serial) stat = 1; serial->iir = 6; } - else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Recieved data available*/ + else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Received data available*/ { stat = 1; serial->iir = 4; @@ -185,7 +185,7 @@ uint8_t serial_read(uint16_t addr, void *p) serial_update_ints(serial); temp = serial_read_fifo(serial); if (serial->fifo_read != serial->fifo_write) - serial->recieve_delay = 1000 * TIMER_USEC; + timer_set_delay_u64(&serial->receive_timer, 1000 * TIMER_USEC); break; case 1: if (serial->lcr & 0x80) @@ -234,12 +234,10 @@ uint8_t serial_read(uint16_t addr, void *p) return temp; } -void serial_recieve_callback(void *p) +void serial_receive_callback(void *p) { SERIAL *serial = (SERIAL *)p; - serial->recieve_delay = 0; - if (serial->fifo_read != serial->fifo_write) { serial->lsr |= 1; @@ -256,7 +254,7 @@ void serial1_init(uint16_t addr, int irq) serial1.irq = irq; serial1.addr = addr; serial1.rcr_callback = NULL; - timer_add(serial_recieve_callback, &serial1.recieve_delay, &serial1.recieve_delay, &serial1); + timer_add(&serial1.receive_timer, serial_receive_callback, &serial1, 0); } void serial1_set(uint16_t addr, int irq) { @@ -277,7 +275,7 @@ void serial2_init(uint16_t addr, int irq) serial2.irq = irq; serial2.addr = addr; serial2.rcr_callback = NULL; - timer_add(serial_recieve_callback, &serial2.recieve_delay, &serial2.recieve_delay, &serial2); + timer_add(&serial2.receive_timer, serial_receive_callback, &serial2, 0); } void serial2_set(uint16_t addr, int irq) { diff --git a/src/serial.h b/src/serial.h index 930292a..453acbf 100644 --- a/src/serial.h +++ b/src/serial.h @@ -1,3 +1,5 @@ +#include "timer.h" + void serial1_init(uint16_t addr, int irq); void serial2_init(uint16_t addr, int irq); void serial1_set(uint16_t addr, int irq); @@ -25,7 +27,7 @@ typedef struct uint8_t fifo[256]; int fifo_read, fifo_write; - int recieve_delay; + pc_timer_t receive_timer; } SERIAL; void serial_write_fifo(SERIAL *serial, uint8_t dat); diff --git a/src/sound.c b/src/sound.c index cb5820d..a5e7320 100644 --- a/src/sound.c +++ b/src/sound.c @@ -114,7 +114,8 @@ static struct static int sound_handlers_num; -static int sound_poll_time = 0, sound_poll_latch; +static pc_timer_t sound_poll_timer; +static uint64_t sound_poll_latch; int sound_pos_global = 0; int soundon = 1; @@ -226,7 +227,7 @@ void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), vo static int cd_pos = 0; void sound_poll(void *priv) { - sound_poll_time += sound_poll_latch; + timer_advance_u64(&sound_poll_timer, sound_poll_latch); cd_pos++; if (cd_pos == (CD_BUFLEN * 48000) / CD_FREQ) @@ -269,12 +270,12 @@ void sound_poll(void *priv) void sound_speed_changed() { - sound_poll_latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); + sound_poll_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); } void sound_reset() { - timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&sound_poll_timer, sound_poll, NULL, 1); sound_handlers_num = 0; diff --git a/src/sound_ad1848.c b/src/sound_ad1848.c index 1e9f99a..abbbc96 100644 --- a/src/sound_ad1848.c +++ b/src/sound_ad1848.c @@ -71,9 +71,19 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) break; case 9: + if (!ad1848->enable && (val & 0x41) == 0x01) + { + if (ad1848->timer_latch) + timer_advance_u64(&ad1848->timer, ad1848->timer_latch); + else + timer_advance_u64(&ad1848->timer, TIMER_USEC); + } ad1848->enable = ((val & 0x41) == 0x01); if (!ad1848->enable) + { + timer_disable(&ad1848->timer); ad1848->out_l = ad1848->out_r = 0; + } break; case 12: @@ -93,7 +103,7 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) void ad1848_speed_changed(ad1848_t *ad1848) { - ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); + ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); } void ad1848_update(ad1848_t *ad1848) @@ -110,9 +120,9 @@ static void ad1848_poll(void *p) ad1848_t *ad1848 = (ad1848_t *)p; if (ad1848->timer_latch) - ad1848->timer_count += ad1848->timer_latch; + timer_advance_u64(&ad1848->timer, ad1848->timer_latch); else - ad1848->timer_count = TIMER_USEC; + timer_advance_u64(&ad1848->timer, TIMER_USEC); ad1848_update(ad1848); @@ -214,5 +224,5 @@ void ad1848_init(ad1848_t *ad1848) // pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]); } - timer_add(ad1848_poll, &ad1848->timer_count, &ad1848->enable, ad1848); + timer_add(&ad1848->timer, ad1848_poll, ad1848, 0); } diff --git a/src/sound_ad1848.h b/src/sound_ad1848.h index 34b707a..a0c436d 100644 --- a/src/sound_ad1848.h +++ b/src/sound_ad1848.h @@ -19,7 +19,8 @@ typedef struct ad1848_t int freq; - int timer_count, timer_latch; + pc_timer_t timer; + uint64_t timer_latch; int16_t buffer[MAXSOUNDBUFLEN * 2]; int pos; diff --git a/src/sound_adlibgold.c b/src/sound_adlibgold.c index 507751c..a8ce40b 100644 --- a/src/sound_adlibgold.c +++ b/src/sound_adlibgold.c @@ -36,7 +36,7 @@ typedef struct adgold_t int16_t adgold_mma_out[2]; int adgold_mma_intpos[2]; - int adgold_mma_timer_count; + pc_timer_t adgold_mma_timer; struct { @@ -586,9 +586,10 @@ void adgold_timer_poll(void *p) { adgold_t *adgold = (adgold_t *)p; - while (adgold->adgold_mma_timer_count <= 0) - { - adgold->adgold_mma_timer_count += (int)((double)TIMER_USEC * 1.88964); + timer_advance_u64(&adgold->adgold_mma_timer, (uint64_t)((double)TIMER_USEC * 1.88964)); +// while (adgold->adgold_mma_timer_count <= 0) +// { +// adgold->adgold_mma_timer_count += (int)((double)TIMER_USEC * 1.88964); if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/ { adgold->adgold_mma.timer0_count--; @@ -649,7 +650,7 @@ void adgold_timer_poll(void *p) adgold_mma_poll(adgold, 1); } } - } +// } } static void adgold_get_buffer(int32_t *buffer, int len, void *p) @@ -817,7 +818,7 @@ void *adgold_init() /*388/389 are handled by adlib_init*/ io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold); - timer_add(adgold_timer_poll, &adgold->adgold_mma_timer_count, TIMER_ALWAYS_ENABLED, adgold); + timer_add(&adgold->adgold_mma_timer, adgold_timer_poll, adgold, 1); sound_add_handler(adgold_get_buffer, adgold); diff --git a/src/sound_audiopci.c b/src/sound_audiopci.c index 61e1b33..e9d4ef7 100644 --- a/src/sound_audiopci.c +++ b/src/sound_audiopci.c @@ -49,7 +49,8 @@ typedef struct es1371_t uint16_t samp_ct, curr_samp_ct; - int time, latch; + pc_timer_t timer; + uint64_t latch; uint32_t vf, ac; @@ -1077,7 +1078,7 @@ static void es1371_poll(void *p) { es1371_t *es1371 = (es1371_t *)p; - es1371->dac[1].time += es1371->dac[1].latch; + timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch); es1371_update(es1371); @@ -1205,7 +1206,7 @@ static void *es1371_init() es1371->card = pci_add(es1371_pci_read, es1371_pci_write, es1371); - timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371); + timer_add(&es1371->dac[1].timer, es1371_poll, es1371, 1); generate_es1371_filter(); diff --git a/src/sound_gus.c b/src/sound_gus.c index 08b3e5d..20df0c3 100644 --- a/src/sound_gus.c +++ b/src/sound_gus.c @@ -42,13 +42,14 @@ typedef struct gus_t int16_t buffer[2][MAXSOUNDBUFLEN]; int pos; - int samp_timer, samp_latch; + pc_timer_t samp_timer; + uint64_t samp_latch; uint8_t *ram; int irqnext; - int timer_1, timer_2; + pc_timer_t timer_1, timer_2; int irq, dma, irq_midi; int latch_enable; @@ -365,9 +366,9 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); gus->global=val; // printf("GUS voices %i\n",val&31); if (gus->voices < 14) - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); else - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); break; case 0x41: /*DMA*/ @@ -824,7 +825,7 @@ void gus_poll_timer_1(void *p) { gus_t *gus = (gus_t *)p; - gus->timer_1 += (TIMER_USEC * 80); + timer_advance_u64(&gus->timer_1, (uint64_t)(TIMER_USEC * 80)); // pclog("gus_poll_timer_1 %i %i %i %i %02X\n", gustime, gus->t1on, gus->t1, gus->t1l, gus->tctrl); if (gus->t1on) { @@ -859,7 +860,7 @@ void gus_poll_timer_2(void *p) { gus_t *gus = (gus_t *)p; - gus->timer_2 += (TIMER_USEC * 320); + timer_advance_u64(&gus->timer_2, (uint64_t)(TIMER_USEC * 320)); // pclog("pollgus2 %i %i %i %i %02X\n", gustime, gus->t2on, gus->t2, gus->t2l, gus->tctrl); if (gus->t2on) { @@ -919,7 +920,7 @@ void gus_poll_wave(void *p) gus_update(gus); - gus->samp_timer += gus->samp_latch; + timer_advance_u64(&gus->samp_timer, gus->samp_latch); gus->out_l = gus->out_r = 0; @@ -1120,7 +1121,7 @@ void *gus_init() printf("Top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]); gus->voices=14; - gus->samp_timer = gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); gus->t1l = gus->t2l = 0xff; @@ -1128,9 +1129,9 @@ void *gus_init() io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); - timer_add(gus_poll_wave, &gus->samp_timer, TIMER_ALWAYS_ENABLED, gus); - timer_add(gus_poll_timer_1, &gus->timer_1, TIMER_ALWAYS_ENABLED, gus); - timer_add(gus_poll_timer_2, &gus->timer_2, TIMER_ALWAYS_ENABLED, gus); + timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); + timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); + timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); sound_add_handler(gus_get_buffer, gus); @@ -1150,9 +1151,9 @@ void gus_speed_changed(void *p) gus_t *gus = (gus_t *)p; if (gus->voices < 14) - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); else - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); } device_t gus_device = diff --git a/src/sound_opl.c b/src/sound_opl.c index 2a59460..33f6fd9 100644 --- a/src/sound_opl.c +++ b/src/sound_opl.c @@ -106,54 +106,45 @@ void ym3812_timer_set_0(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period * TIMER_USEC * 20; - if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; - opl->timers_enable[0][timer] = period ? 1 : 0; + if (period) + timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[0][timer]); } void ym3812_timer_set_1(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[1][timer] = period * TIMER_USEC * 20; - if (!opl->timers[1][timer]) opl->timers[1][timer] = 1; - opl->timers_enable[1][timer] = period ? 1 : 0; + if (period) + timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[1][timer]); } void ymf262_timer_set(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period * TIMER_USEC * 20; - if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; - opl->timers_enable[0][timer] = period ? 1 : 0; + if (period) + timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[0][timer]); } static void opl_timer_callback00(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[0][0] = 0; opl_timer_over(0, 0); } static void opl_timer_callback01(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[0][1] = 0; opl_timer_over(0, 1); } static void opl_timer_callback10(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[1][0] = 0; opl_timer_over(1, 0); } static void opl_timer_callback11(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[1][1] = 0; opl_timer_over(1, 1); } @@ -161,16 +152,16 @@ void opl2_init(opl_t *opl) { opl_init(ym3812_timer_set_0, opl, 0, 0, 0); opl_init(ym3812_timer_set_1, opl, 1, 0, 0); - timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl); - timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl); - timer_add(opl_timer_callback10, &opl->timers[1][0], &opl->timers_enable[1][0], (void *)opl); - timer_add(opl_timer_callback11, &opl->timers[1][1], &opl->timers_enable[1][1], (void *)opl); + timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); + timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); + timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0); + timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0); } void opl3_init(opl_t *opl, int opl_emu) { opl_init(ymf262_timer_set, opl, 0, 1, opl_emu); - timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl); - timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl); + timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); + timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); } diff --git a/src/sound_opl.h b/src/sound_opl.h index 0728d67..06f5cd7 100644 --- a/src/sound_opl.h +++ b/src/sound_opl.h @@ -4,8 +4,7 @@ typedef struct opl_t { int chip_nr[2]; - int timers[2][2]; - int timers_enable[2][2]; + pc_timer_t timers[2][2]; int16_t filtbuf[2]; diff --git a/src/sound_pas16.c b/src/sound_pas16.c index c736611..7f44fe7 100644 --- a/src/sound_pas16.c +++ b/src/sound_pas16.c @@ -118,7 +118,8 @@ typedef struct pas16_t struct { uint32_t l[3]; - int c[3]; + int c[3]; + pc_timer_t timer[3]; uint8_t m[3]; uint8_t ctrl, ctrls[2]; int wp, rm[3], wm[3]; @@ -398,7 +399,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) { if (!(val & 0x20)) { - if (val & 2) pas16->pit.rl[0] = pas16->pit.c[0] / (PITCONST * (1 << TIMER_SHIFT)); + if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pit.timer[0]) / PITCONST;; if (val & 4) pas16->pit.rl[1] = pas16->pit.c[1]; if (val & 8) pas16->pit.rl[2] = pas16->pit.c[2]; } @@ -413,11 +414,14 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) } if (!(pas16->pit.ctrl & 0x30)) { - pas16->pit.rl[t] = pas16->pit.c[t]; - if (!t) - pas16->pit.rl[t] /= (PITCONST * (1 << TIMER_SHIFT)); - if (pas16->pit.c[t] < 0) - pas16->pit.rl[t] = 0; + if (!t) + pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST; + else + { + pas16->pit.rl[t] = pas16->pit.c[t]; + if (pas16->pit.c[t] < 0) + pas16->pit.rl[t] = 0; + } pas16->pit.ctrl |= 0x30; pas16->pit.rereadlatch[t] = 0; pas16->pit.rm[t] = 3; @@ -431,9 +435,10 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) if (!pas16->pit.rm[t]) { pas16->pit.rm[t] = 3; - pas16->pit.rl[t] = pit.c[t]; - if (!t) - pas16->pit.rl[t] /= (PITCONST * (1 << TIMER_SHIFT)); + if (!t) + pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST; + else + pas16->pit.rl[t] = pas16->pit.c[t]; } pas16->pit.rereadlatch[t] = 1; } @@ -449,7 +454,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.thit[t] = 0; pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); pas16->pit.enable[t] = 1; break; case 2: @@ -457,7 +462,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.thit[t] = 0; pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); pas16->pit.enable[t] = 1; break; case 0: @@ -465,7 +470,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.l[t] |= (val << 8); pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); pas16->pit.thit[t] = 0; pas16->pit.wm[t] = 3; pas16->pit.enable[t] = 1; @@ -481,7 +486,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.l[t] |= 0x10000; pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); } break; } @@ -501,8 +506,8 @@ static uint8_t pas16_pit_in(uint16_t port, void *p) pas16->pit.rereadlatch[t] = 0; if (!t) { - pas16->pit.rl[t] = pas16->pit.c[t] / (PITCONST * (1 << TIMER_SHIFT)); - if ((pas16->pit.c[t] / (PITCONST * (1 << TIMER_SHIFT))) > 65536) + pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST; + if ((timer_get_remaining_u64(&pit.timer[t]) / PITCONST) > 65536) pas16->pit.rl[t] = 0xFFFF; } else @@ -557,13 +562,12 @@ static void pas16_pcm_poll(void *p) if (pas16->pit.m[0] & 2) { if (pas16->pit.l[0]) - pas16->pit.c[0] += (pas16->pit.l[0] * PITCONST * (1 << TIMER_SHIFT)); + timer_advance_u64(&pas16->pit.timer[0], pas16->pit.l[0] * PITCONST); else - pas16->pit.c[0] += (0x10000 * PITCONST * (1 << TIMER_SHIFT)); + timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST); } else { - pas16->pit.c[0] = -1; pas16->pit.enable[0] = 0; } // if (pas16->pcm_ctrl & PAS16_PCM_ENA) @@ -736,7 +740,7 @@ void *pas16_init() io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); - timer_add(pas16_pcm_poll, &pas16->pit.c[0], &pas16->pit.enable[0], pas16); + timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0); sound_add_handler(pas16_get_buffer, pas16); diff --git a/src/sound_ps1.c b/src/sound_ps1.c index fb8a9a5..27c5767 100644 --- a/src/sound_ps1.c +++ b/src/sound_ps1.c @@ -13,7 +13,8 @@ typedef struct ps1_audio_t uint8_t status, ctrl; - int timer_latch, timer_count, timer_enable; + uint64_t timer_latch; + pc_timer_t timer; uint8_t fifo[2048]; int fifo_read_idx, fifo_write_idx; @@ -89,8 +90,10 @@ static void ps1_audio_write(uint16_t port, uint8_t val, void *p) break; case 3: /*Timer reload value*/ ps1->timer_latch = val; - ps1->timer_count = (0xff-val) * TIMER_USEC; - ps1->timer_enable = (val != 0); + if (val) + timer_set_delay_u64(&ps1->timer, (0xff-val) * TIMER_USEC); + else + timer_disable(&ps1->timer); break; case 4: /*Almost empty*/ ps1->fifo_threshold = val * 4; @@ -124,7 +127,7 @@ static void ps1_audio_callback(void *p) ps1->status |= 0x10; /*ADC data ready*/ ps1_update_irq_status(ps1); - ps1->timer_count += ps1->timer_latch * TIMER_USEC; + timer_advance_u64(&ps1->timer, ps1->timer_latch * TIMER_USEC); } static void ps1_audio_get_buffer(int32_t *buffer, int len, void *p) @@ -149,7 +152,7 @@ static void *ps1_audio_init() io_sethandler(0x0200, 0x0001, ps1_audio_read, NULL, NULL, ps1_audio_write, NULL, NULL, ps1); io_sethandler(0x0202, 0x0006, ps1_audio_read, NULL, NULL, ps1_audio_write, NULL, NULL, ps1); - timer_add(ps1_audio_callback, &ps1->timer_count, &ps1->timer_enable, ps1); + timer_add(&ps1->timer, ps1_audio_callback, ps1, 0); sound_add_handler(ps1_audio_get_buffer, ps1); return ps1; diff --git a/src/sound_pssj.c b/src/sound_pssj.c index d692f33..4169c4a 100644 --- a/src/sound_pssj.c +++ b/src/sound_pssj.c @@ -21,7 +21,7 @@ typedef struct pssj_t int amplitude; int irq; - int timer_count; + pc_timer_t timer; int enable; int wave_pos; @@ -46,7 +46,13 @@ static void pssj_write(uint16_t port, uint8_t val, void *p) { case 0: pssj->ctrl = val; + + if (!pssj->enable && ((val & 4) && (pssj->ctrl & 3))) + timer_set_delay_u64(&pssj->timer, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); pssj->enable = (val & 4) && (pssj->ctrl & 3); + if (!pssj->enable) + timer_disable(&pssj->timer); + sn74689_set_extra_divide(&pssj->sn76489, val & 0x40); if (!(val & 8)) pssj->irq = 0; @@ -166,7 +172,7 @@ static void pssj_callback(void *p) pssj->wave_pos = (pssj->wave_pos + 1) & 31; } - pssj->timer_count += (int)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)); + timer_advance_u64(&pssj->timer, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); } static void pssj_get_buffer(int32_t *buffer, int len, void *p) @@ -190,7 +196,7 @@ void *pssj_init() sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); - timer_add(pssj_callback, &pssj->timer_count, &pssj->enable, pssj); + timer_add(&pssj->timer, pssj_callback, pssj, 0); sound_add_handler(pssj_get_buffer, pssj); return pssj; diff --git a/src/sound_sb_dsp.c b/src/sound_sb_dsp.c index df6954a..25de3ee 100644 --- a/src/sound_sb_dsp.c +++ b/src/sound_sb_dsp.c @@ -164,7 +164,9 @@ void sb_irqc(sb_dsp_t *dsp, int irq8) void sb_dsp_reset(sb_dsp_t *dsp) { - dsp->sbenable = dsp->sb_enable_i = 0; + timer_disable(&dsp->output_timer); + timer_disable(&dsp->input_timer); + dsp->sb_command = 0; dsp->sb_8_length = 0xffff; @@ -181,7 +183,6 @@ void sb_dsp_reset(sb_dsp_t *dsp) dsp->sbe2count = 0; dsp->sbreset = 0; - dsp->sbenable = dsp->sb_enable_i = dsp->sb_count_i = 0; dsp->record_pos_read=0; dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN; @@ -219,12 +220,12 @@ void sb_dsp_speed_changed(sb_dsp_t *dsp) if (dsp->sb_timeo < 256) dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo); else - dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); + dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); if (dsp->sb_timei < 256) dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); else - dsp->sblatchi = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); + dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); } void sb_add_data(sb_dsp_t *dsp, uint8_t v) @@ -249,9 +250,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len dsp->sb_8_enable = 1; if (dsp->sb_16_enable && dsp->sb_16_output) dsp->sb_16_enable = 0; dsp->sb_8_output = 1; - timer_process(); - dsp->sbenable = dsp->sb_8_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); dsp->sbleftright = 0; dsp->sbdacpos = 0; // pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); @@ -265,9 +265,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len dsp->sb_16_enable = 1; if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0; dsp->sb_16_output = 1; - timer_process(); - dsp->sbenable = dsp->sb_16_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); // pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len); } } @@ -290,9 +289,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l dsp->sb_8_enable = 1; if (dsp->sb_16_enable && !dsp->sb_16_output) dsp->sb_16_enable = 0; dsp->sb_8_output = 0; - timer_process(); - dsp->sb_enable_i = dsp->sb_8_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); // pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else @@ -311,9 +309,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l dsp->sb_16_enable = 1; if (dsp->sb_8_enable && !dsp->sb_8_output) dsp->sb_8_enable = 0; dsp->sb_16_output = 0; - timer_process(); - dsp->sb_enable_i = dsp->sb_16_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); // pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); @@ -413,15 +410,13 @@ void sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); /*Due to the current implementation, I need to emulate a samplerate, even if this * mode does not imply such samplerate. Position is increased in sb_poll_i*/ - if (dsp->sb_enable_i==0) + if (!timer_is_enabled(&dsp->input_timer)) { dsp->sb_timei = 256 - 22; dsp->sblatchi = TIMER_USEC * 22; temp = 1000000 / 22; dsp->sb_freq = temp; - timer_process(); - dsp->sb_enable_i = 1; - timer_update_outstanding(); + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); } break; case 0x24: /*8-bit single cycle DMA input*/ @@ -444,7 +439,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x41: /*Set output sampling rate*/ case 0x42: /*Set input sampling rate*/ if (dsp->sb_type < SB16) break; - dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); + dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); // pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); temp = dsp->sb_freq; dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); @@ -494,9 +489,8 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x80: /*Pause DAC*/ dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); // pclog("SB pause %04X\n",sb_pausetime); - timer_process(); - dsp->sbenable = 1; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); break; case 0x90: /*High speed 8-bit autoinit DMA output*/ if (dsp->sb_type < SB2) break; @@ -686,10 +680,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sbreset = v; return; case 0xC: /*Command/data write*/ - timer_process(); - dsp->wb_time = TIMER_USEC * 1; - dsp->wb_full = 1; - timer_update_outstanding(); + timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); if (dsp->asp_data_len) { // pclog("ASP data %i\n", dsp->asp_data_len); @@ -740,7 +731,7 @@ uint8_t sb_read(uint16_t a, void *priv) dsp->busy_count = 0; if (dsp->wb_full || (dsp->busy_count & 2)) { - dsp->wb_full = dsp->wb_time; + dsp->wb_full = timer_is_enabled(&dsp->wb_timer); return 0xff; } return 0x7f; @@ -758,9 +749,6 @@ uint8_t sb_read(uint16_t a, void *priv) static void sb_wb_clear(void *p) { - sb_dsp_t *dsp = (sb_dsp_t *)p; - - dsp->wb_time = 0; } void sb_dsp_init(sb_dsp_t *dsp, int type) @@ -774,9 +762,9 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) sb_doreset(dsp); - timer_add(pollsb, &dsp->sbcount, &dsp->sbenable, dsp); - timer_add(sb_poll_i, &dsp->sb_count_i, &dsp->sb_enable_i, dsp); - timer_add(sb_wb_clear, &dsp->wb_time, &dsp->wb_time, dsp); + timer_add(&dsp->output_timer, pollsb, dsp, 0); + timer_add(&dsp->input_timer, sb_poll_i, dsp, 0); + timer_add(&dsp->wb_timer, sb_wb_clear, dsp, 0); /*Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when a set frequency command is sent.*/ @@ -806,7 +794,8 @@ void pollsb(void *p) sb_dsp_t *dsp = (sb_dsp_t *)p; int tempi,ref; - dsp->sbcount += dsp->sblatcho; + timer_advance_u64(&dsp->output_timer, dsp->sblatcho); + // pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { @@ -970,8 +959,13 @@ void pollsb(void *p) if (dsp->sb_8_length < 0) { - if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sb_8_enable = dsp->sbenable=0; + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_autolen; + else + { + dsp->sb_8_enable = 0; + timer_disable(&dsp->output_timer); + } sb_irq(dsp, 1); } } @@ -1022,8 +1016,13 @@ void pollsb(void *p) if (dsp->sb_16_length < 0) { // pclog("16DMA over %i\n",dsp->sb_16_autoinit); - if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else dsp->sb_16_enable = dsp->sbenable = 0; + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_autolen; + else + { + dsp->sb_16_enable = 0; + timer_disable(&dsp->output_timer); + } sb_irq(dsp, 0); } } @@ -1033,7 +1032,8 @@ void pollsb(void *p) if (dsp->sb_pausetime < 0) { sb_irq(dsp, 1); - dsp->sbenable = dsp->sb_8_enable; + if (!dsp->sb_8_enable) + timer_disable(&dsp->output_timer); // pclog("SB pause over\n"); } } @@ -1043,7 +1043,9 @@ void sb_poll_i(void *p) { sb_dsp_t *dsp = (sb_dsp_t *)p; int processed=0; - dsp->sb_count_i += dsp->sblatchi; + + timer_advance_u64(&dsp->input_timer, dsp->sblatchi); + // pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { @@ -1100,8 +1102,13 @@ void sb_poll_i(void *p) if (dsp->sb_8_length < 0) { // pclog("Input DMA over %i\n",sb_8_autoinit); - if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sb_8_enable = dsp->sb_enable_i = 0; + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_autolen; + else + { + dsp->sb_8_enable = 0; + timer_disable(&dsp->input_timer); + } sb_irq(dsp, 1); } processed=1; @@ -1167,8 +1174,13 @@ void sb_poll_i(void *p) if (dsp->sb_16_length < 0) { // pclog("16iDMA over %i\n",sb_16_autoinit); - if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else dsp->sb_16_enable = dsp->sb_enable_i = 0; + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_autolen; + else + { + dsp->sb_16_enable = 0; + timer_disable(&dsp->input_timer); + } sb_irq(dsp, 0); } processed=1; diff --git a/src/sound_sb_dsp.h b/src/sound_sb_dsp.h index 68f260a..cb14af5 100644 --- a/src/sound_sb_dsp.h +++ b/src/sound_sb_dsp.h @@ -47,9 +47,9 @@ typedef struct sb_dsp_t int sbenable, sb_enable_i; - int sbcount, sb_count_i; + pc_timer_t output_timer, input_timer; - int sblatcho, sblatchi; + uint64_t sblatcho, sblatchi; uint16_t sb_addr; @@ -57,7 +57,8 @@ typedef struct sb_dsp_t int asp_data_len; - int wb_time, wb_full; + pc_timer_t wb_timer; + int wb_full; int busy_count; diff --git a/src/timer.c b/src/timer.c index 381562e..a999d4f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,117 +1,134 @@ #include "ibm.h" -/*#include "sound_opl.h" -#include "adlibgold.h" -#include "sound_pas16.h" -#include "sound_sb.h" -#include "sound_sb_dsp.h" -#include "sound_wss.h"*/ #include "timer.h" -#define TIMERS_MAX 32 +uint64_t TIMER_USEC; +uint32_t timer_target; -int TIMER_USEC; +/*Enabled timers are stored in a linked list, with the first timer to expire at + the head.*/ +static pc_timer_t *timer_head = NULL; -static struct +void timer_enable(pc_timer_t *timer) { - int present; - void (*callback)(void *priv); - void *priv; - int *enable; - int *count; -} timers[TIMERS_MAX]; + pc_timer_t *timer_node = timer_head; -int timers_present = 0; -int timer_one = 1; - -int timer_count = 0, timer_latch = 0; -int timer_start = 0; +// pclog("timer->enable %p %i\n", timer, timer->enabled); + if (timer->enabled) + timer_disable(timer); + + if (timer->next || timer->prev) + fatal("timer_enable - timer->next\n"); + + timer->enabled = 1; + + /*List currently empty - add to head*/ + if (!timer_head) + { + timer_head = timer; + timer->next = timer->prev = NULL; + timer_target = timer_head->ts_integer; + return; + } + + timer_node = timer_head; + + while (1) + { + /*Timer expires before timer_node. Add to list in front of timer_node*/ + if (TIMER_LESS_THAN(timer, timer_node)) + { + timer->next = timer_node; + timer->prev = timer_node->prev; + timer_node->prev = timer; + if (timer->prev) + timer->prev->next = timer; + else + { + timer_head = timer; + timer_target = timer_head->ts_integer; + } + return; + } + + /*timer_node is last in the list. Add timer to end of list*/ + if (!timer_node->next) + { + timer_node->next = timer; + timer->prev = timer_node; + return; + } + + timer_node = timer_node->next; + } +} +void timer_disable(pc_timer_t *timer) +{ +// pclog("timer->disable %p\n", timer); + if (!timer->enabled) + return; + + if (!timer->next && !timer->prev && timer != timer_head) + fatal("timer_disable - !timer->next\n"); + + timer->enabled = 0; + + if (timer->prev) + timer->prev->next = timer->next; + else + timer_head = timer->next; + if (timer->next) + timer->next->prev = timer->prev; + timer->prev = timer->next = NULL; +} +static void timer_remove_head() +{ + if (timer_head) + { + pc_timer_t *timer = timer_head; +// pclog("timer_remove_head %p %p\n", timer_head, timer_head->next); + timer_head = timer->next; + timer_head->prev = NULL; + timer->next = timer->prev = NULL; + timer->enabled = 0; + } +} void timer_process() { - int c; - int process = 0; - /*Get actual elapsed time*/ - int diff = timer_latch - timer_count; - int enable[TIMERS_MAX]; + if (!timer_head) + return; - timer_latch = 0; - - for (c = 0; c < timers_present; c++) - { - enable[c] = *timers[c].enable; - if (*timers[c].enable) - { - *timers[c].count = *timers[c].count - diff; - if (*timers[c].count <= 0) - process = 1; - } - } - - if (!process) - return; - - while (1) - { - int lowest = 1, lowest_c; - - for (c = 0; c < timers_present; c++) - { - if (enable[c]) - { - if (*timers[c].count < lowest) - { - lowest = *timers[c].count; - lowest_c = c; - } - } - } - - if (lowest > 0) - break; - - timers[lowest_c].callback(timers[lowest_c].priv); - enable[lowest_c] = *timers[lowest_c].enable; - } -} - -void timer_update_outstanding() -{ - int c; - timer_latch = 0x7fffffff; - for (c = 0; c < timers_present; c++) + while (1) { - if (*timers[c].enable && *timers[c].count < timer_latch) - timer_latch = *timers[c].count; + pc_timer_t *timer = timer_head; + + if (!TIMER_LESS_THAN_VAL(timer, (uint32_t)tsc)) + break; + + timer_remove_head(); + timer->callback(timer->p); } - timer_count = timer_latch = (timer_latch + ((1 << TIMER_SHIFT) - 1)); + + timer_target = timer_head->ts_integer; } void timer_reset() { pclog("timer_reset\n"); - timers_present = 0; - timer_latch = timer_count = 0; -// timer_process(); + timer_target = 0; + tsc = 0; + timer_head = NULL; } -int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv) +void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer) { - if (timers_present < TIMERS_MAX) - { -// pclog("timer_add : adding timer %i\n", timers_present); - timers[timers_present].present = 1; - timers[timers_present].callback = callback; - timers[timers_present].priv = priv; - timers[timers_present].count = count; - timers[timers_present].enable = enable; - timers_present++; - return timers_present - 1; - } - return -1; -} - -void timer_set_callback(int timer, void (*callback)(void *priv)) -{ - timers[timer].callback = callback; + memset(timer, 0, sizeof(pc_timer_t)); + + timer->callback = callback; + timer->p = p; + timer->enabled = 0; + timer->prev = timer->next = NULL; + if (start_timer) + timer_set_delay_u64(timer, 0); } diff --git a/src/timer.h b/src/timer.h index 43722d8..181c1ce 100644 --- a/src/timer.h +++ b/src/timer.h @@ -3,56 +3,140 @@ #include "cpu.h" -extern int timer_start; +/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a + 32:32 fixed point format, with the integer part compared against the TSC. The + fractional part is used when advancing the timestamp to ensure a more accurate + period. + + As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits, + the timer period can only be at most 0x7fffffff CPU cycles. To allow room for + (optimistic) CPU frequency growth, timer period must be at most 1 second. -#define timer_start_period(cycles) \ - timer_start = cycles; + When a timer callback is called, the timer has been disabled. If the timer is + to repeat, the callback must call timer_advance_u64(). This is a change from + the old timer API.*/ +typedef struct pc_timer_t +{ + uint32_t ts_integer; + uint32_t ts_frac; + int enabled; -#define timer_end_period(cycles) \ - do \ - { \ - int diff = timer_start - (cycles); \ - timer_count -= diff; \ - timer_start = cycles; \ - if (timer_count <= 0) \ - { \ - timer_process(); \ - timer_update_outstanding(); \ - } \ - } while (0) + void (*callback)(void *p); + void *p; -#define timer_clock() \ - do \ - { \ - int diff; \ - if (AT) \ - { \ - diff = timer_start - (cycles << TIMER_SHIFT); \ - timer_start = cycles << TIMER_SHIFT; \ - } \ - else \ - { \ - diff = timer_start - (cycles * xt_cpu_multi); \ - timer_start = cycles * xt_cpu_multi; \ - } \ - timer_count -= diff; \ - timer_process(); \ - timer_update_outstanding(); \ - } while (0) + struct pc_timer_t *prev, *next; +} pc_timer_t; +/*Timestamp of nearest enabled timer. CPU emulation must call timer_process() + when TSC matches or exceeds this.*/ +extern uint32_t timer_target; + +/*Enable timer, without updating timestamp*/ +void timer_enable(pc_timer_t *timer); +/*Disable timer*/ +void timer_disable(pc_timer_t *timer); + +/*Process any pending timers*/ void timer_process(); -void timer_update_outstanding(); + +/*Reset timer system*/ void timer_reset(); -int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv); -void timer_set_callback(int timer, void (*callback)(void *priv)); -#define TIMER_ALWAYS_ENABLED &timer_one +/*Add new timer. If start_timer is set, timer will be enabled with a zero + timestamp - this is useful for permanently enabled timers*/ +void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer); -extern int timer_count; -extern int timer_one; +/*1us in 32:32 format*/ +extern uint64_t TIMER_USEC; -#define TIMER_SHIFT 6 +/*True if timer a expires before timer b*/ +#define TIMER_LESS_THAN(a, b) ((int32_t)((a)->ts_integer - (b)->ts_integer) <= 0) +/*True if timer a expires before 32 bit integer timestamp b*/ +#define TIMER_LESS_THAN_VAL(a, b) ((int32_t)((a)->ts_integer - (b)) <= 0) +/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/ +#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t)((a) - (b)) <= 0) -extern int TIMER_USEC; +/*Advance timer by delay, specified in 32:32 format. This should be used to + resume a recurring timer in a callback routine*/ +static inline void timer_advance_u64(pc_timer_t *timer, uint64_t delay) +{ + uint32_t int_delay = delay >> 32; + uint32_t frac_delay = delay & 0xffffffff; + + if ((frac_delay + timer->ts_frac) < frac_delay) + timer->ts_integer++; + timer->ts_frac += frac_delay; + timer->ts_integer += int_delay; + + timer_enable(timer); +} + +/*Set a timer to the given delay, specified in 32:32 format. This should be used + when starting a timer*/ +static inline void timer_set_delay_u64(pc_timer_t *timer, uint64_t delay) +{ + uint32_t int_delay = delay >> 32; + uint32_t frac_delay = delay & 0xffffffff; + + timer->ts_frac = frac_delay; + timer->ts_integer = int_delay + (uint32_t)tsc; + + timer_enable(timer); +} + +/*True if timer currently enabled*/ +static inline int timer_is_enabled(pc_timer_t *timer) +{ + return timer->enabled; +} + +/*Return integer timestamp of timer*/ +static inline uint32_t timer_get_ts_int(pc_timer_t *timer) +{ + return timer->ts_integer; +} + +/*Return remaining time before timer expires, in us. If the timer has already + expired then return 0*/ +static inline uint32_t timer_get_remaining_us(pc_timer_t *timer) +{ + if (timer->enabled) + { + int64_t remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32); + + if (remaining < 0) + return 0; + return remaining / TIMER_USEC; + } + + return 0; +} + +/*Return remaining time before timer expires, in 32:32 timestamp format. If the + timer has already expired then return 0*/ +static inline uint64_t timer_get_remaining_u64(pc_timer_t *timer) +{ + if (timer->enabled) + { + int64_t remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32); + + if (remaining < 0) + return 0; + return remaining; + } + + return 0; +} + +/*Set timer callback function*/ +static inline void timer_set_callback(pc_timer_t *timer, void (*callback)(void *p)) +{ + timer->callback = callback; +} +/*Set timer private data*/ +static inline void timer_set_p(pc_timer_t *timer, void *p) +{ + timer->p = p; +} #endif /*_TIMER_H_*/ diff --git a/src/vid_cga.c b/src/vid_cga.c index 7b616fc..29f6ecb 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -80,8 +80,9 @@ void cga_write(uint32_t addr, uint8_t val, void *p) cga->vram[addr & 0x3fff] = val; if (cga->snow_enabled) { - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; + int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; + cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; + cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } egawrites++; cycles -= 4; @@ -93,8 +94,9 @@ uint8_t cga_read(uint32_t addr, void *p) cycles -= 4; if (cga->snow_enabled) { - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff]; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff]; + int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; + cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; + cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } egareads++; // pclog("CGA_READ %04X\n", addr); @@ -121,8 +123,8 @@ void cga_recalctimings(cga_t *cga) _dispontime *= CGACONST; _dispofftime *= CGACONST; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); - cga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - cga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + cga->dispontime = (uint64_t)_dispontime; + cga->dispofftime = (uint64_t)_dispofftime; } void cga_poll(void *p) @@ -140,7 +142,7 @@ void cga_poll(void *p) if (!cga->linepos) { - cga->vidtime += cga->dispofftime; + timer_advance_u64(&cga->timer, cga->dispofftime); cga->cgastat |= 1; cga->linepos = 1; oldsc = cga->sc; @@ -313,7 +315,7 @@ void cga_poll(void *p) } else { - cga->vidtime += cga->dispontime; + timer_advance_u64(&cga->timer, cga->dispontime); cga->linepos = 0; if (cga->vsynctime) { @@ -434,6 +436,7 @@ void cga_poll(void *p) void cga_init(cga_t *cga) { + timer_add(&cga->timer, cga_poll, cga, 1); cga->composite = 0; } @@ -452,7 +455,8 @@ void *cga_standalone_init() cga->vram = malloc(0x4000); cga_comp_init(cga->revision); - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); + + timer_add(&cga->timer, cga_poll, cga, 1); mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, cga); io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); diff --git a/src/vid_cga.h b/src/vid_cga.h index 7594bf1..b8b73c9 100644 --- a/src/vid_cga.h +++ b/src/vid_cga.h @@ -18,8 +18,8 @@ typedef struct cga_t uint16_t ma, maback; int oddeven; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; diff --git a/src/vid_colorplus.c b/src/vid_colorplus.c index 6a28a23..298cee2 100644 --- a/src/vid_colorplus.c +++ b/src/vid_colorplus.c @@ -119,7 +119,7 @@ void colorplus_poll(void *p) if (!colorplus->cga.linepos) { - colorplus->cga.vidtime += colorplus->cga.dispofftime; + timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime); colorplus->cga.cgastat |= 1; colorplus->cga.linepos = 1; oldsc = colorplus->cga.sc; @@ -215,7 +215,7 @@ void colorplus_poll(void *p) } else { - colorplus->cga.vidtime += colorplus->cga.dispontime; + timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispontime); colorplus->cga.linepos = 0; if (colorplus->cga.vsynctime) { @@ -346,7 +346,7 @@ void *colorplus_init() display_type = device_get_config_int("display_type"); contrast = device_get_config_int("contrast"); - timer_add(colorplus_poll, &colorplus->cga.vidtime, TIMER_ALWAYS_ENABLED, colorplus); + timer_add(&colorplus->cga.timer, colorplus_poll, colorplus, 1); mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, 0, colorplus); io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus); diff --git a/src/vid_compaq_cga.c b/src/vid_compaq_cga.c index d25cc24..f92bd84 100644 --- a/src/vid_compaq_cga.c +++ b/src/vid_compaq_cga.c @@ -25,8 +25,8 @@ void compaq_cga_recalctimings(compaq_cga_t *self) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - self->cga.dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - self->cga.dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + self->cga.dispontime = (uint64_t)_dispontime; + self->cga.dispofftime = (uint64_t)_dispofftime; } void compaq_cga_poll(void *p) @@ -52,7 +52,7 @@ void compaq_cga_poll(void *p) /* We are in Compaq 350-line CGA territory */ if (!self->cga.linepos) { - self->cga.vidtime += self->cga.dispofftime; + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); self->cga.cgastat |= 1; self->cga.linepos = 1; oldsc = self->cga.sc; @@ -194,7 +194,7 @@ void compaq_cga_poll(void *p) } else { - self->cga.vidtime += self->cga.dispontime; + timer_advance_u64(&self->cga.timer, self->cga.dispontime); self->cga.linepos = 0; if (self->cga.vsynctime) { @@ -325,7 +325,7 @@ void *compaq_cga_init() self->cga.vram = malloc(0x4000); - timer_add(compaq_cga_poll, &self->cga.vidtime, TIMER_ALWAYS_ENABLED, self); + timer_add(&self->cga.timer, compaq_cga_poll, self, 1); mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); diff --git a/src/vid_ega.c b/src/vid_ega.c index 8444382..1c134be 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -241,10 +241,10 @@ void ega_recalctimings(ega_t *ega) _dispontime *= crtcconst; _dispofftime *= crtcconst; - ega->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); - pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime / (1 << TIMER_SHIFT), - ega->dispofftime, (float)ega->dispofftime / (1 << TIMER_SHIFT)); + ega->dispontime = (uint64_t)_dispontime; + ega->dispofftime = (uint64_t)_dispofftime; + pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime, + ega->dispofftime, (float)ega->dispofftime); // printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart); // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]); @@ -500,7 +500,7 @@ void ega_poll(void *p) if (!ega->linepos) { - ega->vidtime += ega->dispofftime; + timer_advance_u64(&ega->timer, ega->dispofftime); ega->stat |= 1; ega->linepos = 1; @@ -567,7 +567,7 @@ void ega_poll(void *p) } else { - ega->vidtime += ega->dispontime; + timer_advance_u64(&ega->timer, ega->dispontime); // if (output) printf("Display on %f\n",vidtime); if (ega->dispon) ega->stat &= ~1; @@ -983,6 +983,8 @@ void ega_init(ega_t *ega, int monitor_type, int is_mono) egaswitches = monitor_type & 0xf; ega->vram_limit = 256 * 1024; ega->vrammask = ega->vram_limit-1; + + timer_add(&ega->timer, ega_poll, ega, 1); } void *ega_standalone_init() @@ -1013,8 +1015,8 @@ void *ega_standalone_init() ega->vrammask = ega->vram_limit-1; mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); - timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + return ega; } diff --git a/src/vid_ega.h b/src/vid_ega.h index 4d50622..c955509 100644 --- a/src/vid_ega.h +++ b/src/vid_ega.h @@ -39,8 +39,8 @@ typedef struct ega_t int vres; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; uint8_t scrblank; diff --git a/src/vid_genius.c b/src/vid_genius.c index 088cdf2..50f2e1d 100644 --- a/src/vid_genius.c +++ b/src/vid_genius.c @@ -98,8 +98,8 @@ typedef struct genius_t int enabled; /* Display enabled, 0 or 1 */ int detach; /* Detach cursor, 0 or 1 */ - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int linepos, displine; int vc; @@ -246,8 +246,8 @@ void genius_recalctimings(genius_t *genius) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - genius->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - genius->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + genius->dispontime = (uint64_t)_dispontime; + genius->dispofftime = (uint64_t)_dispofftime; } @@ -462,7 +462,7 @@ void genius_poll(void *p) if (!genius->linepos) { - genius->vidtime += genius->dispofftime; + timer_advance_u64(&genius->timer, genius->dispofftime); genius->cga_stat |= 1; genius->mda_stat |= 1; genius->linepos = 1; @@ -526,7 +526,7 @@ void genius_poll(void *p) genius->cga_stat &= ~1; genius->mda_stat &= ~1; } - genius->vidtime += genius->dispontime; + timer_advance_u64(&genius->timer, genius->dispontime); genius->linepos = 0; if (genius->displine == 1008) @@ -561,7 +561,7 @@ void *genius_init() /* 160k video RAM */ genius->vram = malloc(0x28000); - timer_add(genius_poll, &genius->vidtime, TIMER_ALWAYS_ENABLED, genius); + timer_add(&genius->timer, genius_poll, genius, 1); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in * high-resolution modes) */ diff --git a/src/vid_hercules.c b/src/vid_hercules.c index 899de86..0363cce 100644 --- a/src/vid_hercules.c +++ b/src/vid_hercules.c @@ -17,8 +17,8 @@ typedef struct hercules_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; @@ -110,8 +110,8 @@ void hercules_recalctimings(hercules_t *hercules) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - hercules->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - hercules->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + hercules->dispontime = (uint64_t)_dispontime; + hercules->dispofftime = (uint64_t)_dispofftime; } void hercules_poll(void *p) @@ -128,7 +128,7 @@ void hercules_poll(void *p) if (!hercules->linepos) { //pclog("Poll %i %i\n",vc,sc); - hercules->vidtime += hercules->dispofftime; + timer_advance_u64(&hercules->timer, hercules->dispofftime); hercules->stat |= 1; hercules->linepos = 1; oldsc = hercules->sc; @@ -199,7 +199,7 @@ void hercules_poll(void *p) } else { - hercules->vidtime += hercules->dispontime; + timer_advance_u64(&hercules->timer, hercules->dispontime); if (hercules->dispon) hercules->stat &= ~1; hercules->linepos = 0; @@ -314,7 +314,7 @@ void *hercules_init() hercules->vram = malloc(0x10000); - timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules); + timer_add(&hercules->timer, hercules_poll, hercules, 1); mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, hercules); io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules); diff --git a/src/vid_incolor.c b/src/vid_incolor.c index a393d3e..76fa405 100644 --- a/src/vid_incolor.c +++ b/src/vid_incolor.c @@ -148,8 +148,8 @@ typedef struct incolor_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; @@ -358,8 +358,8 @@ void incolor_recalctimings(incolor_t *incolor) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - incolor->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - incolor->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + incolor->dispontime = (uint64_t)_dispontime; + incolor->dispofftime = (uint64_t)_dispofftime; } @@ -851,7 +851,7 @@ void incolor_poll(void *p) if (!incolor->linepos) { // pclog("InColor poll %i %i\n", incolor->vc, incolor->sc); - incolor->vidtime += incolor->dispofftime; + timer_advance_u64(&incolor->timer, incolor->dispofftime); incolor->stat |= 1; incolor->linepos = 1; oldsc = incolor->sc; @@ -886,7 +886,7 @@ void incolor_poll(void *p) } else { - incolor->vidtime += incolor->dispontime; + timer_advance_u64(&incolor->timer, incolor->dispontime); if (incolor->dispon) incolor->stat &= ~1; incolor->linepos = 0; @@ -1006,7 +1006,7 @@ void *incolor_init() incolor->vram = malloc(0x40000); /* 4 planes of 64k */ - timer_add(incolor_poll, &incolor->vidtime, TIMER_ALWAYS_ENABLED, incolor); + timer_add(&incolor->timer, incolor_poll, incolor, 1); mem_mapping_add(&incolor->mapping, 0xb0000, 0x08000, incolor_read, NULL, NULL, incolor_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, incolor); io_sethandler(0x03b0, 0x0010, incolor_in, NULL, NULL, incolor_out, NULL, NULL, incolor); diff --git a/src/vid_mda.c b/src/vid_mda.c index fdb549e..c54aa85 100644 --- a/src/vid_mda.c +++ b/src/vid_mda.c @@ -17,8 +17,8 @@ typedef struct mda_t uint8_t ctrl, stat; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; @@ -96,8 +96,8 @@ void mda_recalctimings(mda_t *mda) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - mda->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - mda->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + mda->dispontime = (uint64_t)_dispontime; + mda->dispofftime = (uint64_t)_dispofftime; } void mda_poll(void *p) @@ -112,7 +112,7 @@ void mda_poll(void *p) int blink; if (!mda->linepos) { - mda->vidtime += mda->dispofftime; + timer_advance_u64(&mda->timer, mda->dispofftime); mda->stat |= 1; mda->linepos = 1; oldsc = mda->sc; @@ -166,7 +166,7 @@ void mda_poll(void *p) } else { - mda->vidtime += mda->dispontime; + timer_advance_u64(&mda->timer, mda->dispontime); if (mda->dispon) mda->stat&=~1; mda->linepos=0; if (mda->vsynctime) @@ -270,7 +270,7 @@ void *mda_init() mda->vram = malloc(0x1000); - timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda); + timer_add(&mda->timer, mda_poll, mda, 1); mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); diff --git a/src/vid_olivetti_m24.c b/src/vid_olivetti_m24.c index 9e04c0d..dc8a2e3 100644 --- a/src/vid_olivetti_m24.c +++ b/src/vid_olivetti_m24.c @@ -33,7 +33,8 @@ typedef struct m24_t uint16_t ma, maback; int dispon; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; } m24_t; @@ -100,9 +101,11 @@ uint8_t m24_in(uint16_t addr, void *p) void m24_write(uint32_t addr, uint8_t val, void *p) { m24_t *m24 = (m24_t *)p; + int offset = ((timer_get_remaining_u64(&m24->timer) / CGACONST) * 4) & 0xfc; + m24->vram[addr & 0x7FFF]=val; - m24->charbuffer[ ((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; - m24->charbuffer[(((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; + m24->charbuffer[offset] = val; + m24->charbuffer[offset | 1] = val; } uint8_t m24_read(uint32_t addr, void *p) @@ -129,8 +132,8 @@ void m24_recalctimings(m24_t *m24) _dispontime *= CGACONST / 2; _dispofftime *= CGACONST / 2; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); - m24->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - m24->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + m24->dispontime = (uint64_t)_dispontime; + m24->dispofftime = (uint64_t)_dispofftime; } void m24_poll(void *p) @@ -148,7 +151,7 @@ void m24_poll(void *p) if (!m24->linepos) { // pclog("Line poll %i %i %i %i - %04X %i %i %i\n", m24_lineff, vc, sc, vadj, ma, firstline, lastline, displine); - m24->vidtime += m24->dispofftime; + timer_advance_u64(&m24->timer, m24->dispofftime); m24->stat |= 1; m24->linepos = 1; oldsc = m24->sc; @@ -324,7 +327,7 @@ void m24_poll(void *p) else { // pclog("Line poll %i %i %i %i\n", m24_lineff, vc, sc, vadj); - m24->vidtime += m24->dispontime; + timer_advance_u64(&m24->timer, m24->dispontime); if (m24->dispon) m24->stat &= ~1; m24->linepos = 0; m24->lineff ^= 1; @@ -456,7 +459,7 @@ void *m24_init() m24->vram = malloc(0x8000); - timer_add(m24_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); + timer_add(&m24->timer, m24_poll, m24, 1); mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, NULL, 0, m24); io_sethandler(0x03d0, 0x0010, m24_in, NULL, NULL, m24_out, NULL, NULL, m24); return m24; diff --git a/src/vid_pc1512.c b/src/vid_pc1512.c index 0b5f89a..4c94a5a 100644 --- a/src/vid_pc1512.c +++ b/src/vid_pc1512.c @@ -35,7 +35,8 @@ typedef struct pc1512_t int dispon; int blink; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; uint8_t *vram; @@ -153,8 +154,8 @@ static void pc1512_recalctimings(pc1512_t *pc1512) _dispontime *= CGACONST; _dispofftime *= CGACONST; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); - pc1512->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - pc1512->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + pc1512->dispontime = (uint64_t)_dispontime; + pc1512->dispofftime = (uint64_t)_dispofftime; } static void pc1512_poll(void *p) @@ -171,7 +172,7 @@ static void pc1512_poll(void *p) if (!pc1512->linepos) { - pc1512->vidtime += pc1512->dispofftime; + timer_advance_u64(&pc1512->timer, pc1512->dispofftime); pc1512->stat |= 1; pc1512->linepos = 1; oldsc = pc1512->sc; @@ -337,7 +338,7 @@ static void pc1512_poll(void *p) } else { - pc1512->vidtime += pc1512->dispontime; + timer_advance_u64(&pc1512->timer, pc1512->dispontime); if ((pc1512->lastline - pc1512->firstline) == 199) pc1512->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ if (pc1512->dispon) @@ -459,7 +460,7 @@ static void *pc1512_init() pc1512->cgacol = 7; pc1512->cgamode = 0x12; - timer_add(pc1512_poll, &pc1512->vidtime, TIMER_ALWAYS_ENABLED, pc1512); + timer_add(&pc1512->timer, pc1512_poll, pc1512, 1); mem_mapping_add(&pc1512->mapping, 0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL, 0, pc1512); io_sethandler(0x03d0, 0x0010, pc1512_in, NULL, NULL, pc1512_out, NULL, NULL, pc1512); return pc1512; diff --git a/src/vid_pc1640.c b/src/vid_pc1640.c index c01dab3..dd92d57 100644 --- a/src/vid_pc1640.c +++ b/src/vid_pc1640.c @@ -23,7 +23,8 @@ typedef struct pc1640_t rom_t bios_rom; int cga_enabled; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; } pc1640_t; void pc1640_out(uint16_t addr, uint8_t val, void *p) @@ -33,29 +34,36 @@ void pc1640_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3db: - pc1640->cga_enabled = val & 0x40; - if (pc1640->cga_enabled) + if (pc1640->cga_enabled != (val & 0x40)) { - mem_mapping_enable(&pc1640->cga_mapping); - mem_mapping_disable(&pc1640->ega_mapping); - } - else - { - mem_mapping_disable(&pc1640->cga_mapping); - switch (pc1640->ega.gdcreg[6] & 0xc) + pc1640->cga_enabled = val & 0x40; + if (pc1640->cga_enabled) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x20000); - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x10000); - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xb0000, 0x08000); - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xb8000, 0x08000); - break; + timer_disable(&pc1640->ega.timer); + timer_set_delay_u64(&pc1640->cga.timer, 0); + mem_mapping_enable(&pc1640->cga_mapping); + mem_mapping_disable(&pc1640->ega_mapping); + } + else + { + timer_disable(&pc1640->cga.timer); + timer_set_delay_u64(&pc1640->ega.timer, 0); + mem_mapping_disable(&pc1640->cga_mapping); + switch (pc1640->ega.gdcreg[6] & 0xc) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x20000); + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x10000); + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xb0000, 0x08000); + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xb8000, 0x08000); + break; + } } } pclog("3DB write %02X\n", val); @@ -93,23 +101,6 @@ void pc1640_recalctimings(pc1640_t *pc1640) } } -void pc1640_poll(void *p) -{ - pc1640_t *pc1640 = (pc1640_t *)p; - if (pc1640->cga_enabled) - { - pc1640->cga.vidtime = pc1640->vidtime; - cga_poll(&pc1640->cga); - pc1640->vidtime = pc1640->cga.vidtime; - } - else - { - pc1640->ega.vidtime = pc1640->vidtime; - ega_poll(&pc1640->ega); - pc1640->vidtime = pc1640->ega.vidtime; - } -} - void *pc1640_init() { pc1640_t *pc1640 = malloc(sizeof(pc1640_t)); @@ -123,8 +114,8 @@ void *pc1640_init() pc1640->cga.vram = pc1640->ega.vram; pc1640->cga_enabled = 1; cga_init(&pc1640->cga); + timer_disable(&pc1640->ega.timer); - timer_add(pc1640_poll, &pc1640->vidtime, TIMER_ALWAYS_ENABLED, pc1640); mem_mapping_add(&pc1640->cga_mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); mem_mapping_add(&pc1640->ega_mapping, 0, 0, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); io_sethandler(0x03a0, 0x0040, pc1640_in, NULL, NULL, pc1640_out, NULL, NULL, pc1640); diff --git a/src/vid_pc200.c b/src/vid_pc200.c index 06f511d..8f59dfc 100644 --- a/src/vid_pc200.c +++ b/src/vid_pc200.c @@ -111,7 +111,6 @@ void *pc200_init() pc200->cga.vram = malloc(0x4000); cga_init(&pc200->cga); - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); mem_mapping_add(&pc200->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200); return pc200; diff --git a/src/vid_pcjr.c b/src/vid_pcjr.c index fb3643c..5a8fb7c 100644 --- a/src/vid_pcjr.c +++ b/src/vid_pcjr.c @@ -36,7 +36,8 @@ typedef struct pcjr_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; int composite; @@ -168,8 +169,8 @@ void pcjr_recalctimings(pcjr_t *pcjr) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - pcjr->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - pcjr->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + pcjr->dispontime = (uint64_t)_dispontime; + pcjr->dispofftime = (uint64_t)_dispofftime; } void pcjr_poll(void *p) @@ -189,7 +190,7 @@ void pcjr_poll(void *p) { // cgapal[0]=pcjr->col&15; // printf("Firstline %i Lastline %i pcjr->displine %i\n",firstline,lastline,pcjr->displine); - pcjr->vidtime += pcjr->dispofftime; + timer_advance_u64(&pcjr->timer, pcjr->dispofftime); pcjr->stat &= ~1; pcjr->linepos = 1; oldsc = pcjr->sc; @@ -435,7 +436,7 @@ void pcjr_poll(void *p) } else { - pcjr->vidtime += pcjr->dispontime; + timer_advance_u64(&pcjr->timer, pcjr->dispontime); if (pcjr->dispon) pcjr->stat |= 1; pcjr->linepos = 0; @@ -552,7 +553,7 @@ static void *pcjr_video_init() pcjr->memctrl = -1; - timer_add(pcjr_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr); + timer_add(&pcjr->timer, pcjr_poll, pcjr, 1); mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL, NULL, 0, pcjr); io_sethandler(0x03d0, 0x0010, pcjr_in, NULL, NULL, pcjr_out, NULL, NULL, pcjr); return pcjr; diff --git a/src/vid_s3.c b/src/vid_s3.c index 723cb47..e22e6cd 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -1206,7 +1206,7 @@ void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; svga->interlace = svga->crtc[0x42] & 0x20; - svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); switch (svga->crtc[0x67] >> 4) { diff --git a/src/vid_svga.c b/src/vid_svga.c index d94606f..8f774cf 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -433,8 +433,8 @@ void svga_recalctimings(svga_t *svga) _dispontime *= crtcconst; _dispofftime *= crtcconst; - svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + svga->dispontime = (uint64_t)_dispontime; + svga->dispofftime = (uint64_t)_dispofftime; /* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock); printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart); printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]); @@ -478,7 +478,7 @@ void svga_poll(void *p) svga->overlay_oddeven = 1; } - svga->vidtime += svga->dispofftime; + timer_advance_u64(&svga->timer, svga->dispofftime); // if (output) printf("Display off %f\n",vidtime); svga->cgastat |= 1; svga->linepos = 1; @@ -540,7 +540,7 @@ void svga_poll(void *p) else { // pclog("VC %i ma %05X\n", svga->vc, svga->ma); - svga->vidtime += svga->dispontime; + timer_advance_u64(&svga->timer, svga->dispontime); // if (output) printf("Display on %f\n",vidtime); if (svga->dispon) @@ -730,8 +730,8 @@ int svga_init(svga_t *svga, void *p, int memsize, svga->crtc[0] = 63; svga->crtc[6] = 255; - svga->dispontime = 1000 * (1 << TIMER_SHIFT); - svga->dispofftime = 1000 * (1 << TIMER_SHIFT); + svga->dispontime = 1000ull << 32; + svga->dispofftime = 1000ull << 32; svga->bpp = 8; svga->vram = malloc(memsize); svga->vram_max = memsize; @@ -749,7 +749,7 @@ int svga_init(svga_t *svga, void *p, int memsize, mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); - timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); + timer_add(&svga->timer, svga_poll, svga, 1); svga_pri = svga; diff --git a/src/vid_svga.h b/src/vid_svga.h index db5f817..0c44fff 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -63,8 +63,8 @@ typedef struct svga_t uint32_t ma_latch; int bpp; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; uint8_t scrblank; diff --git a/src/vid_t1000.c b/src/vid_t1000.c index def3eff..b97e092 100644 --- a/src/vid_t1000.c +++ b/src/vid_t1000.c @@ -13,6 +13,9 @@ #define T1000_XSIZE 640 #define T1000_YSIZE 200 +/*Very rough estimate*/ +#define VID_CLOCK (double)(651 * 216 * 60) + /* Mapping of attributes to colours */ static uint32_t blue, grey; static uint8_t boldcols[256]; /* Which attributes use the bold font */ @@ -65,7 +68,7 @@ typedef struct t1000_t int internal; /* Using internal display? */ uint8_t attrmap; /* Attribute mapping register */ - int dispontime, dispofftime; + uint64_t dispontime, dispofftime; int linepos, displine; int vc; @@ -176,8 +179,8 @@ static void t1000_recalctimings(t1000_t *t1000) disptime = 651; _dispontime = 640; _dispofftime = disptime - _dispontime; - t1000->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t1000->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + t1000->dispontime = (uint64_t)(_dispontime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); + t1000->dispofftime = (uint64_t)(_dispofftime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); } /* Draw a row of text in 80-column mode */ @@ -446,7 +449,7 @@ static void t1000_poll(void *p) if (!t1000->linepos) { - t1000->cga.vidtime += t1000->dispofftime; + timer_advance_u64(&t1000->cga.timer, t1000->dispofftime); t1000->cga.cgastat |= 1; t1000->linepos = 1; if (t1000->dispon) @@ -493,7 +496,7 @@ static void t1000_poll(void *p) { t1000->cga.cgastat &= ~1; } - t1000->cga.vidtime += t1000->dispontime; + timer_advance_u64(&t1000->cga.timer, t1000->dispontime); t1000->linepos = 0; if (t1000->displine == 200) @@ -635,7 +638,8 @@ static void *t1000_init() /* 16k video RAM */ t1000->vram = malloc(0x4000); - timer_add(t1000_poll, &t1000->cga.vidtime, TIMER_ALWAYS_ENABLED, t1000); + timer_set_callback(&t1000->cga.timer, t1000_poll); + timer_set_p(&t1000->cga.timer, t1000); /* Occupy memory between 0xB8000 and 0xBFFFF */ mem_mapping_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); diff --git a/src/vid_t3100e.c b/src/vid_t3100e.c index c1195b6..8a48450 100644 --- a/src/vid_t3100e.c +++ b/src/vid_t3100e.c @@ -13,6 +13,9 @@ #define T3100E_XSIZE 640 #define T3100E_YSIZE 400 +/*Very rough estimate*/ +#define VID_CLOCK (double)(651 * 416 * 60) + /* T3100e CRTC regs (from the ROM): * * Selecting a character height of 3 seems to be sufficient to convert the @@ -73,7 +76,7 @@ typedef struct t3100e_t int internal; /* Using internal display? */ uint8_t attrmap; /* Attribute mapping register */ - int dispontime, dispofftime; + uint64_t dispontime, dispofftime; int linepos, displine; int vc; @@ -186,8 +189,8 @@ void t3100e_recalctimings(t3100e_t *t3100e) disptime = 651; _dispontime = 640; _dispofftime = disptime - _dispontime; - t3100e->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t3100e->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + t3100e->dispontime = (uint64_t)(_dispontime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); + t3100e->dispofftime = (uint64_t)(_dispofftime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); } @@ -481,7 +484,7 @@ void t3100e_poll(void *p) if (!t3100e->linepos) { - t3100e->cga.vidtime += t3100e->dispofftime; + timer_advance_u64(&t3100e->cga.timer, t3100e->dispofftime); t3100e->cga.cgastat |= 1; t3100e->linepos = 1; if (t3100e->dispon) @@ -528,7 +531,7 @@ void t3100e_poll(void *p) { t3100e->cga.cgastat &= ~1; } - t3100e->cga.vidtime += t3100e->dispontime; + timer_advance_u64(&t3100e->cga.timer, t3100e->dispontime); t3100e->linepos = 0; if (t3100e->displine == 400) @@ -672,7 +675,8 @@ void *t3100e_init() /* 32k video RAM */ t3100e->vram = malloc(0x8000); - timer_add(t3100e_poll, &t3100e->cga.vidtime, TIMER_ALWAYS_ENABLED, t3100e); + timer_set_callback(&t3100e->cga.timer, t3100e_poll); + timer_set_p(&t3100e->cga.timer, t3100e); /* Occupy memory between 0xB8000 and 0xBFFFF */ mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); diff --git a/src/vid_tandy.c b/src/vid_tandy.c index 40a6034..d2cd49a 100644 --- a/src/vid_tandy.c +++ b/src/vid_tandy.c @@ -37,7 +37,8 @@ typedef struct tandy_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; int composite; @@ -186,8 +187,8 @@ void tandy_recalctimings(tandy_t *tandy) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - tandy->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - tandy->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + tandy->dispontime = (uint64_t)_dispontime; + tandy->dispofftime = (uint64_t)_dispofftime; } @@ -208,7 +209,7 @@ void tandy_poll(void *p) { // cgapal[0]=tandy->col&15; // printf("Firstline %i Lastline %i tandy->displine %i\n",firstline,lastline,tandy->displine); - tandy->vidtime += tandy->dispofftime; + timer_advance_u64(&tandy->timer, tandy->dispofftime); tandy->stat |= 1; tandy->linepos = 1; oldsc = tandy->sc; @@ -476,7 +477,7 @@ void tandy_poll(void *p) } else { - tandy->vidtime += tandy->dispontime; + timer_advance_u64(&tandy->timer, tandy->dispontime); if (tandy->dispon) tandy->stat &= ~1; tandy->linepos = 0; @@ -624,7 +625,7 @@ void *tandy_init() tandy->memctrl = -1; tandy->base = (mem_size - 128) * 1024; - timer_add(tandy_poll, &tandy->vidtime, TIMER_ALWAYS_ENABLED, tandy); + timer_add(&tandy->timer, tandy_poll, tandy, 1); mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, NULL, 0, tandy); mem_mapping_add(&tandy->ram_mapping, 0x80000, 0x20000, tandy_ram_read, NULL, NULL, tandy_ram_write, NULL, NULL, NULL, 0, tandy); /*Base 128k mapping is controlled via port 0xA0, so we remove it from the main mapping*/ diff --git a/src/vid_tandysl.c b/src/vid_tandysl.c index 183fa5a..2a521b0 100644 --- a/src/vid_tandysl.c +++ b/src/vid_tandysl.c @@ -35,7 +35,8 @@ typedef struct tandysl_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; } tandysl_t; @@ -249,8 +250,8 @@ static void tandysl_recalctimings(tandysl_t *tandy) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - tandy->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - tandy->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + tandy->dispontime = (uint64_t)_dispontime; + tandy->dispofftime = (uint64_t)_dispofftime; } @@ -272,7 +273,7 @@ static void tandysl_poll(void *p) // pclog("tandy_poll vc=%i sc=%i dispon=%i\n", tandy->vc, tandy->sc, tandy->dispon); // cgapal[0]=tandy->col&15; // printf("Firstline %i Lastline %i tandy->displine %i\n",firstline,lastline,tandy->displine); - tandy->vidtime += tandy->dispofftime; + timer_advance_u64(&tandy->timer, tandy->dispofftime); tandy->stat |= 1; tandy->linepos = 1; oldsc = tandy->sc; @@ -537,7 +538,7 @@ static void tandysl_poll(void *p) } else { - tandy->vidtime += tandy->dispontime; + timer_advance_u64(&tandy->timer, tandy->dispontime); if (tandy->dispon) tandy->stat &= ~1; tandy->linepos = 0; @@ -694,7 +695,7 @@ static void *tandysl_init() tandy->b8000_limit = 0x8000; tandy->planar_ctrl = 4; - timer_add(tandysl_poll, &tandy->vidtime, TIMER_ALWAYS_ENABLED, tandy); + timer_add(&tandy->timer, tandysl_poll, tandy, 1); mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandysl_read, NULL, NULL, tandysl_write, NULL, NULL, NULL, 0, tandy); mem_mapping_add(&tandy->ram_mapping, 0x80000, 0x20000, tandysl_ram_read, NULL, NULL, tandysl_ram_write, NULL, NULL, NULL, 0, tandy); /*Base 128k mapping is controlled via port 0xffe8, so we remove it from the main mapping*/ diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index e40cfa1..bbc5653 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -214,7 +214,7 @@ typedef struct voodoo_t uint16_t dac_pll_regs[16]; float pixel_clock; - int line_time; + uint64_t line_time; voodoo_params_t params; @@ -248,7 +248,7 @@ typedef struct voodoo_t int swap_count; int disp_buffer, draw_buffer; - int timer_count; + pc_timer_t timer; int line; svga_t *svga; @@ -386,7 +386,7 @@ typedef struct voodoo_t int read_time, write_time, burst_time; - int wake_timer; + pc_timer_t wake_timer; uint8_t thefilter[256][256]; // pixel filter, feeding from one or two uint8_t thefilterg[256][256]; // for green @@ -5860,15 +5860,13 @@ static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) #define WAKE_DELAY (TIMER_USEC * 100) static inline void wake_fifo_thread(voodoo_t *voodoo) { - if (!voodoo->wake_timer) + if (!timer_is_enabled(&voodoo->wake_timer)) { /*Don't wake FIFO thread immediately - if we do that it will probably process one word and go back to sleep, requiring it to be woken on almost every write. Instead, wait a short while so that the CPU emulation writes more data so we have more batched-up work.*/ - timer_process(); - voodoo->wake_timer = WAKE_DELAY; - timer_update_outstanding(); + timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY); } } @@ -5881,8 +5879,6 @@ static void voodoo_wake_timer(void *p) { voodoo_t *voodoo = (voodoo_t *)p; - voodoo->wake_timer = 0; - thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } @@ -6126,13 +6122,11 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) break; case SST_vRetrace: - timer_clock(); temp = voodoo->line & 0x1fff; break; case SST_hvRetrace: - timer_clock(); temp = voodoo->line & 0x1fff; - temp |= ((((voodoo->line_time - voodoo->timer_count) * voodoo->h_total) / voodoo->timer_count) << 16) & 0x7ff0000; + temp |= ((((tsc - timer_get_ts_int(&voodoo->timer)) * voodoo->h_total) / (voodoo->line_time >> 32)) << 16) & 0x7ff0000; break; case SST_fbiInit5: @@ -6208,7 +6202,7 @@ static void voodoo_pixelclock_update(voodoo_t *voodoo) voodoo->pixel_clock = t; clock_const = cpuclock / t; - voodoo->line_time = (int)((double)line_length * clock_const * (double)(1 << TIMER_SHIFT)); + voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32)); } static void voodoo_writel(uint32_t addr, uint32_t val, void *p) @@ -7440,9 +7434,9 @@ skip_draw: voodoo->v_retrace = 0; } if (voodoo->line_time) - voodoo->timer_count += voodoo->line_time; + timer_advance_u64(&voodoo->timer, voodoo->line_time); else - voodoo->timer_count += TIMER_USEC * 32; + timer_advance_u64(&voodoo->timer, TIMER_USEC * 32); } static void voodoo_add_status_info(char *s, int max_len, void *p) @@ -7610,7 +7604,7 @@ void *voodoo_card_init() } } - timer_add(voodoo_callback, &voodoo->timer_count, TIMER_ALWAYS_ENABLED, voodoo); + timer_add(&voodoo->timer, voodoo_callback, voodoo, 1); voodoo->svga = svga_get_pri(); voodoo->fbiInit0 = 0; @@ -7627,7 +7621,7 @@ void *voodoo_card_init() if (voodoo->render_threads == 2) voodoo->render_thread[1] = thread_create(render_thread_2, voodoo); - timer_add(voodoo_wake_timer, &voodoo->wake_timer, &voodoo->wake_timer, (void *)voodoo); + timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0); for (c = 0; c < 0x100; c++) { diff --git a/src/vid_wy700.c b/src/vid_wy700.c index 107b134..a19f664 100644 --- a/src/vid_wy700.c +++ b/src/vid_wy700.c @@ -190,8 +190,8 @@ typedef struct wy700_t int enabled; /* Display enabled, 0 or 1 */ int detach; /* Detach cursor, 0 or 1 */ - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int linepos, displine; int vc; @@ -490,8 +490,8 @@ void wy700_recalctimings(wy700_t *wy700) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - wy700->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - wy700->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + wy700->dispontime = (uint64_t)_dispontime; + wy700->dispofftime = (uint64_t)_dispofftime; } @@ -759,7 +759,7 @@ void wy700_poll(void *p) if (!wy700->linepos) { - wy700->vidtime += wy700->dispofftime; + timer_advance_u64(&wy700->timer, wy700->dispofftime); wy700->cga_stat |= 1; wy700->mda_stat |= 1; wy700->linepos = 1; @@ -820,7 +820,7 @@ void wy700_poll(void *p) wy700->cga_stat &= ~1; wy700->mda_stat &= ~1; } - wy700->vidtime += wy700->dispontime; + timer_advance_u64(&wy700->timer, wy700->dispontime); wy700->linepos = 0; if (wy700->displine == 800) @@ -868,7 +868,7 @@ void *wy700_init() /* 128k video RAM */ wy700->vram = malloc(0x20000); - timer_add(wy700_poll, &wy700->vidtime, TIMER_ALWAYS_ENABLED, wy700); + timer_add(&wy700->timer, wy700_poll, wy700, 1); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in * high-resolution modes) */ From 42d62925c3dde8fdc9e163afcc8fd67758def03c Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 2 Aug 2018 22:09:18 +0100 Subject: [PATCH 022/181] Fix compiler warnings on ARM builds. --- src/cdrom-ioctl-linux.c | 15 ++-------- src/codegen_backend_arm.c | 26 ++++++++--------- src/codegen_backend_arm_defs.h | 4 +-- src/codegen_backend_arm_uops.c | 52 +++++++++++++++++----------------- src/fdi2raw.c | 8 +++--- src/vid_voodoo.c | 2 ++ 6 files changed, 50 insertions(+), 57 deletions(-) diff --git a/src/cdrom-ioctl-linux.c b/src/cdrom-ioctl-linux.c index 5876eca..f5299ff 100644 --- a/src/cdrom-ioctl-linux.c +++ b/src/cdrom-ioctl-linux.c @@ -14,7 +14,6 @@ static ATAPI ioctl_atapi; static uint32_t last_block = 0; static uint32_t cdrom_capacity = 0; static int ioctl_inited = 0; -static char ioctl_path[8]; static int tocvalid = 0; static struct cdrom_tocentry toc[256]; static int toc_tracks; @@ -209,7 +208,7 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc) first_track = toc_hdr.cdth_trk0; last_track = toc_hdr.cdth_trk1; //pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track); - memset(btoc, 0, sizeof(btoc)); + memset(btoc, 0, sizeof(struct cdrom_tocentry)); c = 0; for (track = 0; track < 256; track++) @@ -233,8 +232,6 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc) static int ioctl_ready(void) { - long size; - int temp; struct cdrom_tochdr toc_hdr; struct cdrom_tocentry toc_entry; int err; @@ -266,7 +263,6 @@ static int ioctl_ready(void) (toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ) || !tocvalid) { - int track; ioctl_cd_state = CD_STOPPED; tocvalid = read_toc(ioctl_fd, toc); @@ -306,8 +302,6 @@ static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, i static int ioctl_medium_changed(void) { - long size; - int temp; struct cdrom_tochdr toc_hdr; struct cdrom_tocentry toc_entry; int err; @@ -338,15 +332,12 @@ static int ioctl_medium_changed(void) static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf) { - struct cdrom_subchnl sub; uint32_t cdpos = ioctl_cd_pos; int track = get_track_nr(cdpos); uint32_t track_address = toc[track].cdte_addr.msf.frame + (toc[track].cdte_addr.msf.second * 75) + (toc[track].cdte_addr.msf.minute * 75 * 60); - long size; int pos=0; - int err; uint8_t ret; //pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i\n", cdpos, track_address, track); if (ioctl_cd_state == CD_PLAYING) @@ -460,7 +451,6 @@ static void ioctl_readsector_raw(uint8_t *b, int sector) static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) { int len=4; - long size; int c,d; uint32_t temp; uint32_t last_address = 0; @@ -644,7 +634,7 @@ static uint32_t ioctl_size() static int ioctl_status() { - if (!(ioctl_ready) && (cdrom_drive <= 0)) return CD_STATUS_EMPTY; + if (!ioctl_ready() && (cdrom_drive <= 0)) return CD_STATUS_EMPTY; switch(ioctl_cd_state) { @@ -653,6 +643,7 @@ static int ioctl_status() case CD_PAUSED: return CD_STATUS_PAUSED; case CD_STOPPED: + default: return CD_STATUS_STOPPED; } } diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 908c5e1..8b117d5 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -34,7 +34,7 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = static void build_load_routine(codeblock_t *block, int size) { uint32_t *branch_offset; - uint8_t *misaligned_offset; + uint32_t *misaligned_offset; /*In - R0 = address Out - R0 = data, R1 = abrt*/ @@ -73,7 +73,7 @@ static void build_load_routine(codeblock_t *block, int size) *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; if (size != 1) *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; - host_arm_STR_IMM_WB(block, REG_LR, REG_SP, -4); + host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); if (size == 1) host_arm_BL(block, (uintptr_t)readmemb386l); else if (size == 2) @@ -83,15 +83,15 @@ static void build_load_routine(codeblock_t *block, int size) else fatal("build_load_routine - unknown size %i\n", size); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); - host_arm_LDR_IMM_POST(block, REG_PC, REG_SP, 4); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size) { - uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; /*In - R0 = address Out - R0 = data, R1 = abrt*/ @@ -130,7 +130,7 @@ static void build_store_routine(codeblock_t *block, int size) *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; if (size != 1) *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; - host_arm_STR_IMM_WB(block, REG_LR, REG_SP, -4); + host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); if (size == 1) host_arm_BL(block, (uintptr_t)writememb386l); else if (size == 2) @@ -140,7 +140,7 @@ static void build_store_routine(codeblock_t *block, int size) else fatal("build_store_routine - unknown size %i\n", size); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); - host_arm_LDR_IMM_POST(block, REG_PC, REG_SP, 4); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); block_pos = (block_pos + 63) & ~63; } @@ -221,15 +221,15 @@ void codegen_backend_prologue(codeblock_t *block) host_arm_nop(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x20); - host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); while (block_pos != BLOCK_START) host_arm_nop(block); /*Entry code*/ - host_arm_STMDB_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_LR); - host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x20); + host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); + host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); host_arm_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET); host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START); offset = add_literal(block, (uintptr_t)&cpu_state); @@ -238,8 +238,8 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x20); - host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC); + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); if (block_pos > ARM_LITERAL_POOL_OFFSET) fatal("Over limit!\n"); diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 3ec520b..8fb0215 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -11,7 +11,7 @@ #define REG_R10 10 #define REG_R11 11 #define REG_R12 12 -#define REG_SP 13 +#define REG_HOST_SP 13 #define REG_LR 14 #define REG_PC 15 @@ -38,7 +38,7 @@ #define REG_MASK_R10 (1 << REG_R10) #define REG_MASK_R11 (1 << REG_R11) #define REG_MASK_R12 (1 << REG_R12) -#define REG_MASK_SP (1 << REG_SP) +#define REG_MASK_SP (1 << REG_HOST_SP) #define REG_MASK_LR (1 << REG_LR) #define REG_MASK_PC (1 << REG_PC) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 0ec4c75..2e4ed9d 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -233,7 +233,7 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) } else fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); - host_arm_BEQ(block, uop->p); + host_arm_BEQ(block, (uintptr_t)uop->p); return 0; } @@ -299,20 +299,20 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { - host_arm_BL(block, codegen_mem_load_byte); + host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); } else if (REG_IS_W(dest_size)) { - host_arm_BL(block, codegen_mem_load_word); + host_arm_BL(block, (uintptr_t)codegen_mem_load_word); } else if (REG_IS_L(dest_size)) { - host_arm_BL(block, codegen_mem_load_long); + host_arm_BL(block, (uintptr_t)codegen_mem_load_long); } else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); if (REG_IS_B(dest_size)) { host_arm_BFI(block, dest_reg, REG_R0, 0, 8); @@ -341,20 +341,20 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { - host_arm_BL(block, codegen_mem_load_byte); + host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); } else if (REG_IS_W(dest_size)) { - host_arm_BL(block, codegen_mem_load_word); + host_arm_BL(block, (uintptr_t)codegen_mem_load_word); } else if (REG_IS_L(dest_size)) { - host_arm_BL(block, codegen_mem_load_long); + host_arm_BL(block, (uintptr_t)codegen_mem_load_long); } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); if (REG_IS_B(dest_size)) { host_arm_BFI(block, dest_reg, REG_R0, 0, 8); @@ -384,22 +384,22 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) if (REG_IS_B(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, codegen_mem_store_byte); + host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); } else if (REG_IS_W(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, codegen_mem_store_word); + host_arm_BL(block, (uintptr_t)codegen_mem_store_word); } else if (REG_IS_L(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, codegen_mem_store_long); + host_arm_BL(block, (uintptr_t)codegen_mem_store_long); } else fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); return 0; } @@ -413,27 +413,27 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) if (REG_IS_B(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, codegen_mem_store_byte); + host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); } else if (REG_IS_BH(src_size)) { host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8); - host_arm_BL(block, codegen_mem_store_byte); + host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); } else if (REG_IS_W(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, codegen_mem_store_word); + host_arm_BL(block, (uintptr_t)codegen_mem_store_word); } else if (REG_IS_L(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, codegen_mem_store_long); + host_arm_BL(block, (uintptr_t)codegen_mem_store_long); } else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); return 0; } @@ -444,9 +444,9 @@ static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, codegen_mem_store_byte); + host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); return 0; } @@ -456,9 +456,9 @@ static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, codegen_mem_store_word); + host_arm_BL(block, (uintptr_t)codegen_mem_store_word); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); return 0; } @@ -468,9 +468,9 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, codegen_mem_store_long); + host_arm_BL(block, (uintptr_t)codegen_mem_store_long); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); return 0; } @@ -908,7 +908,7 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { if (stack_offset >= 0 && stack_offset < 4096) - host_arm_LDR_IMM(block, host_reg, REG_SP, stack_offset); + host_arm_LDR_IMM(block, host_reg, REG_HOST_SP, stack_offset); else fatal("codegen_direct_read_32 - not in range\n"); } @@ -916,7 +916,7 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { if (stack_offset >= 0 && stack_offset < 4096) - host_arm_STR_IMM(block, host_reg, REG_SP, stack_offset); + host_arm_STR_IMM(block, host_reg, REG_HOST_SP, stack_offset); else fatal("codegen_direct_write_32 - not in range\n"); } diff --git a/src/fdi2raw.c b/src/fdi2raw.c index 8dfd819..8573f7e 100644 --- a/src/fdi2raw.c +++ b/src/fdi2raw.c @@ -1628,7 +1628,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi randval = rand(); if (randval < (RAND_MAX / 2)) { if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (3 * (int64_t)RAND_MAX / 8)) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; @@ -1637,7 +1637,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi } else { randval -= RAND_MAX / 2; if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (3 * (int64_t)RAND_MAX / 8)) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; @@ -1663,7 +1663,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi randval = rand(); if (randval < (RAND_MAX / 2)) { if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (3 * (int64_t)RAND_MAX / 8)) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; @@ -1672,7 +1672,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi } else { randval -= RAND_MAX / 2; if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) + if (randval <= (3 * (int64_t)RAND_MAX / 8)) randval = (2 * randval) - (RAND_MAX /4); else randval = (4 * randval) - RAND_MAX; diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index bbc5653..8a1d76c 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -2659,7 +2659,9 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood int dither = params->fbzMode & FBZ_DITHER;*/ int texels; int c; +#ifndef NO_CODEGEN uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y); +#endif int y_diff = SLI_ENABLED ? 2 : 1; if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || From a9d46d95ec573c7534b3fb44331d25e41f79905a Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 2 Aug 2018 22:09:57 +0100 Subject: [PATCH 023/181] Use MOVW/MOVT to load immediates on ARM instead of a literal pool. --- src/codegen_backend_arm.h | 4 +-- src/codegen_backend_arm_ops.c | 24 +++++-------- src/codegen_backend_arm_uops.c | 65 +++++----------------------------- 3 files changed, 19 insertions(+), 74 deletions(-) diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index fd63315..1446594 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -2,7 +2,7 @@ #define BLOCK_SIZE 0x1000 #define BLOCK_MASK 0x0fff -#define BLOCK_START 32 +#define BLOCK_START 64 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff @@ -13,7 +13,7 @@ /*#define BLOCK_EXIT_OFFSET 0x7f0*/ #define BLOCK_GPF_OFFSET 0 -#define BLOCK_EXIT_OFFSET 16 +#define BLOCK_EXIT_OFFSET 32 #define ARM_LITERAL_POOL_OFFSET 0xf000 diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index f7772ae..b32556e 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -201,8 +201,7 @@ void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); } } @@ -226,8 +225,7 @@ void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); } } @@ -314,8 +312,7 @@ void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0); } } @@ -338,8 +335,7 @@ void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm) } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0); } } @@ -358,8 +354,7 @@ void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); } } @@ -457,8 +452,7 @@ void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); } } @@ -519,8 +513,7 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); } } @@ -544,8 +537,7 @@ void host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) } else { - int offset = add_literal(block, imm); - host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_TEMP, imm); host_arm_TST_REG(block, src_reg, REG_TEMP); } } diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 2e4ed9d..17f216b 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -49,8 +49,7 @@ static inline int in_range(void *addr, void *base) void host_arm_call(codeblock_t *block, void *dst_addr) { - int offset = add_literal(block, (uintptr_t)dst_addr); - host_arm_LDR_IMM(block, REG_R3, REG_LITERAL, offset); + host_arm_MOV_IMM(block, REG_R3, (uintptr_t)dst_addr); host_arm_BLX(block, REG_R3); } @@ -240,54 +239,22 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; - - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); - else - { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, REG_ARG0, REG_LITERAL, offset); - } + host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); return 0; } static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; - - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); - else - { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, REG_ARG1, REG_LITERAL, offset); - } + host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); return 0; } static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; - - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); - else - { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, REG_ARG2, REG_LITERAL, offset); - } + host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); return 0; } static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; - - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); - else - { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, REG_ARG3, REG_LITERAL, offset); - } + host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); return 0; } @@ -519,15 +486,7 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size)) { - uint32_t arm_imm; - - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, dest_reg, uop->imm_data); - else - { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, dest_reg, REG_LITERAL, offset); - } + host_arm_MOV_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size)) { @@ -551,8 +510,7 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) { - int offset = add_literal(block, (uintptr_t)uop->p); - host_arm_LDR_IMM(block, uop->dest_reg_a_real, REG_LITERAL, offset); + host_arm_MOV_IMM(block, uop->dest_reg_a_real, (uintptr_t)uop->p); return 0; } @@ -650,13 +608,8 @@ static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { uint32_t arm_imm; - if (get_arm_imm(uop->imm_data, &arm_imm)) - host_arm_MOV_IMM(block, REG_R0, uop->imm_data); - else - { - int offset = add_literal(block, uop->imm_data); - host_arm_LDR_IMM(block, REG_R0, REG_LITERAL, offset); - } + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + if (in_range(uop->p, &cpu_state)) host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); else From 4ada3382b41d881ef737db06d83cd7eecaf13590 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 3 Aug 2018 19:44:35 +0100 Subject: [PATCH 024/181] Fix inconsistent size of ide_fn array. --- src/esdi_at.c | 2 +- src/hdd_esdi.c | 2 +- src/mfm_at.c | 2 +- src/mfm_xebec.c | 2 +- src/scsi_hd.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/esdi_at.c b/src/esdi_at.c index c14ab7a..9002502 100644 --- a/src/esdi_at.c +++ b/src/esdi_at.c @@ -50,7 +50,7 @@ #define CMD_SET_PARAMETERS 0x91 #define CMD_READ_PARAMETERS 0xec -extern char ide_fn[4][512]; +extern char ide_fn[7][512]; typedef struct esdi_drive_t { diff --git a/src/hdd_esdi.c b/src/hdd_esdi.c index 9465af1..6eb239a 100644 --- a/src/hdd_esdi.c +++ b/src/hdd_esdi.c @@ -26,7 +26,7 @@ #define CMD_ADAPTER 0 -extern char ide_fn[4][512]; +extern char ide_fn[7][512]; typedef struct esdi_t { diff --git a/src/mfm_at.c b/src/mfm_at.c index e3ad873..83fee43 100644 --- a/src/mfm_at.c +++ b/src/mfm_at.c @@ -46,7 +46,7 @@ #define CMD_DIAGNOSE 0x90 #define CMD_SET_PARAMETERS 0x91 -extern char ide_fn[4][512]; +extern char ide_fn[7][512]; typedef struct mfm_drive_t { diff --git a/src/mfm_xebec.c b/src/mfm_xebec.c index a60651e..51cec9e 100644 --- a/src/mfm_xebec.c +++ b/src/mfm_xebec.c @@ -23,7 +23,7 @@ #define XEBEC_TIME (2000 * TIMER_USEC) -extern char ide_fn[4][512]; +extern char ide_fn[7][512]; enum { diff --git a/src/scsi_hd.c b/src/scsi_hd.c index 074bdba..bf6412e 100644 --- a/src/scsi_hd.c +++ b/src/scsi_hd.c @@ -8,7 +8,7 @@ #include "scsi_hd.h" #include "timer.h" -extern char ide_fn[4][512]; +extern char ide_fn[7][512]; #define BUFFER_SIZE (256*1024) From f1df9be8f693eb90834b23389572391263a27aa9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 5 Aug 2018 16:24:15 +0100 Subject: [PATCH 025/181] Added recompiled versions of JMP, CALL, RET, PUSH and POP. --- src/Makefile.am | 3 +- src/codegen.c | 6 +- src/codegen.h | 2 +- src/codegen_backend_arm64_ops.c | 15 +++ src/codegen_backend_arm64_ops.h | 3 + src/codegen_backend_arm64_uops.c | 41 +++++- src/codegen_backend_arm_ops.c | 14 ++ src/codegen_backend_arm_ops.h | 3 + src/codegen_backend_arm_uops.c | 66 +++++++++- src/codegen_backend_x86-64_defs.h | 9 ++ src/codegen_backend_x86-64_ops.c | 63 ++++++++- src/codegen_backend_x86-64_ops.h | 7 +- src/codegen_backend_x86-64_uops.c | 36 +++++- src/codegen_backend_x86_ops.c | 58 +++++++++ src/codegen_backend_x86_ops.h | 6 + src/codegen_backend_x86_uops.c | 31 ++++- src/codegen_ir_defs.h | 17 ++- src/codegen_ops.c | 79 ++++++++++-- src/codegen_ops.h | 4 +- src/codegen_ops_arith.c | 46 +++---- src/codegen_ops_helpers.h | 43 +++++++ src/codegen_ops_jump.c | 130 +++++++++++++++++++ src/codegen_ops_jump.h | 12 ++ src/codegen_ops_logic.c | 36 +++--- src/codegen_ops_misc.c | 101 +++++++++++++++ src/codegen_ops_misc.h | 2 + src/codegen_ops_mov.c | 18 +-- src/codegen_ops_stack.c | 207 ++++++++++++++++++++++++++++++ src/codegen_ops_stack.h | 32 +++++ src/codegen_reg.c | 20 +++ src/codegen_reg.h | 26 +++- src/ibm.h | 2 +- src/x86seg.c | 28 ++-- 33 files changed, 1063 insertions(+), 103 deletions(-) create mode 100644 src/codegen_ops_helpers.h create mode 100644 src/codegen_ops_jump.c create mode 100644 src/codegen_ops_jump.h create mode 100644 src/codegen_ops_misc.c create mode 100644 src/codegen_ops_misc.h create mode 100644 src/codegen_ops_stack.c create mode 100644 src/codegen_ops_stack.h diff --git a/src/Makefile.am b/src/Makefile.am index 18da9e0..d465e30 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,8 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_arith.c codegen_ops_logic.c codegen_ops_mov.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ +cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_arith.c codegen_ops_jump.c codegen_ops_logic.c \ +codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ diff --git a/src/codegen.c b/src/codegen.c index 5bd88bb..8a06538 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -238,14 +238,14 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin return op_ea_seg; } -x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset) { cpu_mod = (fetchdat >> 6) & 3; cpu_reg = (fetchdat >> 3) & 7; cpu_rm = fetchdat & 7; if (op_32 & 0x200) - return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, 0); + return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset); return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc); } @@ -320,7 +320,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t { case 0x0f: op_table = x86_dynarec_opcodes_0f; - recomp_op_table = NULL;//recomp_opcodes_0f; + recomp_op_table = recomp_opcodes_0f; over = 1; break; diff --git a/src/codegen.h b/src/codegen.h index 9503b25..7136330 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -264,7 +264,7 @@ void codegen_set_op32(); void codegen_flush(); void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); struct ir_data_t; -x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32); +x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset); void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 0a6b8f8..cd57fd7 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -56,11 +56,13 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BFI (0x0cc << 22) #define OPCODE_LDR_IMM_W (0x2e5 << 22) #define OPCODE_LDRB_IMM_W (0x0e5 << 22) +#define OPCODE_LDRH_IMM (0x1e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) #define OPCODE_STR_IMM_Q (0x3e4 << 22) #define OPCODE_STRB_IMM (0x0e4 << 22) +#define OPCODE_STRH_IMM (0x1e4 << 22) #define OPCODE_UBFX (0x14c << 22) #define OPCODE_ADD_LSL (0x058 << 21) @@ -104,6 +106,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) #define OFFSET12_B(offset) (offset << 10) +#define OFFSET12_H(offset) ((offset >> 1) << 10) #define OFFSET12_W(offset) ((offset >> 2) << 10) #define OFFSET12_Q(offset) ((offset >> 3) << 10) @@ -428,6 +431,12 @@ void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int off codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } +void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_h(offset)) + fatal("host_arm64_LDRH_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); +} void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); @@ -557,6 +566,12 @@ void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offs codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } +void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_h(offset)) + fatal("host_arm64_STRH_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); +} void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 9fc993d..0bdbcb4 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -41,6 +41,7 @@ void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offs void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); +void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); @@ -69,6 +70,7 @@ void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offse void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); +void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); @@ -85,6 +87,7 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); #define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) #define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) +#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1)) #define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) #define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7)) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index cd9f180..7b2ead8 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -208,6 +208,23 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int offset = add_literal_q(block, (uintptr_t)uop->p); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + + host_arm64_LDR_LITERAL_X(block, REG_ARG1, offset); + host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); + host_arm64_call(block, (void *)loadseg); + host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -731,6 +748,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, @@ -776,7 +794,13 @@ void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_8 - not in range\n"); } - +void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +{ + if (in_range12_h((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_16 - not in range\n"); +} void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) @@ -792,7 +816,13 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) else fatal("codegen_direct_write_8 - not in range\n"); } - +void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_h((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_16 - not in range\n"); +} void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) @@ -809,6 +839,13 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) fatal("codegen_direct_write_ptr - not in range\n"); } +void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (in_range12_h(stack_offset)) + host_arm64_LDRH_IMM(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); +} void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { if (in_range12_w(stack_offset)) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index b32556e..83817a7 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -71,7 +71,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BFI 0xe7c00010 #define OPCODE_BLX 0xe12fff30 +#define OPCODE_LDRH_IMM 0xe1d000b0 #define OPCODE_LDRH_REG 0xe19000b0 +#define OPCODE_STRH_IMM 0xe1c000b0 #define OPCODE_STRH_REG 0xe18000b0 #define OPCODE_UADD8 0xe6500f90 #define OPCODE_UADD16 0xe6500f10 @@ -210,6 +212,10 @@ void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr { codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { @@ -398,6 +404,10 @@ void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int of codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } +void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_LDRH_IMM | Rn(addr_reg) | Rd(dst_reg) | LDRH_IMM(offset)); +} void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg) { codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg)); @@ -494,6 +504,10 @@ void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int of codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } +void host_arm_STRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +{ + codegen_addlong(block, COND_AL | OPCODE_STRH_IMM | Rn(addr_reg) | Rd(dst_reg) | STRH_IMM(offset)); +} void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg) { codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 31aee46..dd74e0d 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -1,6 +1,7 @@ void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); #define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0) void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); @@ -38,6 +39,7 @@ void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset #define host_arm_LDRB_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDRB_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0) void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift); +void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset); void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg); void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm); @@ -65,6 +67,7 @@ void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset #define host_arm_STRB_REG(block, src_reg, addr_reg, offset_reg) host_arm_STRB_REG_LSL(block, src_reg, addr_reg, offset_reg, 0) void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift); +void host_arm_STRH_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset); void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg); void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 17f216b..7a98bf1 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -47,6 +47,15 @@ static inline int in_range(void *addr, void *base) return 1; } +static inline int in_range_h(void *addr, void *base) +{ + int diff = (uintptr_t)addr - (uintptr_t)base; + + if (diff < 0 || diff > 255) + return 0; + return 1; +} + void host_arm_call(codeblock_t *block, void *dst_addr) { host_arm_MOV_IMM(block, REG_R3, (uintptr_t)dst_addr); @@ -89,6 +98,11 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); @@ -258,6 +272,22 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + host_arm_UXTH(block, REG_ARG0, src_reg, 0); + host_arm_MOV_IMM(block, REG_ARG1, (uint32_t)uop->p); + host_arm_call(block, loadseg); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -606,8 +636,6 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { - uint32_t arm_imm; - host_arm_MOV_IMM(block, REG_R0, uop->imm_data); if (in_range(uop->p, &cpu_state)) @@ -670,8 +698,8 @@ static int codegen_SUB(codeblock_t *block, uop_t *uop) } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); } else @@ -789,6 +817,8 @@ const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, @@ -826,6 +856,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; +void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +{ + if (in_range_h(p, &cpu_state)) + host_arm_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + { + host_arm_MOV_IMM(block, REG_R3, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_LDRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); + } +} void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { if (in_range(p, &cpu_state)) @@ -841,7 +881,16 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) else fatal("codegen_direct_write_8 - not in range\n"); } - +void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +{ + if (in_range_h(p, &cpu_state)) + host_arm_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + { + host_arm_MOV_IMM(block, REG_R3, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_STRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); + } +} void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { if (in_range(p, &cpu_state)) @@ -858,6 +907,13 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) fatal("codegen_direct_write_ptr - not in range\n"); } +void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (stack_offset >= 0 && stack_offset < 256) + host_arm_LDRH_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); +} void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { if (stack_offset >= 0 && stack_offset < 4096) diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index 706c70d..ee6df65 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -1,3 +1,12 @@ +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 + #define REG_EAX 0 #define REG_ECX 1 #define REG_EDX 2 diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 9262541..bbd80ff 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -395,6 +395,28 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) codegen_addlong(block, (uint32_t)(uintptr_t)p); } } +void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOV16_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } + else if (offset < (1ull << 32)) + { + codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + } +} void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -459,6 +481,27 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_r codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ } +void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOV16_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } + else if (offset < (1ull << 32)) + { + codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } + else + { + fatal("host_x86_MOV16_REG_ABS - out of range\n"); + } +} void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -501,10 +544,28 @@ void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int ba codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ } +void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); +} void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); + fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); if (offset >= -128 && offset < 127) { diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 4b67841..9bf56c5 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -34,6 +34,7 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg); @@ -41,12 +42,16 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale); +void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); +void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); + void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data); void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data); void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data); @@ -69,8 +74,6 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); - void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index d0efa31..a0e1c1f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -191,6 +191,27 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +#if WIN64 + host_x86_MOV16_REG_REG(block, REG_CX, src_reg); + host_x86_MOV64_REG_IMM(block, REG_EDX, (uint64_t)uop->p); +#else + host_x86_MOV16_REG_REG(block, REG_DI, src_reg); + host_x86_MOV64_REG_IMM(block, REG_ESI, (uint64_t)uop->p); +#endif + host_x86_CALL(block, (void *)loadseg); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -595,6 +616,8 @@ const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, @@ -632,6 +655,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; +void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV16_REG_ABS(block, host_reg, p); +} void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); @@ -641,7 +668,10 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { host_x86_MOV8_ABS_REG(block, p, host_reg); } - +void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV16_ABS_REG(block, p, host_reg); +} void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { host_x86_MOV32_ABS_REG(block, p, host_reg); @@ -652,6 +682,10 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) host_x86_MOV64_ABS_REG(block, p, host_reg); } +void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); +} void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index bcc16ef..49ca53b 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -364,6 +364,20 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) codegen_addlong(block, (uint32_t)p); } } +void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t)p); + } +} void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -393,6 +407,20 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ } +void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t)p); + } +} void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -420,6 +448,21 @@ void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } +void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); +} void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { if (offset >= -128 && offset < 127) @@ -435,6 +478,21 @@ void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); } +void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } + else + codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + else + fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); +} void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) { if (offset >= -128 && offset < 127) diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 8d3df16..d4f4d66 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -34,20 +34,24 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg); void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg); +void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift); void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); @@ -58,6 +62,8 @@ void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +#define host_x86_MOV16_STACK_REG(block, offset, src_reg) host_x86_MOV16_BASE_OFFSET_REG(block, REG_ESP, offset, src_reg) + void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index c5f3f80..e88f81d 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -194,6 +194,22 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t)uop->p); + host_x86_CALL(block, loadseg); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -593,6 +609,8 @@ const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, @@ -630,6 +648,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; +void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV16_REG_ABS(block, host_reg, p); +} void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); @@ -639,7 +661,10 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { host_x86_MOV8_ABS_REG(block, p, host_reg); } - +void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV16_ABS_REG(block, p, host_reg); +} void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { host_x86_MOV32_ABS_REG(block, p, host_reg); @@ -650,6 +675,10 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); +} void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index a864468..dc92a77 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -39,6 +39,8 @@ #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) #define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) +/*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/ +#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER) /*UOP_MOV_PTR - dest_reg = p*/ #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) /*UOP_MOV_IMM - dest_reg = imm_data*/ @@ -250,6 +252,15 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p uop->imm_data = imm; } +static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; +} + static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) { uop_t *uop = uop_alloc(ir); @@ -281,6 +292,8 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) +#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) + #define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) #define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg) #define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) @@ -297,13 +310,15 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) - +void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); +void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 6fc74b4..867108f 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -3,52 +3,103 @@ #include "codegen_ir.h" #include "codegen_ops.h" #include "codegen_ops_arith.h" +#include "codegen_ops_jump.h" #include "codegen_ops_logic.h" +#include "codegen_ops_misc.h" #include "codegen_ops_mov.h" +#include "codegen_ops_stack.h" RecompOpFn recomp_opcodes[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, NULL, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16, /*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, ropPOP_W, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, + +/*c0*/ NULL, NULL, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32, +/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, +/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, ropPOP_L, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, + +/*c0*/ NULL, NULL, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32 +}; + + +RecompOpFn recomp_opcodes_0f[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL, +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, +/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, NULL, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, NULL, NULL, +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, -/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL, +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, +/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/src/codegen_ops.h b/src/codegen_ops.h index 1229ce4..1534a38 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -8,8 +8,8 @@ struct ir_data_t; typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); extern RecompOpFn recomp_opcodes[512]; -/*extern RecompOpFn recomp_opcodes_0f[512]; -extern RecompOpFn recomp_opcodes_d8[512]; +extern RecompOpFn recomp_opcodes_0f[512]; +/*extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; extern RecompOpFn recomp_opcodes_da[512]; extern RecompOpFn recomp_opcodes_db[512]; diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index 9e7fb43..7331afc 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -64,7 +64,7 @@ uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); @@ -95,7 +95,7 @@ uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); @@ -127,7 +127,7 @@ uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); @@ -158,7 +158,7 @@ uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); @@ -190,7 +190,7 @@ uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); @@ -220,7 +220,7 @@ uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); @@ -291,7 +291,7 @@ uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); @@ -322,7 +322,7 @@ uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); @@ -353,7 +353,7 @@ uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); @@ -384,7 +384,7 @@ uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); @@ -415,7 +415,7 @@ uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); @@ -445,7 +445,7 @@ uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV(ir, IREG_flags_op1, IREG_temp0); @@ -515,7 +515,7 @@ uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); @@ -546,7 +546,7 @@ uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); @@ -578,7 +578,7 @@ uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); @@ -609,7 +609,7 @@ uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); @@ -641,7 +641,7 @@ uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); @@ -671,7 +671,7 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); @@ -751,7 +751,7 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch uint8_t imm; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); if ((fetchdat & 0x38) == 0x38) /*CMP*/ codegen_check_seg_read(block, ir, target_seg); else @@ -880,7 +880,7 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint16_t imm; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); if ((fetchdat & 0x38) == 0x38) /*CMP*/ codegen_check_seg_read(block, ir, target_seg); else @@ -1008,7 +1008,7 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t imm; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); if ((fetchdat & 0x38) == 0x38) /*CMP*/ codegen_check_seg_read(block, ir, target_seg); else @@ -1137,7 +1137,7 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint16_t imm; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); if ((fetchdat & 0x38) == 0x38) /*CMP*/ codegen_check_seg_read(block, ir, target_seg); else @@ -1266,7 +1266,7 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); if ((fetchdat & 0x38) == 0x38) /*CMP*/ codegen_check_seg_read(block, ir, target_seg); else diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h new file mode 100644 index 0000000..55cb99a --- /dev/null +++ b/src/codegen_ops_helpers.h @@ -0,0 +1,43 @@ +static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) +{ + if (stack32) + { + if (offset) + { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset); + return IREG_eaaddr; + } + else + return IREG_ESP; + } + else + { + if (offset) + { + uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset); + uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W); + return IREG_eaaddr; + } + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + return IREG_eaaddr; + } + } + +} + +static inline void ADD_SP(ir_data_t *ir, int offset) +{ + if (stack32) + uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset); + else + uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset); +} +static inline void SUB_SP(ir_data_t *ir, int offset) +{ + if (stack32) + uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset); + else + uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); +} diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c new file mode 100644 index 0000000..8ae6816 --- /dev/null +++ b/src/codegen_ops_jump.c @@ -0,0 +1,130 @@ +#include "ibm.h" + +#include "x86.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_helpers.h" +#include "codegen_ops_mov.h" + +uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + + uop_MOV_IMM(ir, IREG_pc, op_pc+1+offset); + return -1; +} +uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_pc, op_pc+2+offset); + return -1; +} +uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = fastreadl(cs + op_pc); + + uop_MOV_IMM(ir, IREG_pc, op_pc+4+offset); + return -1; +} + +uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); + uint16_t ret_addr = op_pc + 2; + uint16_t dest_addr = ret_addr + offset; + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr); + SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + + return -1; +} +uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = fastreadl(cs + op_pc); + uint32_t ret_addr = op_pc + 4; + uint32_t dest_addr = ret_addr + offset; + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr); + SUB_SP(ir, 4); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + + return -1; +} + +uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 2); + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + + return -1; +} +uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 4); + + return -1; +} + +uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t offset = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 2+offset); + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + + return -1; +} +uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t offset = fastreadw(cs + op_pc); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 4+offset); + + return -1; +} diff --git a/src/codegen_ops_jump.h b/src/codegen_ops_jump.h new file mode 100644 index 0000000..ee6a591 --- /dev/null +++ b/src/codegen_ops_jump.h @@ -0,0 +1,12 @@ +uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index df4a3de..a9f2021 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -56,7 +56,7 @@ uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); @@ -84,7 +84,7 @@ uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); @@ -113,7 +113,7 @@ uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); @@ -141,7 +141,7 @@ uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); @@ -170,7 +170,7 @@ uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); @@ -198,7 +198,7 @@ uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); @@ -261,7 +261,7 @@ uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); @@ -289,7 +289,7 @@ uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); @@ -318,7 +318,7 @@ uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); @@ -346,7 +346,7 @@ uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); @@ -375,7 +375,7 @@ uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); @@ -403,7 +403,7 @@ uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); @@ -466,7 +466,7 @@ uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); @@ -494,7 +494,7 @@ uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); @@ -523,7 +523,7 @@ uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); @@ -551,7 +551,7 @@ uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); @@ -580,7 +580,7 @@ uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); @@ -608,7 +608,7 @@ uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c new file mode 100644 index 0000000..524fc71 --- /dev/null +++ b/src/codegen_ops_misc.c @@ -0,0 +1,101 @@ +#include "ibm.h" + +#include "x86.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_helpers.h" +#include "codegen_ops_misc.h" + +uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg, sp_reg; + + if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + src_reg = IREG_16(fetchdat & 7); + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0_W; + } + + switch (fetchdat & 0x38) + { + case 0x10: /*CALL*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1); + SUB_SP(ir, 2); + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; + + case 0x20: /*JMP*/ + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; + + case 0x30: /*PUSH*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); + SUB_SP(ir, 2); + return -1; + } + return 0; +} + +uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg, sp_reg; + + if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + src_reg = IREG_32(fetchdat & 7); + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0; + } + + switch (fetchdat & 0x38) + { + case 0x10: /*CALL*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1); + SUB_SP(ir, 4); + uop_MOV(ir, IREG_pc, src_reg); + return -1; + + case 0x20: /*JMP*/ + uop_MOV(ir, IREG_pc, src_reg); + return -1; + + case 0x30: /*PUSH*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); + SUB_SP(ir, 4); + return -1; + } + return 0; +} diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h new file mode 100644 index 0000000..b86c246 --- /dev/null +++ b/src/codegen_ops_misc.h @@ -0,0 +1,2 @@ +uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 7073578..69fa5f7 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -48,7 +48,7 @@ uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); } @@ -69,7 +69,7 @@ uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); } @@ -90,7 +90,7 @@ uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); } @@ -111,7 +111,7 @@ uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } @@ -132,7 +132,7 @@ uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } @@ -153,7 +153,7 @@ uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t x86seg *target_seg; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } @@ -268,7 +268,7 @@ uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ else { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); imm = fastreadb(cs + op_pc + 1); uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); @@ -291,7 +291,7 @@ uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ else { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); imm = fastreadw(cs + op_pc + 1); uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); @@ -314,7 +314,7 @@ uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ else { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); imm = fastreadl(cs + op_pc + 1); uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c new file mode 100644 index 0000000..06391c4 --- /dev/null +++ b/src/codegen_ops_stack.c @@ -0,0 +1,207 @@ +#include "ibm.h" + +#include "x86.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_helpers.h" +#include "codegen_ops_misc.h" + +uint32_t ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7)); + SUB_SP(ir, 2); + + return op_pc; +} +uint32_t ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7)); + SUB_SP(ir, 4); + + return op_pc; +} + +uint32_t ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr); + } + if ((opcode & 7) != REG_SP) + ADD_SP(ir, 2); + + return op_pc; +} +uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr); + } + if ((opcode & 7) != REG_ESP) + ADD_SP(ir, 4); + + return op_pc; +} + +uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if ((fetchdat & 0xc0) == 0xc0) + { + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr); + } + } + else + { + x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2); + codegen_check_seg_write(block, ir, target_seg); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_temp0, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0); + } + + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + } + + if ((fetchdat & 0xc7) != (0xc0 | REG_SP)) + ADD_SP(ir, 2); + + return op_pc + 1; +} +uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if ((fetchdat & 0xc0) == 0xc0) + { + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr); + } + } + else + { + x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4); + codegen_check_seg_write(block, ir, target_seg); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + else + { + uop_MOVZX(ir, IREG_temp0, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0); + } + + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } + + if ((fetchdat & 0xc7) != (0xc0 | REG_ESP)) + ADD_SP(ir, 4); + + return op_pc + 1; +} + +#define ROP_PUSH_SEG(seg) \ +uint32_t ropPUSH_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_ ## seg ## _seg_W); \ + SUB_SP(ir, 2); \ + \ + return op_pc; \ +} \ +uint32_t ropPUSH_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ + uop_MOVZX(ir, IREG_temp0, IREG_ ## seg ## _seg_W); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ + SUB_SP(ir, 4); \ + \ + return op_pc; \ +} + +#define ROP_POP_SEG(seg, rseg) \ +uint32_t ropPOP_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else \ + { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 2); \ + \ + return op_pc; \ +} \ +uint32_t ropPOP_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else \ + { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 4); \ + \ + return op_pc; \ +} + + +ROP_PUSH_SEG(CS) +ROP_PUSH_SEG(DS) +ROP_PUSH_SEG(ES) +ROP_PUSH_SEG(FS) +ROP_PUSH_SEG(GS) +ROP_PUSH_SEG(SS) +ROP_POP_SEG(DS, cpu_state.seg_ds) +ROP_POP_SEG(ES, cpu_state.seg_es) +ROP_POP_SEG(FS, cpu_state.seg_fs) +ROP_POP_SEG(GS, cpu_state.seg_gs) diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h new file mode 100644 index 0000000..319fb17 --- /dev/null +++ b/src/codegen_ops_stack.h @@ -0,0 +1,32 @@ +uint32_t ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPUSH_CS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_DS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_ES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_FS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_GS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_SS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPUSH_CS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_DS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_ES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_FS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_GS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_SS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPOP_DS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_ES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_FS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_GS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPOP_DS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_ES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_FS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOP_GS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 8bbf3ca..36b5ad8 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -64,6 +64,13 @@ struct [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base}, [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base}, + [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg}, + [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg}, + [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg}, + [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg}, + [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg}, + [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ @@ -98,6 +105,13 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) { switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { + case REG_WORD: + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_16_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_16(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; + case REG_DWORD: if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) codegen_direct_read_32_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); @@ -126,6 +140,12 @@ static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate) codegen_direct_write_8(block, p, codegen_host_reg_list[c]); break; + case REG_WORD: + if ((uintptr_t)p < 256) + fatal("codegen_reg_writeback - REG_WORD %p\n", p); + codegen_direct_write_16(block, p, codegen_host_reg_list[c]); + break; + case REG_DWORD: if ((uintptr_t)p < 256) codegen_direct_write_32_stack(block, (int)p, codegen_host_reg_list[c]); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index c57a0e5..e55d73a 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -49,13 +49,20 @@ enum IREG_GS_base = 25, IREG_SS_base = 26, + IREG_CS_seg = 27, + IREG_DS_seg = 28, + IREG_ES_seg = 29, + IREG_FS_seg = 30, + IREG_GS_seg = 31, + IREG_SS_seg = 32, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - IREG_temp0 = 27, - IREG_temp1 = 28, - IREG_temp2 = 29, - IREG_temp3 = 30, + IREG_temp0 = 33, + IREG_temp1 = 34, + IREG_temp2 = 35, + IREG_temp3 = 36, IREG_COUNT, @@ -88,7 +95,16 @@ enum IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, - IREG_temp1_B = IREG_temp1 + IREG_SIZE_B + IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, + + IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, + + IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, + IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W, + IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W, + IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W, + IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, + IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) diff --git a/src/ibm.h b/src/ibm.h index e852ac1..de79af6 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -236,7 +236,7 @@ uint8_t *pccache2; #define CPL ((cpu_state.seg_cs.access>>5)&3) -void loadseg(uint16_t seg, x86seg *s); +int loadseg(uint16_t seg, x86seg *s); void loadcs(uint16_t seg); union diff --git a/src/x86seg.c b/src/x86seg.c index 68b0d49..b508b87 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -309,7 +309,7 @@ static void check_seg_valid(x86seg *s) loadseg(0, s); } -void loadseg(uint16_t seg, x86seg *s) +int loadseg(uint16_t seg, x86seg *s) { uint16_t segdat[4]; uint32_t addr; @@ -324,7 +324,7 @@ void loadseg(uint16_t seg, x86seg *s) { pclog("SS selector = NULL!\n"); x86ss(NULL,0); - return; + return 1; // dumpregs(); // exit(-1); } @@ -335,7 +335,7 @@ void loadseg(uint16_t seg, x86seg *s) if (s == &cpu_state.seg_ds) cpu_cur_status |= CPU_STATUS_NOTFLATDS; // pclog("NULL selector %s%s%s%s %04X(%06X):%06X\n",(s==&_ds)?"DS":"",(s==&_es)?"ES":"",(s==&_fs)?"FS":"",(s==&_gs)?"GS":"",CS,cs,pc); - return; + return 0; } // if (s==&_ss) pclog("Load SS %04X\n",seg); // pclog("Protected mode seg load!\n"); @@ -349,7 +349,7 @@ void loadseg(uint16_t seg, x86seg *s) // dumpregs(); // exit(-1); x86gpf(NULL,seg&~3); - return; + return 1; } addr+=ldt.base; } @@ -361,7 +361,7 @@ void loadseg(uint16_t seg, x86seg *s) // dumpregs(); // exit(-1); x86gpf(NULL,seg&~3); - return; + return 1; } addr+=gdt.base; } @@ -369,7 +369,7 @@ void loadseg(uint16_t seg, x86seg *s) segdat[0]=readmemw(0,addr); segdat[1]=readmemw(0,addr+2); segdat[2]=readmemw(0,addr+4); - segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; + segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return 1; dpl=(segdat[2]>>13)&3; if (s==&cpu_state.seg_ss) { @@ -377,14 +377,14 @@ void loadseg(uint16_t seg, x86seg *s) { pclog("Load SS null selector\n"); x86gpf(NULL,seg&~3); - return; + return 1; } if ((seg&3)!=CPL || dpl!=CPL) { pclog("Invalid SS permiss\n"); x86gpf(NULL,seg&~3); // x86abort("Invalid SS permiss for %04X!\n",seg&0xFFFC); - return; + return 1; } switch ((segdat[2]>>8)&0x1F) { @@ -394,13 +394,13 @@ void loadseg(uint16_t seg, x86seg *s) pclog("Invalid SS type\n"); x86gpf(NULL,seg&~3); // x86abort("Invalid SS segment type for %04X!\n",seg&0xFFFC); - return; + return 1; } if (!(segdat[2]&0x8000)) { pclog("Load SS not present!\n"); x86ss(NULL,seg&~3); - return; + return 1; } set_stack32((segdat[3] & 0x40) ? 1 : 0); // pclog("Load SS %04x %04x %04x %04x\n", segdat[0], segdat[1], segdat[2], segdat[3]); @@ -420,7 +420,7 @@ void loadseg(uint16_t seg, x86seg *s) pclog("Data seg fail - %04X:%08X %04X %i %04X\n",CS,cpu_state.pc,seg,dpl,segdat[2]); x86gpf(NULL,seg&~3); // x86abort("Data segment load - level too low!\n",seg&0xFFFC); - return; + return 1; } break; case 0x1E: case 0x1F: /*Readable conforming code*/ @@ -428,14 +428,14 @@ void loadseg(uint16_t seg, x86seg *s) default: pclog("Invalid segment type for %04X! %04X\n",seg&0xFFFC,segdat[2]); x86gpf(NULL,seg&~3); - return; + return 1; } } if (!(segdat[2] & 0x8000)) { x86np("Load data seg not present", seg & 0xfffc); - return; + return 1; } s->seg = seg; do_seg_load(s, segdat); @@ -486,6 +486,8 @@ void loadseg(uint16_t seg, x86seg *s) else cpu_cur_status |= CPU_STATUS_NOTFLATSS; } + + return cpu_state.abrt; } #define DPL ((segdat[2]>>13)&3) From 57e5549f48b91acc8cec86e3805745dce710a42f Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 5 Aug 2018 16:24:48 +0100 Subject: [PATCH 026/181] Remove final remnants of ARM literal pool, and expand work register set to 7 registers. --- src/codegen_backend_arm.c | 18 ++++++------------ src/codegen_backend_arm.h | 2 +- src/codegen_backend_arm_defs.h | 3 +-- src/codegen_backend_arm_ops.c | 28 ++-------------------------- 4 files changed, 10 insertions(+), 41 deletions(-) diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 8b117d5..fb2d6f2 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -29,6 +29,10 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_R4, REG_R5, REG_R6, + REG_R7, + REG_R8, + REG_R9, + REG_R11, }; static void build_load_routine(codeblock_t *block, int size) @@ -203,14 +207,9 @@ void codegen_backend_init() build_loadstore_routines(&codeblock[block_current]); } -/*R11 - literal pool - R10 - cpu_state*/ +/*R10 - cpu_state*/ void codegen_backend_prologue(codeblock_t *block) { - int offset; - - codegen_reset_literal_pool(block); - block_pos = 0; block_pos = BLOCK_GPF_OFFSET; @@ -230,10 +229,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); - host_arm_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET); - host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START); - offset = add_literal(block, (uintptr_t)&cpu_state); - host_arm_LDR_IMM(block, REG_CPUSTATE, REG_R11, offset); + host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state); } void codegen_backend_epilogue(codeblock_t *block) @@ -244,8 +240,6 @@ void codegen_backend_epilogue(codeblock_t *block) if (block_pos > ARM_LITERAL_POOL_OFFSET) fatal("Over limit!\n"); - - __clear_cache(&block->data[0], &block->data[block_pos]); } diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index 1446594..67d18e6 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -15,7 +15,7 @@ #define BLOCK_GPF_OFFSET 0 #define BLOCK_EXIT_OFFSET 32 -#define ARM_LITERAL_POOL_OFFSET 0xf000 +#define ARM_LITERAL_POOL_OFFSET 0x10000 /*#define BLOCK_MAX 1720*/ #define BLOCK_MAX 65208 diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 8fb0215..e094838 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -21,7 +21,6 @@ #define REG_ARG3 REG_R3 #define REG_CPUSTATE REG_R10 -#define REG_LITERAL REG_R11 #define REG_TEMP REG_R3 @@ -45,7 +44,7 @@ #define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \ REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) -#define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_REGS 7 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 83817a7..ae4e0d2 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -105,32 +105,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define MOVT_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) #define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) -static int literal_offset = 0; -void codegen_reset_literal_pool(codeblock_t *block) -{ - literal_offset = 0; -} - -int add_literal(codeblock_t *block, uint32_t data) -{ - int c; - - if (literal_offset >= 4096) - fatal("add_literal - literal pool full\n"); - - /*Search for pre-existing value*/ - for (c = 0; c < literal_offset; c += 4) - { - if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data) - return c; - } - - *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 4; - - return literal_offset - 4; -} +#define LDRH_IMM(imm) (((imm) & 0xf) | (((imm) & 0xf0) << 4)) +#define STRH_IMM(imm) LDRH_IMM(imm) static inline uint32_t arm_data_offset(int offset) From 9bba93e0bed65b0c06defe1de36d2180fa95ac45 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 8 Aug 2018 22:14:22 +0100 Subject: [PATCH 027/181] Added recompiled versions of LEA, MOV seg, MOVZX, NEG, NOP, NOT, PUSH imm, TEST and XCHG. --- src/codegen_backend_arm64_uops.c | 44 +++++ src/codegen_backend_arm_ops.c | 22 +++ src/codegen_backend_arm_ops.h | 2 + src/codegen_backend_arm_uops.c | 58 ++++++ src/codegen_backend_x86-64_ops.c | 12 +- src/codegen_backend_x86-64_ops.h | 1 + src/codegen_backend_x86-64_uops.c | 28 ++- src/codegen_backend_x86_ops.c | 4 + src/codegen_backend_x86_ops.h | 1 + src/codegen_backend_x86_uops.c | 28 ++- src/codegen_ops.c | 24 +-- src/codegen_ops_logic.c | 111 +++++++++++ src/codegen_ops_logic.h | 7 + src/codegen_ops_misc.c | 239 ++++++++++++++++++++++- src/codegen_ops_misc.h | 9 + src/codegen_ops_mov.c | 307 ++++++++++++++++++++++++++++++ src/codegen_ops_mov.h | 15 ++ src/codegen_ops_stack.c | 50 +++++ src/codegen_ops_stack.h | 5 + 19 files changed, 938 insertions(+), 29 deletions(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 7b2ead8..620cdd2 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -127,6 +127,34 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_a, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_a, 0xffff00ff); + host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_b, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -149,6 +177,12 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); @@ -494,6 +528,16 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index ae4e0d2..801b99a 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -216,12 +216,34 @@ void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr { codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); +} void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); } +void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else if (get_arm_imm(~imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_BIC_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index dd74e0d..43df4d1 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -5,9 +5,11 @@ void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); +void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 7a98bf1..efc987f 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -194,6 +194,32 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) + { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -220,6 +246,22 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -562,6 +604,22 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { host_arm_UXTH(block, dest_reg, src_reg, 0); } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + if (src_reg == dest_reg) + host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index bbd80ff..490e100 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -242,21 +242,21 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n"); + fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } @@ -688,6 +688,12 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); } +void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 9bf56c5..dc95269 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -69,6 +69,7 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); +void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index a0e1c1f..fb1256f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -98,15 +98,21 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_AND32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND32_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_AND16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_AND8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -121,15 +127,21 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_AND32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_AND32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_AND16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_AND16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_AND8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_AND8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -445,6 +457,10 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); + } else fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); return 0; diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 49ca53b..e0ffc0f 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -599,6 +599,10 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) } } +void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index d4f4d66..2d7e53d 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -66,6 +66,7 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); +void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e88f81d..b46fcb8 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -108,15 +108,21 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_AND32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND32_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_AND16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_AND8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -131,15 +137,21 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_AND32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_AND32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_AND16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_AND16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_AND8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_AND8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } else fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -442,6 +454,10 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); + } else fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); return 0; diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 867108f..0315251 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -20,18 +20,18 @@ RecompOpFn recomp_opcodes[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, ropPOP_W, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W, +/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, /*c0*/ NULL, NULL, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -42,18 +42,18 @@ RecompOpFn recomp_opcodes[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, ropPOP_L, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L, +/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, /*c0*/ NULL, NULL, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32 +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32 }; @@ -74,7 +74,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -96,7 +96,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index a9f2021..8f402f1 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -418,6 +418,117 @@ uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc + 1; } +uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 2; +} +uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h index cfb7af3..d86fbb4 100644 --- a/src/codegen_ops_logic.h +++ b/src/codegen_ops_logic.h @@ -18,6 +18,13 @@ uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index 524fc71..01c404f 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -1,6 +1,7 @@ #include "ibm.h" #include "x86.h" +#include "x86_flags.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -8,6 +9,235 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_misc.h" +uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + return 0; + + codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W); + + return op_pc + 1; +} +uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + return 0; + + codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr); + + return op_pc + 1; +} + +uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm_data; + int reg; + + if (fetchdat & 0x20) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_8(fetchdat & 7); + else + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0_B; + } + + switch (fetchdat & 0x38) + { + case 0x00: case 0x08: /*TEST*/ + imm_data = fastreadb(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc+2; + + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); + + codegen_flags_changed = 1; + return op_pc+1; + + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1_B, 0); + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOVZX(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + uop_MOV(ir, reg, IREG_temp1_B); + } + else + { + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOV_IMM(ir, IREG_flags_op1, 0); + + codegen_flags_changed = 1; + return op_pc+1; + } + return 0; +} +uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint16_t imm_data; + int reg; + + if (fetchdat & 0x20) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_16(fetchdat & 7); + else + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0_W; + } + + switch (fetchdat & 0x38) + { + case 0x00: case 0x08: /*TEST*/ + imm_data = fastreadw(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc+3; + + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xffff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); + + codegen_flags_changed = 1; + return op_pc+1; + + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1_W, 0); + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOVZX(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV(ir, reg, IREG_temp1_W); + } + else + { + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOV_IMM(ir, IREG_flags_op1, 0); + + codegen_flags_changed = 1; + return op_pc+1; + } + return 0; +} +uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint32_t imm_data; + int reg; + + if (fetchdat & 0x20) + return 0; + + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_32(fetchdat & 7); + else + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0; + } + + switch (fetchdat & 0x38) + { + case 0x00: case 0x08: /*TEST*/ + imm_data = fastreadl(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_flags_res, reg, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + return op_pc+5; + + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xffffffff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); + + codegen_flags_changed = 1; + return op_pc+1; + + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1, 0); + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOV(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1, IREG_temp1, reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV(ir, reg, IREG_temp1); + } + else + { + uop_SUB(ir, IREG_temp1, IREG_temp1, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV_IMM(ir, IREG_flags_op1, 0); + + codegen_flags_changed = 1; + return op_pc+1; + } + return 0; +} + uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg, sp_reg; @@ -49,7 +279,7 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); SUB_SP(ir, 2); - return -1; + return op_pc+1; } return 0; } @@ -95,7 +325,12 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); SUB_SP(ir, 4); - return -1; + return op_pc+1; } return 0; } + +uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + return op_pc; +} diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h index b86c246..832c747 100644 --- a/src/codegen_ops_misc.h +++ b/src/codegen_ops_misc.h @@ -1,2 +1,11 @@ +uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 69fa5f7..274adcd 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -322,3 +322,310 @@ uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 5; } + +uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + + switch (fetchdat & 0x38) + { + case 0x00: /*ES*/ + src_reg = IREG_ES_seg_W; + break; + case 0x08: /*CS*/ + src_reg = IREG_CS_seg_W; + break; + case 0x18: /*DS*/ + src_reg = IREG_DS_seg_W; + break; + case 0x10: /*SS*/ + src_reg = IREG_SS_seg_W; + break; + case 0x20: /*FS*/ + src_reg = IREG_FS_seg_W; + break; + case 0x28: /*GS*/ + src_reg = IREG_GS_seg_W; + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), src_reg); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); + } + + return op_pc + 1; +} +uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + + switch (fetchdat & 0x38) + { + case 0x00: /*ES*/ + src_reg = IREG_ES_seg_W; + break; + case 0x08: /*CS*/ + src_reg = IREG_CS_seg_W; + break; + case 0x18: /*DS*/ + src_reg = IREG_DS_seg_W; + break; + case 0x10: /*SS*/ + src_reg = IREG_SS_seg_W; + break; + case 0x20: /*FS*/ + src_reg = IREG_FS_seg_W; + break; + case 0x28: /*GS*/ + src_reg = IREG_GS_seg_W; + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), src_reg); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); + } + + return op_pc + 1; +} + +uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + x86seg *rseg; + + switch (fetchdat & 0x38) + { + case 0x00: /*ES*/ + rseg = &cpu_state.seg_es; + break; + case 0x18: /*DS*/ + rseg = &cpu_state.seg_ds; + break; + case 0x20: /*FS*/ + rseg = &cpu_state.seg_fs; + break; + case 0x28: /*GS*/ + rseg = &cpu_state.seg_gs; + break; + default: + return 0; + } + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7)); + src_reg = IREG_temp0_W; + } + else + { + x86seg *target_seg; + + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0_W; + } + + uop_LOAD_SEG(ir, rseg, src_reg); + + return op_pc + 1; +} + +uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W); + } + + return op_pc + 1; +} + + +uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg2 = IREG_16(opcode & 7); + + uop_MOV(ir, IREG_temp0_W, IREG_AX); + uop_MOV(ir, IREG_AX, reg2); + uop_MOV(ir, reg2, IREG_temp0_W); + + return op_pc; +} +uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg2 = IREG_32(opcode & 7); + + uop_MOV(ir, IREG_temp0, IREG_EAX); + uop_MOV(ir, IREG_EAX, reg2); + uop_MOV(ir, reg2, IREG_temp0); + + return op_pc; +} + +uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_8((fetchdat >> 3) & 7); + + if ((fetchdat & 0xc0) == 0xc0) + { + int reg2 = IREG_8(fetchdat & 7); + + uop_MOV(ir, IREG_temp0_B, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0_B); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_16((fetchdat >> 3) & 7); + + if ((fetchdat & 0xc0) == 0xc0) + { + int reg2 = IREG_16(fetchdat & 7); + + uop_MOV(ir, IREG_temp0_W, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0_W); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0_W); + } + + return op_pc + 1; +} +uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_32((fetchdat >> 3) & 7); + + if ((fetchdat & 0xc0) == 0xc0) + { + int reg2 = IREG_32(fetchdat & 7); + + uop_MOV(ir, IREG_temp0, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0); + } + + return op_pc + 1; +} diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index 78442b4..c6c418d 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -20,3 +20,18 @@ uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c index 06391c4..befeb4e 100644 --- a/src/codegen_ops_stack.c +++ b/src/codegen_ops_stack.c @@ -64,6 +64,56 @@ uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc; } +uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm = fastreadw(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 2); + + return op_pc + 2; +} +uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t imm = fastreadl(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 4); + + return op_pc + 4; +} + +uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 2); + + return op_pc + 1; +} +uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 4); + + return op_pc + 1; +} + uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 319fb17..240cc1f 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -4,6 +4,11 @@ uint32_t ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 48466169242df0530de579787ac6dc030585860d Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 8 Aug 2018 22:14:52 +0100 Subject: [PATCH 028/181] Handle REP prefixed instructions without a dedicated REP instruction handler properly in the recompiler. Fixes Windows XP setup. --- src/codegen.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/codegen.c b/src/codegen.c index 8a06538..a43a728 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -485,6 +485,12 @@ generate_call: } } + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) + { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; if (!test_modrm || From 2783471daa739cff1dfdad7435503d4e741660d0 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 8 Aug 2018 22:15:21 +0100 Subject: [PATCH 029/181] Clamp SVGA display on/off timings to a minimum of 1 usec. Fixes hang on Windows XP boot with ViRGE/DX. --- src/vid_svga.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vid_svga.c b/src/vid_svga.c index 8f774cf..40e0e78 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -435,6 +435,10 @@ void svga_recalctimings(svga_t *svga) svga->dispontime = (uint64_t)_dispontime; svga->dispofftime = (uint64_t)_dispofftime; + if (svga->dispontime < TIMER_USEC) + svga->dispontime = TIMER_USEC; + if (svga->dispofftime < TIMER_USEC) + svga->dispofftime = TIMER_USEC; /* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock); printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart); printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]); From 872a2da788c429c0ddf946158d953e3beffa3f2c Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 16 Aug 2018 21:44:41 +0100 Subject: [PATCH 030/181] Added recompiled versions of SHL, SHR, SAR, SHLD and SHRD. --- src/codegen.c | 2 + src/codegen_backend_arm64_ops.c | 26 +- src/codegen_backend_arm64_ops.h | 6 + src/codegen_backend_arm64_uops.c | 208 +++++++- src/codegen_backend_arm_ops.c | 22 + src/codegen_backend_arm_ops.h | 4 + src/codegen_backend_arm_uops.c | 208 +++++++- src/codegen_backend_x86-64_ops.c | 111 +++- src/codegen_backend_x86-64_ops.h | 22 + src/codegen_backend_x86-64_uops.c | 187 ++++++- src/codegen_backend_x86_ops.c | 75 +++ src/codegen_backend_x86_ops.h | 22 + src/codegen_backend_x86_uops.c | 189 ++++++- src/codegen_ir_defs.h | 22 +- src/codegen_ops.c | 13 +- src/codegen_ops_shift.c | 809 ++++++++++++++++++++++++++++++ src/codegen_ops_shift.h | 16 + src/codegen_reg.h | 1 + 18 files changed, 1923 insertions(+), 20 deletions(-) create mode 100644 src/codegen_ops_shift.c create mode 100644 src/codegen_ops_shift.h diff --git a/src/codegen.c b/src/codegen.c index a43a728..ee782d1 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -244,6 +244,8 @@ x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, cpu_reg = (fetchdat >> 3) & 7; cpu_rm = fetchdat & 7; + if ((fetchdat & 0xc0) == 0xc0) + return NULL; if (op_32 & 0x200) return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index cd57fd7..895941e 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -73,6 +73,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_AND_ROR (0x056 << 21) #define OPCODE_ANDS_LSL (0x350 << 21) #define OPCODE_EOR_LSL (0x250 << 21) +#define OPCODE_ORR_ASR (0x154 << 21) #define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_ORR_LSR (0x152 << 21) #define OPCODE_ORRX_LSL (0x550 << 21) @@ -80,11 +81,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SUB_LSR (0x25a << 21) #define OPCODE_SUBX_LSL (0x658 << 21) +#define OPCODE_ASR (0x1ac02800) #define OPCODE_BLR (0xd63f0000) #define OPCODE_LDR_REG (0xb8606800) #define OPCODE_LDRB_REG (0x38606800) #define OPCODE_LDRH_REG (0x78606800) #define OPCODE_LDRX_REG_LSL3 (0xf8607800) +#define OPCODE_LSL (0x1ac02000) +#define OPCODE_LSR (0x1ac02400) #define OPCODE_NOP (0xd503201f) #define OPCODE_RET (0xd65f0000) #define OPCODE_STR_REG (0xb8206800) @@ -271,6 +275,11 @@ void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_ } } +void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +{ + codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); +} + void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); @@ -447,9 +456,24 @@ void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, in codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } +void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +{ + codegen_addlong(block, OPCODE_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); +} + +void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +{ + codegen_addlong(block, OPCODE_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); +} + +void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_ASR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - if (dst_reg != src_m_reg) + if (dst_reg != src_m_reg || shift) codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 0bdbcb4..348355a 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -9,6 +9,8 @@ void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); +void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg); + void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); void host_arm64_BLR(codeblock_t *block, int addr_reg); @@ -46,6 +48,10 @@ void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int off void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); +void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg); +void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg); + +void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 620cdd2..3253609 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -553,10 +553,10 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) { host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + host_arm64_ORR_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { @@ -610,6 +610,201 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_ASR(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_LSL(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_LSL(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_MOV_REG(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_MOV_REG(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_LSR(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, REG_W16, uop->imm_data); @@ -828,6 +1023,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_XOR & UOP_MASK] = codegen_XOR, [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_SAR & UOP_MASK] = codegen_SAR, + [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, + [UOP_SHL & UOP_MASK] = codegen_SHL, + [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, + [UOP_SHR & UOP_MASK] = codegen_SHR, + [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 801b99a..2811a37 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -18,6 +18,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) } #define Rm(x) (x) +#define Rs(x) ((x) << 8) #define Rd(x) ((x) << 12) #define Rn(x) ((x) << 16) @@ -94,9 +95,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define SHIFT_TYPE_REG (1 << 4) #define SHIFT_IMM_SHIFT 7 +#define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +#define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) +#define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) +#define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) + #define BFI_lsb(lsb) ((lsb) << 7) #define BFI_msb(msb) ((msb) << 16) @@ -427,14 +433,30 @@ void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) } } +void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_IMM(shift)); +} +void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_REG(shift_reg)); +} void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) { codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } +void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_REG(shift_reg)); +} void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) { codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); } +void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); +} void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 43df4d1..14690ba 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -46,8 +46,12 @@ void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm); #define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0) +void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm); void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index efc987f..2ab020d 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -635,10 +635,10 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) { host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { @@ -692,6 +692,201 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_ASR_REG(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_LSL_REG(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_LSR_REG(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_arm_MOV_IMM(block, REG_R0, uop->imm_data); @@ -911,6 +1106,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_XOR & UOP_MASK] = codegen_XOR, [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_SAR & UOP_MASK] = codegen_SAR, + [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, + [UOP_SHL & UOP_MASK] = codegen_SHL, + [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, + [UOP_SHR & UOP_MASK] = codegen_SHR, + [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 490e100..c10af3b 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -13,7 +13,9 @@ #define RM_OP_XOR 0x30 #define RM_OP_CMP 0x38 +#define RM_OP_SHL 0x20 #define RM_OP_SHR 0x28 +#define RM_OP_SAR 0x38 static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { @@ -811,10 +813,117 @@ void host_x86_RET(codeblock_t *block) codegen_addbyte(block, 0xc3); /*RET*/ } +void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR8 CL & 8\n"); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR16 CL & 8\n"); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR32 CL & 8\n"); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} + +void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR8 imm & 8\n"); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR16 imm & 8\n"); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR32 imm & 8\n"); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} + +void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL8 CL & 8\n"); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL16 CL & 8\n"); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL32 CL & 8\n"); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} + +void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL8 imm & 8\n"); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL16 imm & 8\n"); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL32 imm & 8\n"); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR8 CL & 8\n"); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR16 CL & 8\n"); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR32 CL & 8\n"); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} + +void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR8 imm & 8\n"); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR16 imm & 8\n"); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) - fatal("SHR32_IMM reg & 8\n"); + fatal("SHR32 imm & 8\n"); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index dc95269..3732f18 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -89,6 +89,28 @@ void host_x86_PUSH(codeblock_t *block, int src_reg); void host_x86_RET(codeblock_t *block); +void host_x86_SAR8_CL(codeblock_t *block, int dst_reg); +void host_x86_SAR16_CL(codeblock_t *block, int dst_reg); +void host_x86_SAR32_CL(codeblock_t *block, int dst_reg); + +void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_SHL8_CL(codeblock_t *block, int dst_reg); +void host_x86_SHL16_CL(codeblock_t *block, int dst_reg); +void host_x86_SHL32_CL(codeblock_t *block, int dst_reg); + +void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_SHR8_CL(codeblock_t *block, int dst_reg); +void host_x86_SHR16_CL(codeblock_t *block, int dst_reg); +void host_x86_SHR32_CL(codeblock_t *block, int dst_reg); + +void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index fb1256f..f251ffe 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -473,11 +473,15 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_OR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR32_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { @@ -511,6 +515,178 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_CL(block, dest_reg); + } + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_CL(block, dest_reg); + } + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_CL(block, dest_reg); + } + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { if (((uintptr_t)uop->p) >> 32) @@ -668,6 +844,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_XOR & UOP_MASK] = codegen_XOR, [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_SAR & UOP_MASK] = codegen_SAR, + [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, + [UOP_SHL & UOP_MASK] = codegen_SHL, + [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, + [UOP_SHR & UOP_MASK] = codegen_SHR, + [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index e0ffc0f..0a7595f 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -13,7 +13,9 @@ #define RM_OP_XOR 0x30 #define RM_OP_CMP 0x38 +#define RM_OP_SHL 0x20 #define RM_OP_SHR 0x28 +#define RM_OP_SAR 0x38 static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { @@ -707,6 +709,79 @@ void host_x86_RET(codeblock_t *block) #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} + +void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} + +void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} + +void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} + +void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 2d7e53d..ca6b0e8 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -89,6 +89,28 @@ void host_x86_PUSH(codeblock_t *block, int src_reg); void host_x86_RET(codeblock_t *block); +void host_x86_SAR8_CL(codeblock_t *block, int dst_reg); +void host_x86_SAR16_CL(codeblock_t *block, int dst_reg); +void host_x86_SAR32_CL(codeblock_t *block, int dst_reg); + +void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_SHL8_CL(codeblock_t *block, int dst_reg); +void host_x86_SHL16_CL(codeblock_t *block, int dst_reg); +void host_x86_SHL32_CL(codeblock_t *block, int dst_reg); + +void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_SHR8_CL(codeblock_t *block, int dst_reg); +void host_x86_SHR16_CL(codeblock_t *block, int dst_reg); +void host_x86_SHR32_CL(codeblock_t *block, int dst_reg); + +void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index b46fcb8..32aa1c9 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -470,11 +470,15 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { - host_x86_OR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR32_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { - host_x86_OR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR16_REG_REG(block, dest_reg, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { @@ -508,6 +512,178 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_CL(block, dest_reg); + } + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_CL(block, dest_reg); + } + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_CL(block, dest_reg); + } + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); @@ -660,7 +836,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, [UOP_XOR & UOP_MASK] = codegen_XOR, [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, - + + [UOP_SAR & UOP_MASK] = codegen_SAR, + [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, + [UOP_SHL & UOP_MASK] = codegen_SHL, + [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, + [UOP_SHR & UOP_MASK] = codegen_SHR, + [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ }; diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index dc92a77..d178898 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -89,7 +89,20 @@ /*UOP_CMP_JZ - if (src_reg_a == imm_data) then jump to ptr*/ #define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) -#define UOP_MAX 0x49 +/*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/ +#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) +/*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/ +#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51) +/*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/ +#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52) +/*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/ +#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53) +/*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/ +#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54) +/*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/ +#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) + +#define UOP_MAX 0x56 #define UOP_MASK 0xffff @@ -287,6 +300,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) #define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg) +#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg) +#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm) +#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) +#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) + #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 0315251..9d2ca5e 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -7,6 +7,7 @@ #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" #include "codegen_ops_mov.h" +#include "codegen_ops_shift.h" #include "codegen_ops_stack.h" RecompOpFn recomp_opcodes[512] = @@ -28,8 +29,8 @@ RecompOpFn recomp_opcodes[512] = /*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, -/*c0*/ NULL, NULL, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16, @@ -50,8 +51,8 @@ RecompOpFn recomp_opcodes[512] = /*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, -/*c0*/ NULL, NULL, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32 }; @@ -73,7 +74,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -95,7 +96,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_shift.c b/src/codegen_ops_shift.c new file mode 100644 index 0000000..90547d1 --- /dev/null +++ b/src/codegen_ops_shift.c @@ -0,0 +1,809 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_shift.h" + +static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) +{ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SAR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + default: + return 0; + } + } + else + { + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +static uint32_t shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) +{ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SAR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + default: + return 0; + } + } + else + { + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) +{ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } + else + { + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + + +uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (imm) + return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc+1; +} +uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (imm) + return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc+1; +} +uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (imm) + return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc+1; +} + +uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_8(ir, fetchdat, op_pc, target_seg, 1); +} +uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_16(ir, fetchdat, op_pc, target_seg, 1); +} +uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_32(ir, fetchdat, op_pc, target_seg, 1); +} + +uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]); + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SAR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]); + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SAR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]); + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (!imm) + return op_pc+2; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); + uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHL_IMM(ir, IREG_temp0_W, IREG_temp2, imm); + uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + + uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + } + return op_pc+2; +} +uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (!imm) + return op_pc+2; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); + uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHL_IMM(ir, IREG_temp0, IREG_temp2, imm); + uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + + uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + } + return op_pc+2; +} +uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (!imm) + return op_pc+2; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); + uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHR_IMM(ir, IREG_temp0_W, IREG_temp2, imm); + uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + + uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + } + return op_pc+2; +} +uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + if ((fetchdat & 0xc0) != 0xc0) + { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + + if (!imm) + return op_pc+2; + + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); + uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHR_IMM(ir, IREG_temp0, IREG_temp2, imm); + uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + + uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + } + return op_pc+2; +} diff --git a/src/codegen_ops_shift.h b/src/codegen_ops_shift.h new file mode 100644 index 0000000..f109b0d --- /dev/null +++ b/src/codegen_ops_shift.h @@ -0,0 +1,16 @@ +uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index e55d73a..aa52e03 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -93,6 +93,7 @@ enum IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, + IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, From 33328978867c7a70df3afb3fe4db429986170bf6 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 30 Aug 2018 22:26:33 +0100 Subject: [PATCH 031/181] Added recompiled versions of Jcc, JCXZ, LOOP, LOOPE and LOOPNE. --- src/codegen_backend_arm64_ops.c | 96 ++++- src/codegen_backend_arm64_ops.h | 17 + src/codegen_backend_arm64_uops.c | 458 ++++++++++++++++++++- src/codegen_backend_arm_ops.c | 103 +++++ src/codegen_backend_arm_ops.h | 19 + src/codegen_backend_arm_uops.c | 453 +++++++++++++++++++- src/codegen_backend_x86-64_ops.c | 143 +++++++ src/codegen_backend_x86-64_ops.h | 24 ++ src/codegen_backend_x86-64_uops.c | 428 ++++++++++++++++++- src/codegen_backend_x86_ops.c | 127 ++++++ src/codegen_backend_x86_ops.h | 25 ++ src/codegen_backend_x86_uops.c | 428 ++++++++++++++++++- src/codegen_ir.c | 55 ++- src/codegen_ir_defs.h | 127 +++++- src/codegen_ops.c | 13 +- src/codegen_ops_branch.c | 662 ++++++++++++++++++++++++++++++ src/codegen_ops_branch.h | 69 ++++ src/codegen_reg.h | 8 +- 18 files changed, 3234 insertions(+), 21 deletions(-) create mode 100644 src/codegen_ops_branch.c create mode 100644 src/codegen_ops_branch.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 895941e..91e49e0 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -31,6 +31,19 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define COND_EQ (0x0) #define COND_NE (0x1) +#define COND_CS (0x2) +#define COND_CC (0x3) +#define COND_MI (0x4) +#define COND_PL (0x5) +#define COND_VS (0x6) +#define COND_VC (0x7) +#define COND_HI (0x8) +#define COND_LS (0x9) +#define COND_GE (0xa) +#define COND_LT (0xb) +#define COND_GT (0xc) +#define COND_LE (0xd) + #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) @@ -72,6 +85,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_AND_LSL (0x050 << 21) #define OPCODE_AND_ROR (0x056 << 21) #define OPCODE_ANDS_LSL (0x350 << 21) +#define OPCODE_CMP_LSL (0x358 << 21) #define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_ASR (0x154 << 21) #define OPCODE_ORR_LSL (0x150 << 21) @@ -83,6 +97,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ASR (0x1ac02800) #define OPCODE_BLR (0xd63f0000) +#define OPCODE_BR (0xd61f0000) #define OPCODE_LDR_REG (0xb8606800) #define OPCODE_LDRB_REG (0x38606800) #define OPCODE_LDRH_REG (0x78606800) @@ -290,15 +305,75 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg) codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); } +uint32_t *host_arm64_BCC_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_CC); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BCS_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_CS); + return (uint32_t *)&block->data[block_pos-4]; +} uint32_t *host_arm64_BEQ_(codeblock_t *block) { codegen_addlong(block, OPCODE_BCOND | COND_EQ); - return &block->data[block_pos-4]; + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BGE_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_GE); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BGT_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_GT); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BHI_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_HI); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BLE_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_LE); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BLS_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_LS); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BLT_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_LT); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BMI_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_MI); + return (uint32_t *)&block->data[block_pos-4]; } uint32_t *host_arm64_BNE_(codeblock_t *block) { codegen_addlong(block, OPCODE_BCOND | COND_NE); - return &block->data[block_pos-4]; + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BPL_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_PL); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BVC_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_VC); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_arm64_BVS_(codeblock_t *block) +{ + codegen_addlong(block, OPCODE_BCOND | COND_VS); + return (uint32_t *)&block->data[block_pos-4]; } void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) @@ -307,6 +382,11 @@ void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) *opcode |= OFFSET19(offset); } +void host_arm64_BR(codeblock_t *block, int addr_reg) +{ + codegen_addlong(block, OPCODE_BR | Rn(addr_reg)); +} + void host_arm64_BEQ(codeblock_t *block, void *dest) { uint32_t *opcode = host_arm64_BEQ_(block); @@ -375,6 +455,11 @@ void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) fatal("CMPX_IMM %08x\n", imm_data); } +void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ @@ -649,6 +734,13 @@ void host_arm64_call(codeblock_t *block, void *dst_addr) host_arm64_BLR(block, REG_X16); } +void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) +{ + int offset = add_literal_q(block, (uintptr_t)dst_addr); + host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_BR(block, REG_X16); +} + void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) { if (imm_is_imm16(imm_data)) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 348355a..35d5044 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -17,11 +17,25 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg); void host_arm64_BEQ(codeblock_t *block, void *dest); +uint32_t *host_arm64_BCC_(codeblock_t *block); +uint32_t *host_arm64_BCS_(codeblock_t *block); uint32_t *host_arm64_BEQ_(codeblock_t *block); +uint32_t *host_arm64_BGE_(codeblock_t *block); +uint32_t *host_arm64_BGT_(codeblock_t *block); +uint32_t *host_arm64_BHI_(codeblock_t *block); +uint32_t *host_arm64_BLE_(codeblock_t *block); +uint32_t *host_arm64_BLS_(codeblock_t *block); +uint32_t *host_arm64_BLT_(codeblock_t *block); +uint32_t *host_arm64_BMI_(codeblock_t *block); uint32_t *host_arm64_BNE_(codeblock_t *block); +uint32_t *host_arm64_BPL_(codeblock_t *block); +uint32_t *host_arm64_BVC_(codeblock_t *block); +uint32_t *host_arm64_BVS_(codeblock_t *block); void host_arm64_branch_set_offset(uint32_t *opcode, void *dest); +void host_arm64_BR(codeblock_t *block, int addr_reg); + void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); @@ -30,6 +44,8 @@ void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); +#define host_arm64_CMP_REG(block, src_n_reg, src_m_reg) host_arm64_CMP_REG_LSL(block, src_n_reg, src_m_reg, 0) +void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift); void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); @@ -88,6 +104,7 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); void host_arm64_call(codeblock_t *block, void *dst_addr); +void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 3253609..ebef0fc 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -7,6 +7,8 @@ #include "codegen_backend_arm64_ops.h" #include "codegen_ir_defs.h" +#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) + #define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) #define REG_IS_L(size) (size == IREG_SIZE_L) @@ -193,6 +195,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_arm64_call(block, uop->p); + host_arm64_MOV_REG(block, dest_reg, REG_W0, 0); + + return 0; +} + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_arm64_call(block, uop->p); @@ -217,6 +232,369 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); + } + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BNE_(block); + + return 0; +} +static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); + } + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BEQ_(block); + + return 0; +} + +static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BCS_(block); + + return 0; +} +static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BHI_(block); + + return 0; +} +static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BGE_(block); + + return 0; +} +static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BGT_(block); + + return 0; +} +static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BVC_(block); + + return 0; +} +static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BNE_(block); + + return 0; +} +static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BCC_(block); + + return 0; +} +static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BLS_(block); + + return 0; +} +static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BLT_(block); + + return 0; +} +static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BLE_(block); + + return 0; +} +static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BVS_(block); + + return 0; +} +static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BEQ_(block); + + return 0; +} + +static int codegen_JMP(codeblock_t *block, uop_t *uop) +{ + host_arm64_jump(block, (uintptr_t)uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); @@ -918,6 +1296,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm64_TST_IMM(block, src_reg, 1 << 31); + } + else if (REG_IS_W(src_size)) + { + host_arm64_TST_IMM(block, src_reg, 1 << 15); + } + else if (REG_IS_B(src_size)) + { + host_arm64_TST_IMM(block, src_reg, 1 << 7); + } + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BEQ_(block); + + return 0; +} +static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm64_TST_IMM(block, src_reg, 1 << 31); + } + else if (REG_IS_W(src_size)) + { + host_arm64_TST_IMM(block, src_reg, 1 << 15); + } + else if (REG_IS_B(src_size)) + { + host_arm64_TST_IMM(block, src_reg, 1 << 7); + } + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm64_BNE_(block); + + return 0; +} + static int codegen_XOR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -986,7 +1413,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, @@ -1030,7 +1461,26 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) @@ -1108,4 +1558,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos fatal("codegen_direct_write_32_stack - not in range\n"); } +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)&block->data[block_pos] - (uintptr_t)p; + + *(uint32_t *)p |= OFFSET19(offset); +} #endif diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 2811a37..66941ce 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -28,6 +28,18 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define COND_SHIFT 28 #define COND_EQ (0x0 << COND_SHIFT) #define COND_NE (0x1 << COND_SHIFT) +#define COND_CS (0x2 << COND_SHIFT) +#define COND_CC (0x3 << COND_SHIFT) +#define COND_MI (0x4 << COND_SHIFT) +#define COND_PL (0x5 << COND_SHIFT) +#define COND_VS (0x6 << COND_SHIFT) +#define COND_VC (0x7 << COND_SHIFT) +#define COND_HI (0x8 << COND_SHIFT) +#define COND_LS (0x9 << COND_SHIFT) +#define COND_GE (0xa << COND_SHIFT) +#define COND_LT (0xb << COND_SHIFT) +#define COND_GT (0xc << COND_SHIFT) +#define COND_LE (0xd << COND_SHIFT) #define COND_AL (0xe << COND_SHIFT) #define OPCODE_SHIFT 20 @@ -72,6 +84,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BFI 0xe7c00010 #define OPCODE_BLX 0xe12fff30 +#define OPCODE_BX 0xe12fff10 #define OPCODE_LDRH_IMM 0xe1d000b0 #define OPCODE_LDRH_REG 0xe19000b0 #define OPCODE_STRH_IMM 0xe1c000b0 @@ -227,6 +240,19 @@ void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } +void host_arm_B(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + { + host_arm_MOV_IMM(block, REG_R3, dest_addr); + host_arm_BX(block, REG_R3); + } + else + codegen_addlong(block, COND_AL | OPCODE_B | B_OFFSET(offset)); +} + void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); @@ -276,18 +302,90 @@ void host_arm_BLX(codeblock_t *block, int addr_reg) codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); } +uint32_t *host_arm_BCC_(codeblock_t *block) +{ + codegen_addlong(block, COND_CC | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BCS_(codeblock_t *block) +{ + codegen_addlong(block, COND_CS | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} uint32_t *host_arm_BEQ_(codeblock_t *block) { codegen_addlong(block, COND_EQ | OPCODE_B); return (uint32_t *)&block->data[block_pos - 4]; } +uint32_t *host_arm_BGE_(codeblock_t *block) +{ + codegen_addlong(block, COND_GE | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BGT_(codeblock_t *block) +{ + codegen_addlong(block, COND_GT | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BHI_(codeblock_t *block) +{ + codegen_addlong(block, COND_HI | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BLE_(codeblock_t *block) +{ + codegen_addlong(block, COND_LE | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BLS_(codeblock_t *block) +{ + codegen_addlong(block, COND_LS | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BLT_(codeblock_t *block) +{ + codegen_addlong(block, COND_LT | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BMI_(codeblock_t *block) +{ + codegen_addlong(block, COND_MI | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} uint32_t *host_arm_BNE_(codeblock_t *block) { codegen_addlong(block, COND_NE | OPCODE_B); return (uint32_t *)&block->data[block_pos - 4]; } +uint32_t *host_arm_BPL_(codeblock_t *block) +{ + codegen_addlong(block, COND_PL | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BVC_(codeblock_t *block) +{ + codegen_addlong(block, COND_VC | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} +uint32_t *host_arm_BVS_(codeblock_t *block) +{ + codegen_addlong(block, COND_VS | OPCODE_B); + + return (uint32_t *)&block->data[block_pos - 4]; +} void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) { @@ -308,6 +406,11 @@ void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); } +void host_arm_BX(codeblock_t *block, int addr_reg) +{ + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); +} + void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) { uint32_t arm_imm; diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 14690ba..6dcb29e 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -7,6 +7,8 @@ void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_B(codeblock_t *block, uintptr_t dest_addr); + void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); @@ -15,15 +17,32 @@ void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_BL(codeblock_t *block, uintptr_t dest_addr); void host_arm_BLX(codeblock_t *block, int addr_reg); + +uint32_t *host_arm_BCC_(codeblock_t *block); +uint32_t *host_arm_BCS_(codeblock_t *block); uint32_t *host_arm_BEQ_(codeblock_t *block); +uint32_t *host_arm_BGE_(codeblock_t *block); +uint32_t *host_arm_BGT_(codeblock_t *block); +uint32_t *host_arm_BHI_(codeblock_t *block); +uint32_t *host_arm_BLE_(codeblock_t *block); +uint32_t *host_arm_BLS_(codeblock_t *block); +uint32_t *host_arm_BLT_(codeblock_t *block); +uint32_t *host_arm_BMI_(codeblock_t *block); uint32_t *host_arm_BNE_(codeblock_t *block); +uint32_t *host_arm_BPL_(codeblock_t *block); +uint32_t *host_arm_BVC_(codeblock_t *block); +uint32_t *host_arm_BVS_(codeblock_t *block); + void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr); void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr); +void host_arm_BX(codeblock_t *block, int addr_reg); + void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm); void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift); void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm); +#define host_arm_CMP_REG(block, src_reg_n, src_reg_m) host_arm_CMP_REG_LSL(block, src_reg_n, src_reg_m, 0) void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift); void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 2ab020d..427da2e 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -268,6 +268,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_arm_call(block, uop->p); + host_arm_MOV_REG(block, dest_reg, REG_R0); + + return 0; +} + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_arm_call(block, uop->p); @@ -293,6 +306,369 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); + } + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} +static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); + } + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} + +static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BCS_(block); + + return 0; +} +static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BHI_(block); + + return 0; +} +static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BGE_(block); + + return 0; +} +static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BGT_(block); + + return 0; +} +static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BVC_(block); + + return 0; +} +static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} +static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BCC_(block); + + return 0; +} +static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLS_(block); + + return 0; +} +static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLT_(block); + + return 0; +} +static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLE_(block); + + return 0; +} +static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BVS_(block); + + return 0; +} +static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} + +static int codegen_JMP(codeblock_t *block, uop_t *uop) +{ + host_arm_B(block, (uintptr_t)uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); @@ -1000,6 +1376,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm_TST_IMM(block, src_reg, 1 << 31); + } + else if (REG_IS_W(src_size)) + { + host_arm_TST_IMM(block, src_reg, 1 << 15); + } + else if (REG_IS_B(src_size)) + { + host_arm_TST_IMM(block, src_reg, 1 << 7); + } + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} +static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_arm_TST_IMM(block, src_reg, 1 << 31); + } + else if (REG_IS_W(src_size)) + { + host_arm_TST_IMM(block, src_reg, 1 << 15); + } + else if (REG_IS_B(src_size)) + { + host_arm_TST_IMM(block, src_reg, 1 << 7); + } + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} + static int codegen_XOR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1068,8 +1493,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, @@ -1113,7 +1541,26 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, }; void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) @@ -1190,4 +1637,8 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + *(uint32_t *)p |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; +} #endif diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index c10af3b..6de5334 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -117,6 +117,23 @@ static inline void call(codeblock_t *block, uintptr_t func) } } +static inline void jmp(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uint32_t)diff); + } + else + { + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ + codegen_addquad(block, func); + codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ + } +} + void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) @@ -268,6 +285,21 @@ void host_x86_CALL(codeblock_t *block, void *p) call(block, (uintptr_t)p); } +void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (is_imm8(imm_data)) @@ -291,6 +323,24 @@ void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) fatal("CMP64_REG_IMM not 8-bit imm\n"); } +void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} + +void host_x86_JMP(codeblock_t *block, void *p) +{ + jmp(block, (uintptr_t)p); +} + void host_x86_JNZ(codeblock_t *block, void *p) { codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ @@ -313,6 +363,91 @@ uint8_t *host_x86_JZ_short(codeblock_t *block) return &block->data[block_pos-1]; } +uint32_t *host_x86_JNB_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNBE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNL_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNLE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNO_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNS_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNZ_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JB_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JBE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JL_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JLE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JO_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JS_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JZ_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) { if (offset) @@ -1007,6 +1142,14 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) { if ((dst_reg & 8) || (src_reg & 8)) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 3732f18..2bef40c 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -17,15 +17,37 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int void host_x86_CALL(codeblock_t *block, void *p); +void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data); +void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); + +void host_x86_JMP(codeblock_t *block, void *p); + void host_x86_JNZ(codeblock_t *block, void *p); void host_x86_JZ(codeblock_t *block, void *p); uint8_t *host_x86_JNZ_short(codeblock_t *block); uint8_t *host_x86_JZ_short(codeblock_t *block); +uint32_t *host_x86_JNB_long(codeblock_t *block); +uint32_t *host_x86_JNBE_long(codeblock_t *block); +uint32_t *host_x86_JNL_long(codeblock_t *block); +uint32_t *host_x86_JNLE_long(codeblock_t *block); +uint32_t *host_x86_JNO_long(codeblock_t *block); +uint32_t *host_x86_JNS_long(codeblock_t *block); +uint32_t *host_x86_JNZ_long(codeblock_t *block); +uint32_t *host_x86_JB_long(codeblock_t *block); +uint32_t *host_x86_JBE_long(codeblock_t *block); +uint32_t *host_x86_JL_long(codeblock_t *block); +uint32_t *host_x86_JLE_long(codeblock_t *block); +uint32_t *host_x86_JO_long(codeblock_t *block); +uint32_t *host_x86_JS_long(codeblock_t *block); +uint32_t *host_x86_JZ_long(codeblock_t *block); + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset); void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); @@ -122,6 +144,8 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); +void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg); void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index f251ffe..59f78b3 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -149,6 +149,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_x86_CALL(block, uop->p); + host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); + + return 0; +} + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); @@ -174,6 +187,343 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNZ_long(block); + + return 0; +} +static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JZ_long(block); + + return 0; +} + +static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNB_long(block); + + return 0; +} +static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNBE_long(block); + + return 0; +} +static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNL_long(block); + + return 0; +} +static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNLE_long(block); + + return 0; +} +static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNO_long(block); + + return 0; +} +static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNZ_long(block); + + return 0; +} +static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JB_long(block); + + return 0; +} +static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JBE_long(block); + + return 0; +} +static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JL_long(block); + + return 0; +} +static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JLE_long(block); + + return 0; +} +static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JO_long(block); + + return 0; +} +static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JZ_long(block); + + return 0; +} + +static int codegen_JMP(codeblock_t *block, uop_t *uop) +{ + host_x86_JMP(block, uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { #if WIN64 @@ -759,6 +1109,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_TEST32_REG(block, src_reg, src_reg); + } + else if (REG_IS_W(src_size)) + { + host_x86_TEST16_REG(block, src_reg, src_reg); + } + else if (REG_IS_B(src_size)) + { + host_x86_TEST8_REG(block, src_reg, src_reg); + } + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNS_long(block); + + return 0; +} +static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_TEST32_REG(block, src_reg, src_reg); + } + else if (REG_IS_W(src_size)) + { + host_x86_TEST16_REG(block, src_reg, src_reg); + } + else if (REG_IS_B(src_size)) + { + host_x86_TEST8_REG(block, src_reg, src_reg); + } + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JS_long(block); + + return 0; +} + static int codegen_XOR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -806,8 +1205,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, @@ -851,7 +1253,26 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, }; void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) @@ -895,4 +1316,9 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + *(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4); +} + #endif diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 0a7595f..b61abd1 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -260,6 +260,21 @@ void host_x86_CALL(codeblock_t *block, void *p) codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); } +void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + else if (dst_reg == REG_EAX) + { + codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ + codegen_addword(block, imm_data); + } + else + { + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (is_imm8(imm_data)) @@ -276,6 +291,25 @@ void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } +void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} + +void host_x86_JMP(codeblock_t *block, void *p) +{ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); +} + void host_x86_JNZ(codeblock_t *block, void *p) { codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ @@ -298,6 +332,91 @@ uint8_t *host_x86_JZ_short(codeblock_t *block) return &block->data[block_pos-1]; } +uint32_t *host_x86_JNB_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNBE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNL_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNLE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNO_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNS_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JNZ_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JB_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JBE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JL_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JLE_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JO_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JS_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} +uint32_t *host_x86_JZ_long(codeblock_t *block) +{ + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) { if (offset) @@ -856,6 +975,14 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } +void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index ca6b0e8..6fa0a97 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -18,14 +18,36 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int void host_x86_CALL(codeblock_t *block, void *p); +void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); +void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); + +void host_x86_JMP(codeblock_t *block, void *p); + void host_x86_JNZ(codeblock_t *block, void *p); void host_x86_JZ(codeblock_t *block, void *p); uint8_t *host_x86_JNZ_short(codeblock_t *block); uint8_t *host_x86_JZ_short(codeblock_t *block); +uint32_t *host_x86_JNB_long(codeblock_t *block); +uint32_t *host_x86_JNBE_long(codeblock_t *block); +uint32_t *host_x86_JNL_long(codeblock_t *block); +uint32_t *host_x86_JNLE_long(codeblock_t *block); +uint32_t *host_x86_JNO_long(codeblock_t *block); +uint32_t *host_x86_JNS_long(codeblock_t *block); +uint32_t *host_x86_JNZ_long(codeblock_t *block); +uint32_t *host_x86_JB_long(codeblock_t *block); +uint32_t *host_x86_JBE_long(codeblock_t *block); +uint32_t *host_x86_JL_long(codeblock_t *block); +uint32_t *host_x86_JLE_long(codeblock_t *block); +uint32_t *host_x86_JO_long(codeblock_t *block); +uint32_t *host_x86_JS_long(codeblock_t *block); +uint32_t *host_x86_JZ_long(codeblock_t *block); + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset); void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); @@ -121,7 +143,10 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); +void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); + void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data); void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 32aa1c9..4f1ceb8 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -159,6 +159,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_x86_CALL(block, uop->p); + host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); + + return 0; +} + static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); @@ -181,10 +194,347 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) else fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); host_x86_JZ(block, uop->p); + + return 0; +} + +static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNZ_long(block); + + return 0; +} +static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } + else if (REG_IS_W(src_size)) + { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JZ_long(block); return 0; } +static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNB_long(block); + + return 0; +} +static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNBE_long(block); + + return 0; +} +static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNL_long(block); + + return 0; +} +static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNLE_long(block); + + return 0; +} +static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNO_long(block); + + return 0; +} +static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNZ_long(block); + + return 0; +} +static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JB_long(block); + + return 0; +} +static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JBE_long(block); + + return 0; +} +static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JL_long(block); + + return 0; +} +static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JLE_long(block); + + return 0; +} +static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JO_long(block); + + return 0; +} +static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } + else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JZ_long(block); + + return 0; +} + +static int codegen_JMP(codeblock_t *block, uop_t *uop) +{ + host_x86_JMP(block, uop->p); + + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); @@ -752,6 +1102,55 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_TEST32_REG(block, src_reg, src_reg); + } + else if (REG_IS_W(src_size)) + { + host_x86_TEST16_REG(block, src_reg, src_reg); + } + else if (REG_IS_B(src_size)) + { + host_x86_TEST8_REG(block, src_reg, src_reg); + } + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JNS_long(block); + + return 0; +} +static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) + { + host_x86_TEST32_REG(block, src_reg, src_reg); + } + else if (REG_IS_W(src_size)) + { + host_x86_TEST16_REG(block, src_reg, src_reg); + } + else if (REG_IS_B(src_size)) + { + host_x86_TEST8_REG(block, src_reg, src_reg); + } + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_x86_JS_long(block); + + return 0; +} + static int codegen_XOR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -799,8 +1198,11 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, + [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, @@ -844,7 +1246,26 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ + [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, }; void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) @@ -888,4 +1309,9 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); } +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + *(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4); +} + #endif diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 8d81db8..c179632 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -17,6 +17,7 @@ ir_data_t *codegen_ir_init() void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) { + int jump_target_at_end = -1; int c; codegen_backend_prologue(block); @@ -26,12 +27,23 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) uop_t *uop = &ir->uops[c]; // pclog("uOP %i : %08x\n", c, uop->type); - + if (uop->type & UOP_TYPE_BARRIER) codegen_reg_flush_invalidate(ir, block); else if (uop->type & UOP_TYPE_ORDER_BARRIER) codegen_reg_flush(ir, block); + if (uop->type & UOP_TYPE_JUMP_DEST) + { + uop_t *uop_dest = uop; + + while (uop_dest->jump_list_next != -1) + { + uop_dest = &ir->uops[uop_dest->jump_list_next]; + codegen_set_jump_dest(block, uop_dest->p); + } + } + if (uop->type & UOP_TYPE_PARAMS_REGS) { codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); @@ -56,10 +68,51 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) if (!uop_handlers[uop->type & UOP_MASK]) fatal("!uop_handlers[uop->type & UOP_MASK]\n"); uop_handlers[uop->type & UOP_MASK](block, uop); + + if (uop->type & UOP_TYPE_JUMP) + { + if (uop->jump_dest_uop == ir->wr_pos) + { + if (jump_target_at_end == -1) + jump_target_at_end = c; + else + { + uop_t *uop_dest = &ir->uops[jump_target_at_end]; + + while (uop_dest->jump_list_next != -1) + uop_dest = &ir->uops[uop_dest->jump_list_next]; + + uop_dest->jump_list_next = c; + } + } + else + { + uop_t *uop_dest = &ir->uops[uop->jump_dest_uop]; + + while (uop_dest->jump_list_next != -1) + uop_dest = &ir->uops[uop_dest->jump_list_next]; + + uop_dest->jump_list_next = c; + ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST; + } + } } codegen_reg_flush_invalidate(ir, block); + if (jump_target_at_end != -1) + { + uop_t *uop_dest = &ir->uops[jump_target_at_end]; + + while (1) + { + codegen_set_jump_dest(block, uop_dest->p); + if (uop_dest->jump_list_next == -1) + break; + uop_dest = &ir->uops[uop_dest->jump_list_next]; + } + } + codegen_backend_epilogue(block); // if (has_ea) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index d178898..22b1e70 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -24,6 +24,13 @@ /*uOP uses immediate data*/ #define UOP_TYPE_PARAMS_IMM (1 << 30) +/*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must + set jump_dest in the destination uOP to the address of the branch offset to be + written when known.*/ +#define UOP_TYPE_JUMP (1 << 26) +/*uOP is the destination of a jump, and must set the destination offset of the jump + at compile time.*/ +#define UOP_TYPE_JUMP_DEST (1 << 25) #define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00) @@ -41,6 +48,10 @@ #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) /*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/ #define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER) +/*UOP_JMP - jump to ptr*/ +#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER) +/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/ +#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) /*UOP_MOV_PTR - dest_reg = p*/ #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) /*UOP_MOV_IMM - dest_reg = imm_data*/ @@ -86,7 +97,7 @@ #define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/ #define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) -/*UOP_CMP_JZ - if (src_reg_a == imm_data) then jump to ptr*/ +/*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/ #define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) /*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/ @@ -102,7 +113,43 @@ /*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/ #define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) -#define UOP_MAX 0x56 +/*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/ +#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/ +#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) + +/*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/ +#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/ +#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/ +#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/ +#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/ +#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/ +#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) + + +/*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/ +#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +/*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/ +#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) + +#define UOP_MAX 0x72 #define UOP_MASK 0xffff @@ -117,6 +164,9 @@ typedef struct uop_t void *p; ir_host_reg_t dest_reg_a_real; ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; + int jump_dest_uop; + int jump_list_next; + void *jump_dest; } uop_t; #define UOP_NR_MAX 4096 @@ -141,15 +191,45 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop->src_reg_b = invalid_ir_reg; uop->src_reg_c = invalid_ir_reg; + uop->jump_list_next = -1; + return uop; } -static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) +static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop) +{ + uop_t *uop = &ir->uops[jump_uop]; + + uop->jump_dest_uop = ir->wr_pos; +} + +static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) { uop_t *uop = uop_alloc(ir); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); + + return ir->wr_pos-1; +} + +static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); +} + +static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->imm_data = imm; + + return ir->wr_pos-1; } static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) @@ -220,6 +300,17 @@ static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int uop->imm_data = imm; } +static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + + return ir->wr_pos-1; +} + static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) { uop_t *uop = uop_alloc(ir); @@ -284,7 +375,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, uop->imm_data = imm; } -#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) +#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1_arg(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) @@ -307,11 +398,30 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) #define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) -#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) -#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) +#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) +#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) #define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) +#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm) +#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm) + +#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) + +#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) + #define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) #define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) @@ -330,6 +440,9 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) +#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) +#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) + void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); @@ -343,4 +456,6 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); +void codegen_set_jump_dest(codeblock_t *block, void *p); + #endif diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 9d2ca5e..ff7df3d 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -3,6 +3,7 @@ #include "codegen_ir.h" #include "codegen_ops.h" #include "codegen_ops_arith.h" +#include "codegen_ops_branch.h" #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" @@ -22,7 +23,7 @@ RecompOpFn recomp_opcodes[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W, /*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -31,7 +32,7 @@ RecompOpFn recomp_opcodes[512] = /*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, +/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16, /*32-bit data*/ @@ -44,7 +45,7 @@ RecompOpFn recomp_opcodes[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L, /*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -53,7 +54,7 @@ RecompOpFn recomp_opcodes[512] = /*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, +/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32 }; @@ -72,7 +73,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -94,7 +95,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c new file mode 100644 index 0000000..d62e1e5 --- /dev/null +++ b/src/codegen_ops_branch.c @@ -0,0 +1,662 @@ +#include "ibm.h" + +#include "x86.h" +#include "386_common.h" +#include "x86_flags.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_helpers.h" +#include "codegen_ops_mov.h" + +static int NF_SET_01() +{ + return NF_SET() ? 1 : 0; +} +static int VF_SET_01() +{ + return VF_SET() ? 1 : 0; +} + +static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Overflow is always zero*/ + return; + + case FLAGS_SUB8: case FLAGS_DEC8: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: case FLAGS_DEC16: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: case FLAGS_DEC32: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Overflow is always zero*/ + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + return; + + case FLAGS_SUB8: case FLAGS_DEC8: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: case FLAGS_DEC16: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: case FLAGS_DEC32: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} + +static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Carry is always zero*/ + return; + + case FLAGS_SUB8: + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Carry is always zero*/ + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + return; + + case FLAGS_SUB8: + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} + +static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} + +static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop, jump_uop2 = -1; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Carry is always zero, so test zero only*/ + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + break; + + case FLAGS_SUB8: + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop, jump_uop2 = -1; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Carry is always zero, so test zero only*/ + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + break; + + case FLAGS_SUB8: + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); +} + +static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + break; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + break; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + break; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + break; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} + +static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} + +static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: + /*V flag is always clear. Condition is true if N is set*/ + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + break; + case FLAGS_ZN16: + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + break; + case FLAGS_ZN32: + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_SUB8: case FLAGS_DEC8: + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: case FLAGS_DEC16: + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: case FLAGS_DEC32: + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_ZN8: + /*V flag is always clear. Condition is true if N is set*/ + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + break; + case FLAGS_ZN16: + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + break; + case FLAGS_ZN32: + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_SUB8: case FLAGS_DEC8: + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: case FLAGS_DEC16: + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: case FLAGS_DEC32: + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} + +static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop, jump_uop2 = -1; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_SUB8: case FLAGS_DEC8: + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: case FLAGS_DEC16: + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: case FLAGS_DEC32: + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); +} +static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +{ + int jump_uop, jump_uop2 = -1; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) + { + case FLAGS_SUB8: case FLAGS_DEC8: + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: case FLAGS_DEC16: + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: case FLAGS_DEC32: + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); +} + +#define ropJ(cond) \ +uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); \ + ropJ ## cond ## _common(block, ir, op_pc+1, offset); \ + \ + return op_pc+1; \ +} \ +uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); \ + ropJ ## cond ## _common(block, ir, op_pc+2, offset); \ + \ + return op_pc+2; \ +} \ +uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + uint32_t offset = fastreadl(cs + op_pc); \ + ropJ ## cond ## _common(block, ir, op_pc+4, offset); \ + \ + return op_pc+4; \ +} + +ropJ(O) +ropJ(NO) +ropJ(B) +ropJ(NB) +ropJ(E) +ropJ(NE) +ropJ(BE) +ropJ(NBE) +ropJ(S) +ropJ(NS) +ropJ(P) +ropJ(NP) +ropJ(L) +ropJ(NL) +ropJ(LE) +ropJ(NLE) + + +uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + int jump_uop; + + if (op_32 & 0x200) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); + uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); + + return op_pc+1; +} + +uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + int jump_uop; + + if (op_32 & 0x200) + { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } + else + { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); + + return op_pc+1; +} + +uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + int jump_uop, jump_uop2; + + if (op_32 & 0x200) + { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } + else + { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); + uop_set_jump_dest(ir, jump_uop2); + + return op_pc+1; +} +uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + int jump_uop, jump_uop2; + + if (op_32 & 0x200) + { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } + else + { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_set_jump_dest(ir, jump_uop); + uop_set_jump_dest(ir, jump_uop2); + + return op_pc+1; +} diff --git a/src/codegen_ops_branch.h b/src/codegen_ops_branch.h new file mode 100644 index 0000000..a67a2b5 --- /dev/null +++ b/src/codegen_ops_branch.h @@ -0,0 +1,69 @@ +uint32_t ropJB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJNS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJNS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index aa52e03..26422d8 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -88,9 +88,13 @@ enum IREG_BH = IREG_EBX + IREG_SIZE_BH, IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, - + IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W, + IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W, + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, - + IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B, + IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B, + IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, From 8a19e5634035a9818c7a31572eb2be2f09fc5da0 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 12 Sep 2018 20:16:27 +0100 Subject: [PATCH 032/181] Added recompiled versions of INC and DEC. --- src/codegen_backend_arm64_uops.c | 8 ++ src/codegen_backend_arm_uops.c | 8 ++ src/codegen_backend_x86-64_uops.c | 8 ++ src/codegen_backend_x86_uops.c | 8 ++ src/codegen_ops.c | 8 +- src/codegen_ops_arith.c | 127 ++++++++++++++++++++++++++++ src/codegen_ops_arith.h | 9 ++ src/codegen_ops_misc.c | 135 ++++++++++++++++++++++++++++-- 8 files changed, 298 insertions(+), 13 deletions(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index ebef0fc..1c29270 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -195,6 +195,13 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm64_call(block, uop->p); + + return 0; +} + static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -1413,6 +1420,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 427da2e..6a65d3b 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -268,6 +268,13 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm_call(block, uop->p); + + return 0; +} + static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -1493,6 +1500,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 59f78b3..9e14a0b 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -149,6 +149,13 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +{ + host_x86_CALL(block, uop->p); + + return 0; +} + static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -1205,6 +1212,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 4f1ceb8..5bca500 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -159,6 +159,13 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +{ + host_x86_CALL(block, uop->p); + + return 0; +} + static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -1198,6 +1205,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, diff --git a/src/codegen_ops.c b/src/codegen_ops.c index ff7df3d..d4bfd76 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -20,7 +20,7 @@ RecompOpFn recomp_opcodes[512] = /*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, /*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL, /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, @@ -33,7 +33,7 @@ RecompOpFn recomp_opcodes[512] = /*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_16, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, ropINCDEC, ropFF_16, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -42,7 +42,7 @@ RecompOpFn recomp_opcodes[512] = /*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, /*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL, /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, @@ -55,7 +55,7 @@ RecompOpFn recomp_opcodes[512] = /*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFF_32 +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, ropINCDEC, ropFF_32 }; diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index 7331afc..1a9c8d1 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -1330,3 +1330,130 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_flags_changed = 1; return op_pc + 2; } + +static void rebuild_c(ir_data_t *ir) +{ + int needs_rebuild = 1; + + if (codegen_flags_changed) + { + switch (cpu_state.flags_op) + { + case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32: + case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: + needs_rebuild = 0; + break; + } + } + + if (needs_rebuild) + { + uop_CALL_FUNC(ir, flags_rebuild_c); + } +} + +uint32_t ropINC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); + uop_ADD_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); + uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + codegen_flags_changed = 1; + + return op_pc; +} +uint32_t ropINC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); + uop_ADD_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); + uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + codegen_flags_changed = 1; + + return op_pc; +} + +uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); + uop_SUB_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); + uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + codegen_flags_changed = 1; + + return op_pc; +} +uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); + uop_SUB_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); + uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + codegen_flags_changed = 1; + + return op_pc; +} + +uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOVZX(ir, IREG_flags_op1, IREG_8(fetchdat & 7)); + if (fetchdat & 0x38) + { + uop_SUB_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); + } + else + { + uop_ADD_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); + } + uop_MOVZX(ir, IREG_flags_res, IREG_8(fetchdat & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + + if (fetchdat & 0x38) + { + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); + } + else + { + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); + } + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + if (fetchdat & 0x38) + { + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); + } + else + { + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); + } + } + + return op_pc+1; +} diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index 2faa55d..75a70b2 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -33,3 +33,12 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + + +uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropINC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropINC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index 01c404f..999e17c 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -238,28 +238,97 @@ uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return 0; } +static void rebuild_c(ir_data_t *ir) +{ + int needs_rebuild = 1; + + if (codegen_flags_changed) + { + switch (cpu_state.flags_op) + { + case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32: + case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: + needs_rebuild = 0; + break; + } + } + + if (needs_rebuild) + { + uop_CALL_FUNC(ir, flags_rebuild_c); + } +} + uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + x86seg *target_seg = NULL; int src_reg, sp_reg; - if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) return 0; - + if ((fetchdat & 0xc0) == 0xc0) src_reg = IREG_16(fetchdat & 7); else { - x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); + if (!(fetchdat & 0x30)) /*INC/DEC*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); src_reg = IREG_temp0_W; } switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_ADD_IMM(ir, src_reg, src_reg, 1); + uop_MOVZX(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + } + else + { + uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + } + return op_pc+1; + + case 0x08: /*DEC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_SUB_IMM(ir, src_reg, src_reg, 1); + uop_MOVZX(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + } + else + { + uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + } + return op_pc+1; + case 0x10: /*CALL*/ if ((fetchdat & 0xc0) == 0xc0) uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -286,26 +355,74 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + x86seg *target_seg = NULL; int src_reg, sp_reg; - if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) return 0; if ((fetchdat & 0xc0) == 0xc0) src_reg = IREG_32(fetchdat & 7); else { - x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); + if (!(fetchdat & 0x30)) /*INC/DEC*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); src_reg = IREG_temp0; } switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_ADD_IMM(ir, src_reg, src_reg, 1); + uop_MOV(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + } + else + { + uop_ADD_IMM(ir, IREG_temp1, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + } + return op_pc+1; + + case 0x08: /*DEC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) + { + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_SUB_IMM(ir, src_reg, src_reg, 1); + uop_MOV(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + } + else + { + uop_SUB_IMM(ir, IREG_temp1, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + } + return op_pc+1; + case 0x10: /*CALL*/ if ((fetchdat & 0xc0) == 0xc0) uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); From 1aadfd436d69d35a1ff641527c75448da842ef57 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 23 Sep 2018 21:45:12 +0100 Subject: [PATCH 033/181] Added recompiled versions of CBW, CDQ, CWD, CWDE and MOVSX. --- src/codegen_backend_arm64_ops.c | 6 +++ src/codegen_backend_arm64_ops.h | 2 + src/codegen_backend_arm64_uops.c | 33 +++++++++++++++ src/codegen_backend_arm_ops.c | 11 +++++ src/codegen_backend_arm_ops.h | 3 ++ src/codegen_backend_arm_uops.c | 33 +++++++++++++++ src/codegen_backend_x86-64_ops.c | 13 ++++++ src/codegen_backend_x86-64_ops.h | 4 ++ src/codegen_backend_x86-64_uops.c | 22 ++++++++++ src/codegen_backend_x86_ops.c | 13 ++++++ src/codegen_backend_x86_ops.h | 4 ++ src/codegen_backend_x86_uops.c | 22 ++++++++++ src/codegen_ir_defs.h | 3 ++ src/codegen_ops.c | 8 ++-- src/codegen_ops_misc.c | 25 ++++++++++++ src/codegen_ops_misc.h | 5 +++ src/codegen_ops_mov.c | 67 +++++++++++++++++++++++++++++++ src/codegen_ops_mov.h | 4 ++ 18 files changed, 274 insertions(+), 4 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 91e49e0..cab45ac 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -71,6 +71,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDRB_IMM_W (0x0e5 << 22) #define OPCODE_LDRH_IMM (0x1e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) +#define OPCODE_SBFX (0x04c << 22) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) #define OPCODE_STR_IMM_Q (0x3e4 << 22) @@ -640,6 +641,11 @@ void host_arm64_RET(codeblock_t *block, int reg) codegen_addlong(block, OPCODE_RET | Rn(reg)); } +void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +{ + codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); +} + void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { if (!in_range7_x(offset)) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 35d5044..2c47509 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -83,6 +83,8 @@ void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ void host_arm64_RET(codeblock_t *block, int reg); +void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); + void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 1c29270..b98084e 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -896,6 +896,38 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_arm64_SBFX(block, dest_reg, src_reg, 0, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_SBFX(block, dest_reg, src_reg, 8, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_arm64_SBFX(block, dest_reg, src_reg, 0, 16); + } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_SBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1448,6 +1480,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 66941ce..110ddd5 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -89,6 +89,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDRH_REG 0xe19000b0 #define OPCODE_STRH_IMM 0xe1c000b0 #define OPCODE_STRH_REG 0xe18000b0 +#define OPCODE_SXTB 0xe6af0070 +#define OPCODE_SXTH 0xe6bf0070 #define OPCODE_UADD8 0xe6500f90 #define OPCODE_UADD16 0xe6500f10 #define OPCODE_USUB8 0xe6500ff0 @@ -664,6 +666,15 @@ void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } +void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_SXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} +void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +{ + codegen_addlong(block, OPCODE_SXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); +} + void host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) { uint32_t arm_imm; diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 6dcb29e..7df158b 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -99,6 +99,9 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); +void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); + void host_arm_TST_IMM(codeblock_t *block, int src_reg1, uint32_t imm); void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 6a65d3b..5d87692 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -970,6 +970,38 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_arm_SXTB(block, dest_reg, src_reg, 0); + } + else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) + { + host_arm_SXTB(block, dest_reg, src_reg, 8); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_arm_SXTH(block, dest_reg, src_reg, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_arm_SXTB(block, REG_TEMP, src_reg, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) + { + host_arm_SXTB(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1528,6 +1560,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 6de5334..45fde94 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -812,6 +812,19 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } +void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} + void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 2bef40c..85ec419 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -86,6 +86,10 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); +void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 9e14a0b..773349d 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -801,6 +801,27 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); return 0; } +static int codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); + } + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1240,6 +1261,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index b61abd1..355b8f8 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -691,6 +691,19 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } +void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} + void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 6fa0a97..7bf81ed 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -88,6 +88,10 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); +void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 5bca500..e2d64ed 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -798,6 +798,27 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); return 0; } +static int codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) + { + host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); + } + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + return 0; +} static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1233,6 +1254,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_ADD & UOP_MASK] = codegen_ADD, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 22b1e70..591a6df 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -60,6 +60,8 @@ #define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) /*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/ #define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) +/*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/ +#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) /*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) /*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ @@ -435,6 +437,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) #define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) #define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) #define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index d4bfd76..a33b4ba 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -26,7 +26,7 @@ RecompOpFn recomp_opcodes[512] = /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W, -/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropCBW, ropCWD, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, @@ -48,7 +48,7 @@ RecompOpFn recomp_opcodes[512] = /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L, -/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropCWDE, ropCDQ, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, @@ -76,7 +76,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -98,7 +98,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index 999e17c..c0bb217 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -451,3 +451,28 @@ uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc { return op_pc; } + +uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOVSX(ir, IREG_AX, IREG_AL); + + return op_pc; +} +uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31); + + return op_pc; +} +uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15); + + return op_pc; +} +uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOVSX(ir, IREG_EAX, IREG_AX); + + return op_pc; +} diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h index 832c747..c20df48 100644 --- a/src/codegen_ops_misc.h +++ b/src/codegen_ops_misc.h @@ -9,3 +9,8 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 274adcd..26ee1a1 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -459,6 +459,73 @@ uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W); + } + + return op_pc + 1; +} + uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index c6c418d..90c6eb8 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -25,6 +25,10 @@ uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 592b07be638bac354547929accdd1c77174f8522 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 29 Sep 2018 17:42:44 +0100 Subject: [PATCH 034/181] Added recompiled versions of JMP indirect, JMP far, RETF, LxS, XLAT and LEAVE. --- src/codegen_backend_arm64_uops.c | 39 +++++++++ src/codegen_backend_arm_uops.c | 39 +++++++++ src/codegen_backend_x86-64_uops.c | 43 ++++++++++ src/codegen_backend_x86_uops.c | 39 +++++++++ src/codegen_ir_defs.h | 27 ++++-- src/codegen_ops.c | 16 ++-- src/codegen_ops_jump.c | 136 ++++++++++++++++++++++++++++++ src/codegen_ops_jump.h | 9 ++ src/codegen_ops_misc.c | 83 +++++++++++++++++- src/codegen_ops_misc.h | 11 +++ src/codegen_ops_mov.c | 14 +++ src/codegen_ops_mov.h | 2 + src/codegen_ops_stack.c | 33 ++++++++ src/codegen_ops_stack.h | 3 + 14 files changed, 475 insertions(+), 19 deletions(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index b98084e..1e8ffb3 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -602,6 +602,36 @@ static int codegen_JMP(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) + { + host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); + } + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + + return 0; +} +static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); @@ -690,6 +720,8 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { host_arm64_call(block, codegen_mem_load_byte); @@ -763,6 +795,8 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) int src_size = IREG_GET_SIZE(uop->src_reg_c_real); host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); if (REG_IS_B(src_size)) { host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); @@ -1460,6 +1494,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 5d87692..9b21d04 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -676,6 +676,36 @@ static int codegen_JMP(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_ARG0, src_reg, 0); + } + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + + return 0; +} +static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); @@ -761,6 +791,8 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); @@ -832,6 +864,8 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) int src_size = IREG_GET_SIZE(uop->src_reg_c_real); host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); if (REG_IS_B(src_size)) { host_arm_MOV_REG(block, REG_R1, src_reg); @@ -1540,6 +1574,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 773349d..bef4bcb 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -531,6 +531,40 @@ static int codegen_JMP(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) + { +#if WIN64 + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); +#else + host_x86_MOV16_REG_REG(block, REG_EDI, src_reg); +#endif + } + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + + return 0; +} +static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { #if WIN64 @@ -624,6 +658,8 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); if (REG_IS_B(dest_size)) { host_x86_CALL(block, codegen_mem_load_byte); @@ -729,6 +765,8 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) int src_size = IREG_GET_SIZE(uop->src_reg_c_real); host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); if (REG_IS_B(src_size)) { host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); @@ -1241,6 +1279,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e2d64ed..235176d 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -542,6 +542,36 @@ static int codegen_JMP(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) + { + host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); + } + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + + return 0; +} +static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; +} +static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; +} + static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); @@ -622,6 +652,8 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); if (REG_IS_B(dest_size)) { host_x86_CALL(block, codegen_mem_load_byte); @@ -689,6 +721,8 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) int src_size = IREG_GET_SIZE(uop->src_reg_c_real); host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); if (REG_IS_B(src_size)) { host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); @@ -1234,6 +1268,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 591a6df..c0b23c2 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -37,10 +37,10 @@ #define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01) #define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02) #define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03) -#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08) -#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09) -#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a) -#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b) +#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER) #define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) /*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/ #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) @@ -333,6 +333,17 @@ static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_re uop->src_reg_c = codegen_reg_read(src_reg_c); } +static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->imm_data = imm; +} + static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) { uop_t *uop = uop_alloc(ir); @@ -377,7 +388,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, uop->imm_data = imm; } -#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1_arg(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) +#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) @@ -427,9 +438,11 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) #define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) -#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg) +#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset) #define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) -#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg) +#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset) #define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) #define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) #define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index a33b4ba..188e284 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -30,9 +30,9 @@ RecompOpFn recomp_opcodes[512] = /*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, -/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, +/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES_16, ropLDS_16, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, ropRETF_imm_16, ropRETF_16, NULL, NULL, NULL, NULL, +/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, ropJMP_far_16, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, ropINCDEC, ropFF_16, /*32-bit data*/ @@ -52,9 +52,9 @@ RecompOpFn recomp_opcodes[512] = /*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, -/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, +/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES_32, ropLDS_32, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, ropRETF_imm_32, ropRETF_32, NULL, NULL, NULL, NULL, +/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, ropJMP_far_32, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, ropINCDEC, ropFF_32 }; @@ -76,7 +76,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, +/*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -98,7 +98,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, +/*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index 8ae6816..1d677d2 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -2,6 +2,7 @@ #include "x86.h" #include "386_common.h" +#include "386.h" #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" @@ -30,6 +31,33 @@ uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return -1; } +uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t new_pc = fastreadw(cs + op_pc); + uint16_t new_cs = fastreadw(cs + op_pc + 2); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_pc, new_pc); + uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); + uop_CALL_FUNC(ir, loadcsjmp); + + return -1; +} +uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t new_pc = fastreadl(cs + op_pc); + uint16_t new_cs = fastreadw(cs + op_pc + 4); + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_pc, new_pc); + uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); + uop_CALL_FUNC(ir, loadcsjmp); + + return -1; +} + uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); @@ -128,3 +156,111 @@ uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 return -1; } + +uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((msw&1) && !(eflags&VM_FLAG)) + return 0; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + { + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); + } + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); + } + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 4); + + return -1; +} +uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((msw&1) && !(eflags&VM_FLAG)) + return 0; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + { + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); + } + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); + } + uop_MOV(ir, IREG_pc, IREG_temp0); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 8); + + return -1; +} + +uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t offset; + + if ((msw&1) && !(eflags&VM_FLAG)) + return 0; + + offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + { + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); + } + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); + } + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 4+offset); + + return -1; +} +uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t offset; + + if ((msw&1) && !(eflags&VM_FLAG)) + return 0; + + offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + { + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); + } + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); + } + uop_MOV(ir, IREG_pc, IREG_temp0); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 8+offset); + + return -1; +} diff --git a/src/codegen_ops_jump.h b/src/codegen_ops_jump.h index ee6a591..db4c95c 100644 --- a/src/codegen_ops_jump.h +++ b/src/codegen_ops_jump.h @@ -2,6 +2,9 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); @@ -10,3 +13,9 @@ uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index c0bb217..e3635e3 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -3,6 +3,7 @@ #include "x86.h" #include "x86_flags.h" #include "386_common.h" +#include "386.h" #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" @@ -263,12 +264,16 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe { x86seg *target_seg = NULL; int src_reg, sp_reg; - - if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) + + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) return 0; if ((fetchdat & 0xc0) == 0xc0) + { + if ((fetchdat & 0x38) == 0x28) + return 0; src_reg = IREG_16(fetchdat & 7); + } else { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -337,10 +342,18 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe SUB_SP(ir, 2); uop_MOVZX(ir, IREG_pc, src_reg); return -1; - + case 0x20: /*JMP*/ uop_MOVZX(ir, IREG_pc, src_reg); return -1; + + case 0x28: /*JMP far*/ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc); + uop_CALL_FUNC(ir, loadcsjmp); + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; case 0x30: /*PUSH*/ if ((fetchdat & 0xc0) == 0xc0) @@ -358,11 +371,15 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe x86seg *target_seg = NULL; int src_reg, sp_reg; - if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x30) + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) return 0; if ((fetchdat & 0xc0) == 0xc0) + { + if ((fetchdat & 0x38) == 0x28) + return 0; src_reg = IREG_32(fetchdat & 7); + } else { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -436,6 +453,14 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MOV(ir, IREG_pc, src_reg); return -1; + case 0x28: /*JMP far*/ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc); + uop_CALL_FUNC(ir, loadcsjmp); + uop_MOV(ir, IREG_pc, src_reg); + return -1; + case 0x30: /*PUSH*/ if ((fetchdat & 0xc0) == 0xc0) uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -476,3 +501,53 @@ uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet return op_pc; } + +#define ropLxS(name, seg) \ +uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ +} \ +uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ +} + +ropLxS(LDS, &cpu_state.seg_ds) +ropLxS(LES, &cpu_state.seg_es) +ropLxS(LFS, &cpu_state.seg_fs) +ropLxS(LGS, &cpu_state.seg_gs) +ropLxS(LSS, &cpu_state.seg_ss) diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h index c20df48..20f115d 100644 --- a/src/codegen_ops_misc.h +++ b/src/codegen_ops_misc.h @@ -14,3 +14,14 @@ uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropLDS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLDS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLFS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLFS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLGS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLGS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLSS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLSS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 26ee1a1..c33271f 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -696,3 +696,17 @@ uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc + 1; } + +uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + uop_MOVZX(ir, IREG_eaaddr, IREG_AL); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX); + if (!(op_32 & 0x200)) + uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + + uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr); + + return op_pc; +} diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index 90c6eb8..03a9cb8 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -39,3 +39,5 @@ uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c index befeb4e..fb63e1d 100644 --- a/src/codegen_ops_stack.c +++ b/src/codegen_ops_stack.c @@ -255,3 +255,36 @@ ROP_POP_SEG(DS, cpu_state.seg_ds) ROP_POP_SEG(ES, cpu_state.seg_es) ROP_POP_SEG(FS, cpu_state.seg_fs) ROP_POP_SEG(GS, cpu_state.seg_gs) + +uint32_t ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_BP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2); + uop_MOV(ir, IREG_BP, IREG_temp0_W); + + return op_pc; +} +uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP); + else + { + uop_MOVZX(ir, IREG_eaaddr, IREG_BP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + } + uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4); + uop_MOV(ir, IREG_EBP, IREG_temp0); + + return op_pc; +} diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 240cc1f..9af5d60 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -35,3 +35,6 @@ uint32_t ropPOP_DS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t ropPOP_ES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPOP_FS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPOP_GS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 94fe85b17e262c653f9b65240f78f7706f2cbd5c Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 29 Sep 2018 17:43:02 +0100 Subject: [PATCH 035/181] Fixed video clock on Cirrus Logic cards. --- src/vid_cl5429.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index f2e5b05..c9a20d5 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -555,7 +555,7 @@ void gd5429_recalctimings(svga_t *svga) vclk /= 3.0; break; } - svga->clock = cpuclock / vclk; + svga->clock = (cpuclock * (float)(1ull << 32)) / vclk; svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd5429->vram_mask : 0x3ffff; } From e9ff110021d5078c840468fd33cd803bc66ae4ff Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 30 Sep 2018 17:30:28 +0100 Subject: [PATCH 036/181] Fixed flags on register->register ADD/SUB opcode 00/01/28/29. Fixes rendering in Need For Speed II. --- src/codegen_ops_arith.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index 1a9c8d1..f4e4152 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -87,6 +87,7 @@ uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int dest_reg = fetchdat & 7; uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); } @@ -102,9 +103,9 @@ uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); } - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); codegen_flags_changed = 1; @@ -150,6 +151,7 @@ uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int dest_reg = fetchdat & 7; uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); } @@ -165,9 +167,9 @@ uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); } - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); codegen_flags_changed = 1; @@ -212,6 +214,7 @@ uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int dest_reg = fetchdat & 7; uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); } @@ -227,9 +230,9 @@ uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_temp1); } - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); codegen_flags_changed = 1; @@ -538,6 +541,7 @@ uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int dest_reg = fetchdat & 7; uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); } @@ -553,9 +557,9 @@ uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); } - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); codegen_flags_changed = 1; @@ -601,6 +605,7 @@ uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int dest_reg = fetchdat & 7; uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); } @@ -616,9 +621,10 @@ uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); } - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); codegen_flags_changed = 1; @@ -663,6 +669,7 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int dest_reg = fetchdat & 7; uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); } @@ -678,9 +685,10 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_temp1); } - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; From dbb01ef9e22263b6e26a9db929e5024aab1c85df Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 1 Oct 2018 21:02:40 +0100 Subject: [PATCH 037/181] Cleaned up x87 tag register handling. --- src/x87.c | 34 ++++++++++++++++++++--------- src/x87.h | 7 ++++-- src/x87_ops.h | 12 ++++++----- src/x87_ops_arith.h | 48 ++++++++++++++++++++--------------------- src/x87_ops_loadstore.h | 4 ++-- src/x87_ops_misc.h | 40 +++++++++++++++++----------------- 6 files changed, 82 insertions(+), 63 deletions(-) diff --git a/src/x87.c b/src/x87.c index 25ce726..625e56e 100644 --- a/src/x87.c +++ b/src/x87.c @@ -19,6 +19,11 @@ #include "x87.h" #include "386_common.h" +#define X87_TAG_VALID 0 +#define X87_TAG_ZERO 1 +#define X87_TAG_INVALID 2 +#define X87_TAG_EMPTY 3 + uint16_t x87_gettag() { uint16_t ret = 0; @@ -26,10 +31,14 @@ uint16_t x87_gettag() for (c = 0; c < 8; c++) { - if (cpu_state.tag[c] & TAG_UINT64) + if (cpu_state.tag[c] == TAG_EMPTY) + ret |= X87_TAG_EMPTY << (c * 2); + else if (cpu_state.tag[c] & TAG_UINT64) ret |= 2 << (c*2); + else if (cpu_state.ST[c] == 0.0) + ret |= X87_TAG_ZERO << (c * 2); else - ret |= (cpu_state.tag[c] << (c*2)); + ret |= X87_TAG_VALID << (c * 2); } return ret; @@ -37,14 +46,19 @@ uint16_t x87_gettag() void x87_settag(uint16_t new_tag) { - cpu_state.tag[0] = new_tag & 3; - cpu_state.tag[1] = (new_tag >> 2) & 3; - cpu_state.tag[2] = (new_tag >> 4) & 3; - cpu_state.tag[3] = (new_tag >> 6) & 3; - cpu_state.tag[4] = (new_tag >> 8) & 3; - cpu_state.tag[5] = (new_tag >> 10) & 3; - cpu_state.tag[6] = (new_tag >> 12) & 3; - cpu_state.tag[7] = (new_tag >> 14) & 3; + int c; + + for (c = 0; c < 8; c++) + { + int tag = (new_tag >> (c * 2)) & 3; + + if (tag == X87_TAG_EMPTY) + cpu_state.tag[c] = TAG_EMPTY; + else if (tag == 2) + cpu_state.tag[c] = TAG_VALID | TAG_UINT64; + else + cpu_state.tag[c] = TAG_VALID; + } } void x87_dumpregs() diff --git a/src/x87.h b/src/x87.h index 790b6eb..cd4ccbb 100644 --- a/src/x87.h +++ b/src/x87.h @@ -10,7 +10,7 @@ static inline void x87_set_mmx() static inline void x87_emms() { - *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; + *(uint64_t *)cpu_state.tag = 0; cpu_state.ismmx = 0; } @@ -19,5 +19,8 @@ void x87_settag(uint16_t new_tag); void x87_dumpregs(); void x87_reset(); +#define TAG_EMPTY 0 +#define TAG_VALID (1 << 0) /*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ -#define TAG_UINT64 (1 << 2) +#define TAG_UINT64 (1 << 7) + diff --git a/src/x87_ops.h b/src/x87_ops.h index dc15866..3756c19 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -40,7 +40,7 @@ static inline void x87_push(double i) { cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.ST[cpu_state.TOP] = i; - cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; } static inline void x87_push_u64(uint64_t i) @@ -55,13 +55,13 @@ static inline void x87_push_u64(uint64_t i) cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.ST[cpu_state.TOP] = td.d; - cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; } static inline double x87_pop() { double t = cpu_state.ST[cpu_state.TOP]; - cpu_state.tag[cpu_state.TOP&7] = 3; + cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; cpu_state.TOP=(cpu_state.TOP+1)&7; return t; } @@ -186,13 +186,15 @@ static inline void x87_ld_frstor(int reg) cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); - if (cpu_state.MM_w4[reg] == 0x5555 && cpu_state.tag[reg] == 2) + if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64)) { - cpu_state.tag[reg] = TAG_UINT64; cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; } else + { + cpu_state.tag[reg] = TAG_VALID; cpu_state.ST[reg] = x87_ld80(); + } } static inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h index 45077c7..4561c82 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -11,7 +11,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ ST(0) += use_var; \ if ((cpu_state.npxc >> 10) & 3) \ fesetround(FE_TONEAREST); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -48,7 +48,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), ST(0), use_var); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -60,7 +60,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), use_var, ST(0)); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -72,7 +72,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) *= use_var; \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ CLOCK_CYCLES(11); \ return 0; \ } \ @@ -84,7 +84,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) -= use_var; \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -96,7 +96,7 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) = use_var - ST(0); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } @@ -121,7 +121,7 @@ static int opFADD(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FADD\n"); ST(0) = ST(0) + ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -131,7 +131,7 @@ static int opFADDr(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FADD\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -141,7 +141,7 @@ static int opFADDP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FADDP\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(8); return 0; @@ -232,7 +232,7 @@ static int opFDIV(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIV\n"); x87_div(ST(0), ST(0), ST(fetchdat & 7)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -242,7 +242,7 @@ static int opFDIVr(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIV\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -252,7 +252,7 @@ static int opFDIVP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIVP\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(73); return 0; @@ -264,7 +264,7 @@ static int opFDIVR(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(0), ST(fetchdat&7), ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -274,7 +274,7 @@ static int opFDIVRr(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -284,7 +284,7 @@ static int opFDIVRP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(73); return 0; @@ -296,7 +296,7 @@ static int opFMUL(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FMUL\n"); ST(0) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(16); return 0; } @@ -306,7 +306,7 @@ static int opFMULr(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FMUL\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; CLOCK_CYCLES(16); return 0; } @@ -316,7 +316,7 @@ static int opFMULP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FMULP\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(16); return 0; @@ -328,7 +328,7 @@ static int opFSUB(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUB\n"); ST(0) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -338,7 +338,7 @@ static int opFSUBr(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUB\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -348,7 +348,7 @@ static int opFSUBP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUBP\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(8); return 0; @@ -360,7 +360,7 @@ static int opFSUBR(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUBR\n"); ST(0) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -370,7 +370,7 @@ static int opFSUBRr(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUBR\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -380,7 +380,7 @@ static int opFSUBRP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUBRP\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(8); return 0; diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h index bf9fc1f..7a0b938 100644 --- a/src/x87_ops_loadstore.h +++ b/src/x87_ops_loadstore.h @@ -96,7 +96,7 @@ static int opFILDiq_a16(uint32_t fetchdat) if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); x87_push((double)temp64); cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID | TAG_UINT64; CLOCK_CYCLES(10); return 0; @@ -112,7 +112,7 @@ static int opFILDiq_a32(uint32_t fetchdat) if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); x87_push((double)temp64); cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID | TAG_UINT64; CLOCK_CYCLES(10); return 0; diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 5f21a99..34a28d0 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -34,7 +34,7 @@ static int opFINIT(uint32_t fetchdat) cpu_state.npxc = 0x37F; cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); cpu_state.npxs = 0; - *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; + *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; cpu_state.ismmx = 0; CLOCK_CYCLES(17); @@ -47,7 +47,7 @@ static int opFFREE(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; if (fplog) pclog("FFREE\n"); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY; CLOCK_CYCLES(3); return 0; } @@ -278,7 +278,7 @@ static int FSAVE() cpu_state.npxc = 0x37F; cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); cpu_state.npxs = 0; - *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; + *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; cpu_state.ismmx = 0; @@ -369,7 +369,7 @@ static int opFCHS(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FCHS\n"); ST(0) = -ST(0); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(6); return 0; } @@ -380,7 +380,7 @@ static int opFABS(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FABS %f\n", ST(0)); ST(0) = fabs(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(3); return 0; } @@ -403,7 +403,7 @@ static int opFXAM(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FXAM %i %f\n", cpu_state.tag[cpu_state.TOP&7], ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); - if (cpu_state.tag[cpu_state.TOP&7] == 3) cpu_state.npxs |= (C0|C3); + if (cpu_state.tag[cpu_state.TOP&7] == TAG_EMPTY) cpu_state.npxs |= (C0|C3); else if (ST(0) == 0.0) cpu_state.npxs |= C3; else cpu_state.npxs |= C2; if (ST(0) < 0.0) cpu_state.npxs |= C1; @@ -477,7 +477,7 @@ static int opFLDZ(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLDZ\n"); x87_push(0.0); - cpu_state.tag[cpu_state.TOP&7] = 1; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(4); return 0; } @@ -488,7 +488,7 @@ static int opF2XM1(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("F2XM1\n"); ST(0) = pow(2.0, ST(0)) - 1.0; - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(200); return 0; } @@ -499,7 +499,7 @@ static int opFYL2X(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FYL2X\n"); ST(1) = ST(1) * (log(ST(0)) / log(2.0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(250); return 0; @@ -511,7 +511,7 @@ static int opFYL2XP1(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FYL2XP1\n"); ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(250); return 0; @@ -523,7 +523,7 @@ static int opFPTAN(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FPTAN\n"); ST(0) = tan(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; x87_push(1.0); cpu_state.npxs &= ~C2; CLOCK_CYCLES(235); @@ -536,7 +536,7 @@ static int opFPATAN(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FPATAN\n"); ST(1) = atan2(ST(1), ST(0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; + cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; x87_pop(); CLOCK_CYCLES(250); return 0; @@ -570,7 +570,7 @@ static int opFPREM(uint32_t fetchdat) if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; if (fplog) pclog("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; @@ -587,7 +587,7 @@ static int opFPREM1(uint32_t fetchdat) if (fplog) pclog("FPREM1 %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; if (fplog) pclog("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; @@ -603,7 +603,7 @@ static int opFSQRT(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSQRT\n"); ST(0) = sqrt(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(83); return 0; } @@ -616,7 +616,7 @@ static int opFSINCOS(uint32_t fetchdat) if (fplog) pclog("FSINCOS\n"); td = ST(0); ST(0) = sin(td); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; x87_push(cos(td)); cpu_state.npxs &= ~C2; CLOCK_CYCLES(330); @@ -629,7 +629,7 @@ static int opFRNDINT(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FRNDINT %g ", ST(0)); ST(0) = (double)x87_fround(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; if (fplog) pclog("%g\n", ST(0)); CLOCK_CYCLES(21); return 0; @@ -643,7 +643,7 @@ static int opFSCALE(uint32_t fetchdat) if (fplog) pclog("FSCALE\n"); temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; CLOCK_CYCLES(30); return 0; } @@ -654,7 +654,7 @@ static int opFSIN(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSIN\n"); ST(0) = sin(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -666,7 +666,7 @@ static int opFCOS(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FCOS\n"); ST(0) = cos(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + cpu_state.tag[cpu_state.TOP] = TAG_VALID; cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; From 78996b3e5c0175a48c51398552d0151eeedefea2 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 7 Oct 2018 22:02:31 +0100 Subject: [PATCH 038/181] Added recompiled register versions of FADD, FDIV, FDIVR, FMUL, FSUB and FSUBR. --- src/codegen.c | 4 +- src/codegen_backend.h | 7 +- src/codegen_backend_arm.c | 25 +- src/codegen_backend_arm64.c | 26 ++- src/codegen_backend_arm64_defs.h | 37 ++- src/codegen_backend_arm64_ops.c | 67 ++++++ src/codegen_backend_arm64_ops.h | 13 ++ src/codegen_backend_arm64_uops.c | 127 +++++++++++ src/codegen_backend_arm_defs.h | 18 ++ src/codegen_backend_arm_ops.c | 35 +++ src/codegen_backend_arm_ops.h | 7 + src/codegen_backend_arm_uops.c | 121 ++++++++++ src/codegen_backend_x86-64.c | 24 +- src/codegen_backend_x86-64.h | 2 + src/codegen_backend_x86-64_defs.h | 22 ++ src/codegen_backend_x86-64_ops.c | 115 ++++++++++ src/codegen_backend_x86-64_ops.h | 17 ++ src/codegen_backend_x86-64_uops.c | 134 +++++++++++ src/codegen_backend_x86.c | 34 ++- src/codegen_backend_x86_defs.h | 12 + src/codegen_backend_x86_ops.c | 95 ++++++++ src/codegen_backend_x86_ops.h | 17 ++ src/codegen_backend_x86_uops.c | 130 +++++++++++ src/codegen_ir_defs.h | 36 ++- src/codegen_ops.c | 95 ++++++++ src/codegen_ops.h | 8 +- src/codegen_ops_fpu_arith.c | 134 +++++++++++ src/codegen_ops_fpu_arith.h | 12 + src/codegen_reg.c | 364 ++++++++++++++++++++---------- src/codegen_reg.h | 46 +++- src/ibm.h | 16 +- 31 files changed, 1638 insertions(+), 162 deletions(-) create mode 100644 src/codegen_ops_fpu_arith.c create mode 100644 src/codegen_ops_fpu_arith.h diff --git a/src/codegen.c b/src/codegen.c index ee782d1..409221f 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -360,7 +360,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t case 0xd8: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = NULL;//recomp_opcodes_d8; + recomp_op_table = recomp_opcodes_d8; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -397,7 +397,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = NULL;//recomp_opcodes_dc; + recomp_op_table = recomp_opcodes_dc; opcode_shift = 3; opcode_mask = 0x1f; over = 1; diff --git a/src/codegen_backend.h b/src/codegen_backend.h index 0f73290..df6fcea 100644 --- a/src/codegen_backend.h +++ b/src/codegen_backend.h @@ -1,9 +1,9 @@ //#ifdef __amd64__ //#include "codegen_x86-64.h" -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 -#include "codegen_backend_x86.h" -#elif defined __amd64__ +#if defined __amd64__ #include "codegen_backend_x86-64.h" +#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 +#include "codegen_backend_x86.h" #elif defined __ARM_EABI__ #include "codegen_backend_arm.h" #elif defined __aarch64__ @@ -65,3 +65,4 @@ typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop); extern const uOpFn uop_handlers[]; extern int codegen_host_reg_list[CODEGEN_HOST_REGS]; +extern int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS]; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index fb2d6f2..3b9c5fe 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -6,6 +6,7 @@ #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" +#include "codegen_reg.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -35,6 +36,18 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_R11, }; +int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = +{ + REG_D8, + REG_D9, + REG_D10, + REG_D11, + REG_D12, + REG_D13, + REG_D14, + REG_D15 +}; + static void build_load_routine(codeblock_t *block, int size) { uint32_t *branch_offset; @@ -220,7 +233,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm_nop(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); while (block_pos != BLOCK_START) host_arm_nop(block); @@ -228,13 +241,19 @@ void codegen_backend_prologue(codeblock_t *block) /*Entry code*/ host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); - host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); + host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state); + if (block->flags & CODEBLOCK_HAS_FPU) + { + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); + host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); + host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + } } void codegen_backend_epilogue(codeblock_t *block) { - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20); + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); if (block_pos > ARM_LITERAL_POOL_OFFSET) diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 4ae98f0..57eb10b 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -6,6 +6,7 @@ #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" #include "codegen_backend_arm64_ops.h" +#include "codegen_reg.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -38,6 +39,18 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_X28 }; +int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = +{ + REG_V8, + REG_V9, + REG_V10, + REG_V11, + REG_V12, + REG_V13, + REG_V14, + REG_V15 +}; + static void build_load_routine(codeblock_t *block, int size) { uint32_t *branch_offset; @@ -237,7 +250,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_NOP(block); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64); host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); @@ -255,15 +268,22 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -48); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -64); offset = add_literal_q(block, (uintptr_t)&cpu_state); host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); + + if (block->flags & CODEBLOCK_HAS_FPU) + { + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); + host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + } } void codegen_backend_epilogue(codeblock_t *block) { - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64); host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index c818d89..207fd80 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -64,6 +64,39 @@ #define REG_X30 30 #define REG_XZR 31 +#define REG_V0 0 +#define REG_V1 1 +#define REG_V2 2 +#define REG_V3 3 +#define REG_V4 4 +#define REG_V5 5 +#define REG_V6 6 +#define REG_V7 7 +#define REG_V8 8 +#define REG_V9 9 +#define REG_V10 10 +#define REG_V11 11 +#define REG_V12 12 +#define REG_V13 13 +#define REG_V14 14 +#define REG_V15 15 +#define REG_V16 16 +#define REG_V17 17 +#define REG_V18 18 +#define REG_V19 19 +#define REG_V20 20 +#define REG_V21 21 +#define REG_V22 22 +#define REG_V23 23 +#define REG_V24 24 +#define REG_V25 25 +#define REG_V26 26 +#define REG_V27 27 +#define REG_V28 28 +#define REG_V29 29 +#define REG_V30 30 +#define REG_V31 31 + #define REG_SP 31 #define REG_ARG0 REG_X0 @@ -73,9 +106,11 @@ #define REG_CPUSTATE REG_X29 -#define REG_TEMP REG_X7 +#define REG_TEMP REG_X7 +#define REG_TEMP2 REG_X6 #define CODEGEN_HOST_REGS 10 +#define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index cab45ac..a7a3cd6 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -48,6 +48,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) #define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) +#define OPCODE_B (0x14 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) #define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) @@ -68,6 +69,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BFI (0x0cc << 22) #define OPCODE_LDR_IMM_W (0x2e5 << 22) +#define OPCODE_LDR_IMM_F64 (0x3f5 << 22) #define OPCODE_LDRB_IMM_W (0x0e5 << 22) #define OPCODE_LDRH_IMM (0x1e5 << 22) #define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) @@ -75,6 +77,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_STP_PREIDX_X (0x2a6 << 22) #define OPCODE_STR_IMM_W (0x2e4 << 22) #define OPCODE_STR_IMM_Q (0x3e4 << 22) +#define OPCODE_STR_IMM_F64 (0x3f4 << 22) #define OPCODE_STRB_IMM (0x0e4 << 22) #define OPCODE_STRH_IMM (0x1e4 << 22) #define OPCODE_UBFX (0x14c << 22) @@ -99,10 +102,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ASR (0x1ac02800) #define OPCODE_BLR (0xd63f0000) #define OPCODE_BR (0xd61f0000) +#define OPCODE_FADD_D (0x1e602800) +#define OPCODE_FDIV_D (0x1e601800) +#define OPCODE_FMUL_D (0x1e600800) +#define OPCODE_FSUB_D (0x1e603800) #define OPCODE_LDR_REG (0xb8606800) #define OPCODE_LDRB_REG (0x38606800) #define OPCODE_LDRH_REG (0x78606800) #define OPCODE_LDRX_REG_LSL3 (0xf8607800) +#define OPCODE_LDR_REG_F64_S (0xfc607800) #define OPCODE_LSL (0x1ac02000) #define OPCODE_LSR (0x1ac02400) #define OPCODE_NOP (0xd503201f) @@ -110,6 +118,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) #define OPCODE_STRH_REG (0x78206800) +#define OPCODE_STR_REG_F64_S (0xfc207800) #define DATPROC_SHIFT(sh) (sh << 10) #define DATPROC_IMM_SHIFT(sh) (sh << 22) @@ -124,6 +133,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define IMMS(imms) ((imms) << 10) #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) +#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) #define OFFSET12_B(offset) (offset << 10) #define OFFSET12_H(offset) ((offset >> 1) << 10) @@ -146,6 +156,16 @@ static int offset_is_19bit(int offset) return 1; } +/*Returns true if offset fits into 26 bits*/ +static int offset_is_26bit(int offset) +{ + if (offset >= (1 << (25+2))) + return 0; + if (offset < -(1 << (25+2))) + return 0; + return 1; +} + int add_literal(codeblock_t *block, uint32_t data) { if (literal_offset >= 4096) @@ -296,6 +316,15 @@ void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } +void host_arm64_B(codeblock_t *block, void *dest) +{ + int offset = (uintptr_t)dest - (uintptr_t)&block->data[block_pos]; + + if (!offset_is_26bit(offset)) + fatal("host_arm64_B - offset out of range %x\n", offset); + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); +} + void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); @@ -461,6 +490,26 @@ void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, in codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ @@ -515,6 +564,15 @@ void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offs codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } +void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); +} +void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} + void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { if (!in_range12_b(offset)) @@ -670,6 +728,15 @@ void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offse codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } +void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset) +{ + codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg)); +} +void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); +} + void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { if (!in_range12_b(offset)) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 2c47509..da83275 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -11,6 +11,8 @@ void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_ void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg); +void host_arm64_B(codeblock_t *block, void *dest); + void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); void host_arm64_BLR(codeblock_t *block, int addr_reg); @@ -49,6 +51,11 @@ void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, in void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -56,6 +63,9 @@ void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offs void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); +void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); + void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); @@ -91,6 +101,9 @@ void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int of void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); +void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset); +void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg); + void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 1e8ffb3..cb8e7cc 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1,6 +1,8 @@ #ifdef __aarch64__ #include "ibm.h" +#include "x86.h" +#include "386_common.h" #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" @@ -15,6 +17,7 @@ #define REG_IS_W(size) (size == IREG_SIZE_W) #define REG_IS_B(size) (size == IREG_SIZE_B) #define REG_IS_BH(size) (size == IREG_SIZE_BH) +#define REG_IS_D(size) (size == IREG_SIZE_D) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -595,6 +598,85 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm64_FADD_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FDIV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm64_FDIV_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm64_FMUL_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm64_FSUB_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) + fatal("codegen_FP_ENTER - out of range\n"); + + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); + + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); + + host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + + return 0; +} + static int codegen_JMP(codeblock_t *block, uop_t *uop) { host_arm64_jump(block, (uintptr_t)uop->p); @@ -1561,6 +1643,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + + [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [UOP_FMUL & UOP_MASK] = codegen_FMUL, + [UOP_FSUB & UOP_MASK] = codegen_FSUB }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) @@ -1584,6 +1673,21 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_double - not in range\n"); +} +void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); +} void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { @@ -1606,6 +1710,29 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); +} +void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); +} void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index e094838..0a246fa 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -24,6 +24,23 @@ #define REG_TEMP REG_R3 +#define REG_D0 0 +#define REG_D1 1 +#define REG_D2 2 +#define REG_D3 3 +#define REG_D4 4 +#define REG_D5 5 +#define REG_D6 6 +#define REG_D7 7 +#define REG_D8 8 +#define REG_D9 9 +#define REG_D10 10 +#define REG_D11 11 +#define REG_D12 12 +#define REG_D13 13 +#define REG_D14 14 +#define REG_D15 15 + #define REG_MASK_R0 (1 << REG_R0) #define REG_MASK_R1 (1 << REG_R1) #define REG_MASK_R2 (1 << REG_R2) @@ -45,6 +62,7 @@ REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) #define CODEGEN_HOST_REGS 7 +#define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 110ddd5..2146efe 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -97,6 +97,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_USUB16 0xe6500f70 #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 +#define OPCODE_VADD 0xee300b00 +#define OPCODE_VDIV 0xee800b00 +#define OPCODE_VLDR 0xed900b00 +#define OPCODE_VMUL 0xee200b00 +#define OPCODE_VSTR 0xed800b00 +#define OPCODE_VSUB 0xee300b40 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -724,4 +730,33 @@ void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } +void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if ((offset > 1020) || (offset & 3)) + fatal("VLDR bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); +} +void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) +{ + if ((offset > 1020) || (offset & 3)) + fatal("VSTR bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); +} +void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} + #endif \ No newline at end of file diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 7df158b..a446bf1 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -113,3 +113,10 @@ void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); + +void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); +void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 9b21d04..d09f0e3 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1,6 +1,8 @@ #ifdef __ARM_EABI__ #include "ibm.h" +#include "x86.h" +#include "386_common.h" #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" @@ -73,6 +75,7 @@ void host_arm_nop(codeblock_t *block) #define REG_IS_W(size) (size == IREG_SIZE_W) #define REG_IS_B(size) (size == IREG_SIZE_B) #define REG_IS_BH(size) (size == IREG_SIZE_BH) +#define REG_IS_D(size) (size == IREG_SIZE_D) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -669,6 +672,85 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm_VADD_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FDIV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm_VDIV_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm_VMUL_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm_VSUB_D(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_FP_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + + return 0; +} + static int codegen_JMP(codeblock_t *block, uop_t *uop) { host_arm_B(block, (uintptr_t)uop->p); @@ -1641,6 +1723,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + + [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [UOP_FMUL & UOP_MASK] = codegen_FMUL, + [UOP_FSUB & UOP_MASK] = codegen_FSUB }; void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) @@ -1660,6 +1749,18 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +{ + host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); +} +void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); +} void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { @@ -1685,6 +1786,26 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); +} +void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); +} void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index deda8ef..4fb6fe0 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -5,6 +5,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" +#include "codegen_reg.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -30,6 +31,17 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_EDX }; +int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = +{ + REG_XMM0, + REG_XMM1, + REG_XMM2, + REG_XMM3, + REG_XMM4, + REG_XMM5, + REG_XMM6 +}; + static void *mem_abrt_rout; static void build_load_routine(codeblock_t *block, int size) @@ -286,10 +298,16 @@ void codegen_backend_prologue(codeblock_t *block) addbyte(0x48); /*SUBL $40,%rsp*/ addbyte(0x83); addbyte(0xEC); - addbyte(0x28); + addbyte(0x38); addbyte(0x48); /*MOVL RBP, &cpu_state*/ addbyte(0xBD); addquad(((uintptr_t)&cpu_state) + 128); + if (block->flags & CODEBLOCK_HAS_FPU) + { + host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); + } } void codegen_backend_epilogue(codeblock_t *block) @@ -297,7 +315,7 @@ void codegen_backend_epilogue(codeblock_t *block) addbyte(0x48); /*ADDL $40,%rsp*/ addbyte(0x83); addbyte(0xC4); - addbyte(0x28); + addbyte(0x38); addbyte(0x41); /*POP R15*/ addbyte(0x5f); addbyte(0x41); /*POP R14*/ @@ -336,7 +354,7 @@ void codegen_backend_epilogue(codeblock_t *block) addbyte(0x48); /*ADDL $40,%rsp*/ addbyte(0x83); addbyte(0xC4); - addbyte(0x28); + addbyte(0x38); addbyte(0x41); /*POP R15*/ addbyte(0x5f); addbyte(0x41); /*POP R14*/ diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h index 6c0cfca..50797ef 100644 --- a/src/codegen_backend_x86-64.h +++ b/src/codegen_backend_x86-64.h @@ -1,3 +1,5 @@ +#include "codegen_backend_x86-64_defs.h" + #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff #define BLOCK_START 0 diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index ee6df65..8334b74 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -32,3 +32,25 @@ #define REG_R13 13 #define REG_R14 14 #define REG_R15 15 + +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 + +#define REG_XMM_TEMP REG_XMM7 + +#define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_FP_REGS 7 + +extern void *codegen_mem_load_byte; +extern void *codegen_mem_load_word; +extern void *codegen_mem_load_long; + +extern void *codegen_mem_store_byte; +extern void *codegen_mem_store_word; +extern void *codegen_mem_store_long; diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 45fde94..1fe0e58 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -212,6 +212,11 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } +void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) @@ -336,6 +341,11 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_JMP(codeblock_t *block, void *p) { jmp(block, (uintptr_t)p); @@ -599,6 +609,21 @@ void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) } } +void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } + else + { + codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) @@ -812,6 +837,86 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } +void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) +{ + if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); + + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} + +void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); + + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ +} + void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ @@ -874,6 +979,11 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); } +void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) @@ -1153,6 +1263,11 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } +void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 85ec419..5b16a0e 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -7,6 +7,8 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); @@ -25,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_JMP(codeblock_t *block, void *p); void host_x86_JNZ(codeblock_t *block, void *p); @@ -60,6 +64,8 @@ void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg); + void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); @@ -86,6 +92,13 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); +void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); + void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); @@ -101,6 +114,8 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); +void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); @@ -148,6 +163,8 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index bef4bcb..534bb91 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1,6 +1,8 @@ #ifdef __amd64__ #include "ibm.h" +#include "x86.h" +#include "386_common.h" #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" @@ -18,6 +20,7 @@ #define REG_IS_W(size) (size == IREG_SIZE_W) #define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) #define REG_IS_BH(size) (size == IREG_SIZE_BH) +#define REG_IS_D(size) (size == IREG_SIZE_D) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -524,6 +527,95 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_ADDSD_REG_REG(block, dest_reg, src_reg_b); + } + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FDIV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_DIVSD_REG_REG(block, dest_reg, src_reg_b); + } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_MULSD_REG_REG(block, dest_reg, src_reg_b); + } + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_SUBSD_REG_REG(block, dest_reg, src_reg_b); + } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + uint8_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_short(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +#if WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +#else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +#endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + + return 0; +} + static int codegen_JMP(codeblock_t *block, uop_t *uop) { host_x86_JMP(block, uop->p); @@ -1346,6 +1438,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + + [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [UOP_FMUL & UOP_MASK] = codegen_FMUL, + [UOP_FSUB & UOP_MASK] = codegen_FSUB }; void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) @@ -1356,6 +1455,19 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); } +void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOVQ_REG_ABS(block, host_reg, p); +} +void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); +} void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { @@ -1369,6 +1481,28 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOVQ_ABS_REG(block, p, host_reg); +} +void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 3, host_reg); +} void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 17f588f..d09bb21 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -5,6 +5,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" +#include "codegen_reg.h" #include "x86.h" #if defined(__linux__) || defined(__APPLE__) @@ -30,12 +31,23 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] = REG_EDX }; +int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = +{ + REG_XMM0, + REG_XMM1, + REG_XMM2, + REG_XMM3, + REG_XMM4, + REG_XMM5, + REG_XMM6 +}; + static void *mem_abrt_rout; static void build_load_routine(codeblock_t *block, int size) { uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *misaligned_offset = NULL; /*In - ESI = address Out - ECX = data, ESI = abrt*/ @@ -107,7 +119,7 @@ static void build_load_routine(codeblock_t *block, int size) static void build_store_routine(codeblock_t *block, int size) { uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *misaligned_offset = NULL; /*In - ECX = data, ESI = address Out - ESI = abrt @@ -253,18 +265,24 @@ void codegen_backend_prologue(codeblock_t *block) addbyte(0x55); /*PUSH EBP*/ addbyte(0x56); /*PUSH ESI*/ addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $32,%esp*/ + addbyte(0x83); /*SUBL $64,%esp*/ addbyte(0xEC); - addbyte(0x20); + addbyte(0x40); addbyte(0xBD); /*MOVL EBP, &cpu_state*/ addlong(((uintptr_t)&cpu_state) + 128); + if (block->flags & CODEBLOCK_HAS_FPU) + { + host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); + } } void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x83); /*ADDL $32,%esp*/ + addbyte(0x83); /*ADDL $64,%esp*/ addbyte(0xC4); - addbyte(0x20); + addbyte(0x40); addbyte(0x5f); /*POP EDI*/ addbyte(0x5e); /*POP ESI*/ addbyte(0x5d); /*POP EBP*/ @@ -287,9 +305,9 @@ void codegen_backend_epilogue(codeblock_t *block) addbyte(0xe8); /*CALL x86gpf*/ addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $32,%esp*/ + addbyte(0x83); /*ADDL $64,%esp*/ addbyte(0xC4); - addbyte(0x20); + addbyte(0x40); addbyte(0x5f); /*POP EDI*/ addbyte(0x5e); /*POP ESI*/ addbyte(0x5d); /*POP EBP*/ diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 37e4160..93d6569 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -10,7 +10,19 @@ #define REG_ESI 6 #define REG_EDI 7 +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 + +#define REG_XMM_TEMP REG_XMM7 + #define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_FP_REGS 7 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 355b8f8..3dad4db 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -185,6 +185,11 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } +void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg) @@ -304,6 +309,11 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_JMP(codeblock_t *block, void *p) { codegen_addbyte(block, 0xe9); /*JMP*/ @@ -515,6 +525,19 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) } } +void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg) +{ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } + else + { + codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ @@ -691,6 +714,68 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } +void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) +{ + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} + +void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ +} + void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ @@ -755,6 +840,11 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ } +void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) @@ -988,6 +1078,11 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } +void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 7bf81ed..d6ff697 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -8,6 +8,8 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); @@ -25,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_JMP(codeblock_t *block, void *p); void host_x86_JNZ(codeblock_t *block, void *p); @@ -59,6 +63,8 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg); + void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); @@ -88,6 +94,13 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); +void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); + void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); @@ -101,6 +114,8 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); @@ -147,6 +162,8 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 235176d..b153804 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1,6 +1,8 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 #include "ibm.h" +#include "x86.h" +#include "386_common.h" #include "codegen.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" @@ -28,6 +30,7 @@ #define REG_IS_W(size) (size == IREG_SIZE_W) #define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) #define REG_IS_BH(size) (size == IREG_SIZE_BH) +#define REG_IS_D(size) (size == IREG_SIZE_D) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -535,6 +538,91 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_ADDSD_REG_REG(block, dest_reg, src_reg_b); + } + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FDIV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_DIVSD_REG_REG(block, dest_reg, src_reg_b); + } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_MULSD_REG_REG(block, dest_reg, src_reg_b); + } + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) + { + host_x86_SUBSD_REG_REG(block, dest_reg, src_reg_b); + } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + uint8_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_short(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + + return 0; +} + static int codegen_JMP(codeblock_t *block, uop_t *uop) { host_x86_JMP(block, uop->p); @@ -1335,6 +1423,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + + [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [UOP_FMUL & UOP_MASK] = codegen_FMUL, + [UOP_FSUB & UOP_MASK] = codegen_FSUB }; void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) @@ -1345,6 +1440,19 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); } +void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOVQ_REG_ABS(block, host_reg, p); +} +void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); +} void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { @@ -1358,6 +1466,28 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOVQ_ABS_REG(block, p, host_reg); +} +void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 3, host_reg); +} void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index c0b23c2..e949bdf 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -78,7 +78,7 @@ /*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/ #define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) /*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/ -#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) +#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) /*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/ #define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) /*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/ @@ -151,7 +151,18 @@ /*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/ #define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) -#define UOP_MAX 0x72 +/*UOP_FP_ENTER - */ +#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) +/*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) +/*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82) +/*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/ +#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83) +/*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/ +#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) + +#define UOP_MAX 0x85 #define UOP_MASK 0xffff @@ -205,6 +216,15 @@ static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop) uop->jump_dest_uop = ir->wr_pos; } +static inline int uop_gen(uint32_t uop_type, ir_data_t *ir) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + + return ir->wr_pos-1; +} + static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) { uop_t *uop = uop_alloc(ir); @@ -433,6 +453,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b) #define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) +#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) + +#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; } while (0) + #define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) #define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) @@ -461,11 +488,16 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); +void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p); +void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx); void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg); +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg); void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 188e284..55916ee 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -4,6 +4,7 @@ #include "codegen_ops.h" #include "codegen_ops_arith.h" #include "codegen_ops_branch.h" +#include "codegen_ops_fpu_arith.h" #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" @@ -105,3 +106,97 @@ RecompOpFn recomp_opcodes_0f[512] = /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; + +RecompOpFn recomp_opcodes_d8[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, +/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, +/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, +}; + +RecompOpFn recomp_opcodes_dc[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, +/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, +/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, +}; diff --git a/src/codegen_ops.h b/src/codegen_ops.h index 1534a38..fbbaed4 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -9,12 +9,12 @@ typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t extern RecompOpFn recomp_opcodes[512]; extern RecompOpFn recomp_opcodes_0f[512]; -/*extern RecompOpFn recomp_opcodes_d8[512]; -extern RecompOpFn recomp_opcodes_d9[512]; +extern RecompOpFn recomp_opcodes_d8[512]; +/*extern RecompOpFn recomp_opcodes_d9[512]; extern RecompOpFn recomp_opcodes_da[512]; -extern RecompOpFn recomp_opcodes_db[512]; +extern RecompOpFn recomp_opcodes_db[512];*/ extern RecompOpFn recomp_opcodes_dc[512]; -extern RecompOpFn recomp_opcodes_dd[512]; +/*extern RecompOpFn recomp_opcodes_dd[512]; extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; extern RecompOpFn recomp_opcodes_REPE[512]; diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c new file mode 100644 index 0000000..4d2237b --- /dev/null +++ b/src/codegen_ops_fpu_arith.c @@ -0,0 +1,134 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "x87.h" +#include "codegen.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_fpu_arith.h" + +uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + + return op_pc; +} + +uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + + return op_pc; +} +uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + + return op_pc; +} + +uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + + return op_pc; +} + +uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + + return op_pc; +} +uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + + return op_pc; +} diff --git a/src/codegen_ops_fpu_arith.h b/src/codegen_ops_fpu_arith.h new file mode 100644 index 0000000..063f614 --- /dev/null +++ b/src/codegen_ops_fpu_arith.h @@ -0,0 +1,12 @@ +uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 36b5ad8..556dbbf 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -9,10 +9,22 @@ uint8_t reg_version_refcount[IREG_COUNT][256]; ir_reg_t invalid_ir_reg = {IREG_INVALID}; -ir_reg_t host_regs[CODEGEN_HOST_REGS]; -static uint8_t host_reg_dirty[CODEGEN_HOST_REGS]; +ir_reg_t _host_regs[CODEGEN_HOST_REGS]; +static uint8_t _host_reg_dirty[CODEGEN_HOST_REGS]; -static uint8_t host_regs_locked; +ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS]; +static uint8_t host_fp_reg_dirty[CODEGEN_HOST_FP_REGS]; + +typedef struct host_reg_set_t +{ + ir_reg_t *regs; + uint8_t *dirty; + int *reg_list; + uint16_t locked; + int nr_regs; +} host_reg_set_t; + +static host_reg_set_t host_reg_set, host_fp_reg_set; enum { @@ -20,70 +32,110 @@ enum REG_WORD, REG_DWORD, REG_QWORD, - REG_POINTER + REG_POINTER, + REG_FPU_ST_BYTE, + REG_FPU_ST_DOUBLE +}; + +enum +{ + REG_INTEGER, + REG_FP }; struct { int native_size; void *p; + int type; } ireg_data[IREG_COUNT] = { - [IREG_EAX] = {REG_DWORD, &EAX}, - [IREG_ECX] = {REG_DWORD, &ECX}, - [IREG_EDX] = {REG_DWORD, &EDX}, - [IREG_EBX] = {REG_DWORD, &EBX}, - [IREG_ESP] = {REG_DWORD, &ESP}, - [IREG_EBP] = {REG_DWORD, &EBP}, - [IREG_ESI] = {REG_DWORD, &ESI}, - [IREG_EDI] = {REG_DWORD, &EDI}, + [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER}, + [IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER}, + [IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER}, + [IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER}, + [IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER}, + [IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER}, + [IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER}, + [IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER}, - [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op}, - [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res}, - [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1}, - [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2}, + [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER}, + [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER}, + [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER}, + [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER}, - [IREG_pc] = {REG_DWORD, &cpu_state.pc}, - [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc}, + [IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER}, + [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER}, - [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr}, - [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg}, + [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER}, + [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER}, - [IREG_op32] = {REG_DWORD, &cpu_state.op32}, - [IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs}, + [IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER}, + [IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER}, - [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data}, + [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER}, - [IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins}, - [IREG_cycles] = {REG_DWORD, &cpu_state._cycles}, + [IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER}, + [IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER}, - [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base}, - [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base}, - [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base}, - [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base}, - [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base}, - [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base}, + [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER}, + [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER}, + [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER}, + [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER}, + [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER}, + [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER}, - [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg}, - [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg}, - [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg}, - [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg}, - [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg}, - [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg}, + [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER}, + [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER}, + [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER}, + [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER}, + [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER}, + [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER}, + + [IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER}, + + [IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + + [IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - [IREG_temp0] = {REG_DWORD, (void *)16}, - [IREG_temp1] = {REG_DWORD, (void *)20}, - [IREG_temp2] = {REG_DWORD, (void *)24}, - [IREG_temp3] = {REG_DWORD, (void *)28}, + [IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER}, + [IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER}, + [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER}, + [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER}, }; void codegen_reg_reset() { int c; - + + host_reg_set.regs = _host_regs; + host_reg_set.dirty = _host_reg_dirty; + host_reg_set.reg_list = codegen_host_reg_list; + host_reg_set.locked = 0; + host_reg_set.nr_regs = CODEGEN_HOST_REGS; + host_fp_reg_set.regs = host_fp_regs; + host_fp_reg_set.dirty = host_fp_reg_dirty; + host_fp_reg_set.reg_list = codegen_host_fp_reg_list; + host_fp_reg_set.locked = 0; + host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS; + for (c = 0; c < IREG_COUNT; c++) { reg_last_version[c] = 0; @@ -91,8 +143,13 @@ void codegen_reg_reset() } for (c = 0; c < CODEGEN_HOST_REGS; c++) { - host_regs[c] = invalid_ir_reg; - host_reg_dirty[c] = 0; + host_reg_set.regs[c] = invalid_ir_reg; + host_reg_set.dirty[c] = 0; + } + for (c = 0; c < CODEGEN_HOST_FP_REGS; c++) + { + host_fp_reg_set.regs[c] = invalid_ir_reg; + host_fp_reg_set.dirty[c] = 0; } } @@ -101,62 +158,104 @@ static inline int ir_reg_is_invalid(ir_reg_t ir_reg) return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } -static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg) +static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg) +{ + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER) + return &host_reg_set; + else + return &host_fp_reg_set; +} + +static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg) { switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { case REG_WORD: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n"); if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_16_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + codegen_direct_read_16_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); else - codegen_direct_read_16(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + codegen_direct_read_16(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; case REG_DWORD: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n"); if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_32_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + codegen_direct_read_32_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); else - codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + codegen_direct_read_32(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; + + case REG_FPU_ST_DOUBLE: + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_double(block, reg_set->reg_list[c], &cpu_state.ST[ir_reg.reg & 7]); + else + codegen_direct_read_st_double(block, reg_set->reg_list[c], &cpu_state.ST[0], ir_reg.reg & 7); break; default: fatal("codegen_reg_load - native_size=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size); } - host_regs[c] = ir_reg; + reg_set->regs[c] = ir_reg; + //pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version); } -static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate) +static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate) { - int ir_reg = IREG_GET_REG(host_regs[c].reg); + int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); void *p = ireg_data[ir_reg].p; switch (ireg_data[ir_reg].native_size) { case REG_BYTE: + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n"); if ((uintptr_t)p < 256) fatal("codegen_reg_writeback - REG_BYTE %p\n", p); - codegen_direct_write_8(block, p, codegen_host_reg_list[c]); + codegen_direct_write_8(block, p, reg_set->reg_list[c]); break; case REG_WORD: + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n"); if ((uintptr_t)p < 256) fatal("codegen_reg_writeback - REG_WORD %p\n", p); - codegen_direct_write_16(block, p, codegen_host_reg_list[c]); + codegen_direct_write_16(block, p, reg_set->reg_list[c]); break; case REG_DWORD: + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n"); if ((uintptr_t)p < 256) - codegen_direct_write_32_stack(block, (int)p, codegen_host_reg_list[c]); + codegen_direct_write_32_stack(block, (int)p, reg_set->reg_list[c]); else - codegen_direct_write_32(block, p, codegen_host_reg_list[c]); + codegen_direct_write_32(block, p, reg_set->reg_list[c]); break; case REG_POINTER: + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); if ((uintptr_t)p < 256) fatal("codegen_reg_writeback - REG_POINTER %p\n", p); - codegen_direct_write_ptr(block, p, codegen_host_reg_list[c]); + codegen_direct_write_ptr(block, p, reg_set->reg_list[c]); + break; + + case REG_FPU_ST_BYTE: + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c]); + else + codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]); + break; + + case REG_FPU_ST_DOUBLE: + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c]); + else + codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]); break; default: @@ -164,8 +263,8 @@ static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate) } if (invalidate) - host_regs[c] = invalid_ir_reg; - host_reg_dirty[c] = 0; + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) @@ -173,7 +272,8 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ int c; int dest_reference = 0; - host_regs_locked = 0; + host_reg_set.locked = 0; + host_fp_reg_set.locked = 0; /* pclog("alloc_register: dst=%i.%i src_a=%i.%i src_b=%i.%i\n", dest_reg_a.reg, dest_reg_a.version, src_reg_a.reg, src_reg_a.version, @@ -190,82 +290,88 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ } for (c = 0; c < CODEGEN_HOST_REGS; c++) { - if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_a.reg)) + host_reg_set_t *reg_set = get_reg_set(src_reg_a); + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_a.reg)) { - if (host_regs[c].version != src_reg_a.version) + if (reg_set->regs[c].version != src_reg_a.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_a.version\n"); - host_regs_locked |= (1 << c); + reg_set->locked |= (1 << c); } - if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_b.reg)) + reg_set = get_reg_set(src_reg_b); + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_b.reg)) { - if (host_regs[c].version != src_reg_b.version) + if (reg_set->regs[c].version != src_reg_b.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n"); - host_regs_locked |= (1 << c); + reg_set->locked |= (1 << c); } - if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_c.reg)) + reg_set = get_reg_set(src_reg_c); + if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_c.reg)) { - if (host_regs[c].version != src_reg_c.version) + if (reg_set->regs[c].version != src_reg_c.version) fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_c.version\n"); - host_regs_locked |= (1 << c); + reg_set->locked |= (1 << c); } - if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(dest_reg_a.reg)) + reg_set = get_reg_set(dest_reg_a); + if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dest_reg_a.reg)) { - if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] == dest_reference)) - host_regs_locked |= (1 << c); + if (reg_set->regs[c].version == dest_reg_a.version || (reg_set->regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == dest_reference)) + reg_set->locked |= (1 << c); else - fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", host_regs[c].version, dest_reg_a.version, dest_reference); + fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, dest_reg_a.version, dest_reference); } } } ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) { + host_reg_set_t *reg_set = get_reg_set(ir_reg); int c; /*Search for required register*/ - for (c = 0; c < CODEGEN_HOST_REGS; c++) + for (c = 0; c < reg_set->nr_regs; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && host_regs[c].version == ir_reg.version) + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version) break; - if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]) + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]) fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); } - if (c == CODEGEN_HOST_REGS) + if (c == reg_set->nr_regs) { /*No unused registers. Search for an unlocked register*/ - for (c = 0; c < CODEGEN_HOST_REGS; c++) + for (c = 0; c < reg_set->nr_regs; c++) { - if (!(host_regs_locked & (1 << c))) + if (!(reg_set->locked & (1 << c))) break; } - if (c == CODEGEN_HOST_REGS) + if (c == reg_set->nr_regs) fatal("codegen_reg_alloc_read_reg - out of registers\n"); - if (host_reg_dirty[c]) - codegen_reg_writeback(block, c, 1); + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, c, 1); // pclog(" load %i\n", c); - codegen_reg_load(block, c, ir_reg); - host_regs_locked |= (1 << c); + codegen_reg_load(reg_set, block, c, ir_reg); + reg_set->locked |= (1 << c); // fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c); // codegen_reg_writeback(block, c); - host_reg_dirty[c] = 0; + reg_set->dirty[c] = 0; } // else // pclog(" already loaded %i\n", c); - reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]--; - if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] < 0) + reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]--; + if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] < 0) fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); if (host_reg_idx) *host_reg_idx = c; // pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], host_regs[c].reg,host_regs[c].version, c); - return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); + return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { + host_reg_set_t *reg_set = get_reg_set(ir_reg); int c; if (IREG_GET_SIZE(ir_reg.reg) != IREG_SIZE_L) @@ -278,85 +384,107 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) codegen_reg_alloc_read_reg(block, parent_reg, &c); - if (IREG_GET_REG(host_regs[c].reg) != IREG_GET_REG(ir_reg.reg) || host_regs[c].version != ir_reg.version-1) + if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version != ir_reg.version-1) fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, - host_regs[c].reg,host_regs[c].version, + reg_set->regs[c].reg,reg_set->regs[c].version, ir_reg.reg,ir_reg.version); - host_regs[c].reg = ir_reg.reg; - host_regs[c].version = ir_reg.version; - host_reg_dirty[c] = 1; + reg_set->regs[c].reg = ir_reg.reg; + reg_set->regs[c].version = ir_reg.version; + reg_set->dirty[c] = 1; // pclog(" codegen_reg_alloc_write_reg: partial %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); - return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); + return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } /*Search for previous version in host register*/ - for (c = 0; c < CODEGEN_HOST_REGS; c++) + for (c = 0; c < reg_set->nr_regs; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg)) + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { - if (host_regs[c].version == ir_reg.version-1) + if (reg_set->regs[c].version == ir_reg.version-1) { - if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] != 0) + if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] != 0) fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); break; } } } - if (c == CODEGEN_HOST_REGS) + if (c == reg_set->nr_regs) { /*Search for unused registers*/ - for (c = 0; c < CODEGEN_HOST_REGS; c++) + for (c = 0; c < reg_set->nr_regs; c++) { - if (ir_reg_is_invalid(host_regs[c])) + if (ir_reg_is_invalid(reg_set->regs[c])) break; } - if (c == CODEGEN_HOST_REGS) + if (c == reg_set->nr_regs) { /*No unused registers. Search for an unlocked register*/ - for (c = 0; c < CODEGEN_HOST_REGS; c++) + for (c = 0; c < reg_set->nr_regs; c++) { - if (!(host_regs_locked & (1 << c))) + if (!(reg_set->locked & (1 << c))) break; } - if (c == CODEGEN_HOST_REGS) + if (c == reg_set->nr_regs) fatal("codegen_reg_alloc_write_reg - out of registers\n"); - if (host_reg_dirty[c]) - codegen_reg_writeback(block, c, 1); + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, c, 1); } } - host_regs[c].reg = ir_reg.reg; - host_regs[c].version = ir_reg.version; - host_reg_dirty[c] = 1; + reg_set->regs[c].reg = ir_reg.reg; + reg_set->regs[c].version = ir_reg.version; + reg_set->dirty[c] = 1; // pclog(" codegen_reg_alloc_write_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]); - return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg); + return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) { + host_reg_set_t *reg_set; int c; - - for (c = 0; c < CODEGEN_HOST_REGS; c++) + + reg_set = &host_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { - if (!ir_reg_is_invalid(host_regs[c]) && host_reg_dirty[c]) + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { - codegen_reg_writeback(block, c, 0); + codegen_reg_writeback(reg_set, block, c, 0); + } + } + + reg_set = &host_fp_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) + { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) + { + codegen_reg_writeback(reg_set, block, c, 0); } } } void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) { + host_reg_set_t *reg_set; int c; - for (c = 0; c < CODEGEN_HOST_REGS; c++) + reg_set = &host_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { - if (!ir_reg_is_invalid(host_regs[c])) + if (!ir_reg_is_invalid(reg_set->regs[c])) { - codegen_reg_writeback(block, c, 1); + codegen_reg_writeback(reg_set, block, c, 1); + } + } + + reg_set = &host_fp_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) + { + if (!ir_reg_is_invalid(reg_set->regs[c])) + { + codegen_reg_writeback(reg_set, block, c, 1); } } } diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 26422d8..986f0aa 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -1,9 +1,9 @@ #ifndef _CODEGEN_REG_H_ #define _CODEGEN_REG_H_ -#define IREG_REG_MASK 0x3f -#define IREG_SIZE_SHIFT 6 -#define IREG_SIZE_MASK (3 << IREG_SIZE_SHIFT) +#define IREG_REG_MASK 0xff +#define IREG_SIZE_SHIFT 8 +#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT) #define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK) #define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK) @@ -12,6 +12,7 @@ #define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) #define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) #define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) +#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) enum { @@ -64,7 +65,33 @@ enum IREG_temp2 = 35, IREG_temp3 = 36, - IREG_COUNT, + IREG_FPU_TOP = 37, + + /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() + to access. + When CODEBLOCK_STATIC_TOP is set, the physical register number will be + used directly to index the stack. When it is clear, the difference + between the current value of TOP and the value when the block was + first compiled will be added to adjust for any changes in TOP.*/ + IREG_ST0 = 40, + IREG_ST1 = 41, + IREG_ST2 = 42, + IREG_ST3 = 43, + IREG_ST4 = 44, + IREG_ST5 = 45, + IREG_ST6 = 46, + IREG_ST7 = 47, + + IREG_tag0 = 48, + IREG_tag1 = 49, + IREG_tag2 = 50, + IREG_tag3 = 51, + IREG_tag4 = 52, + IREG_tag5 = 53, + IREG_tag6 = 54, + IREG_tag7 = 55, + + IREG_COUNT = 56, IREG_INVALID = 63, @@ -116,6 +143,11 @@ enum #define IREG_16(reg) ((reg) + IREG_AX) #define IREG_32(reg) ((reg) + IREG_EAX) +#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) +#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) + +#define IREG_TOP_diff_stack_offset 32 + static inline int ireg_seg_base(x86seg *seg) { if (seg == &cpu_state.seg_cs) @@ -139,13 +171,13 @@ extern uint8_t reg_version_refcount[IREG_COUNT][256]; typedef struct { - uint8_t reg; - uint8_t version; + uint16_t reg; + uint16_t version; } ir_reg_t; extern ir_reg_t invalid_ir_reg; -typedef uint8_t ir_host_reg_t; +typedef uint16_t ir_host_reg_t; #define REG_VERSION_MAX 250 diff --git a/src/ibm.h b/src/ibm.h index de79af6..6503b67 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -180,6 +180,12 @@ struct uint16_t old_npxc, new_npxc; x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs; + + union + { + uint32_t l; + uint16_t w; + } CR0; } cpu_state; #define cycles cpu_state._cycles @@ -239,14 +245,8 @@ uint8_t *pccache2; int loadseg(uint16_t seg, x86seg *s); void loadcs(uint16_t seg); -union -{ - uint32_t l; - uint16_t w; -} CR0; - -#define cr0 CR0.l -#define msw CR0.w +#define cr0 cpu_state.CR0.l +#define msw cpu_state.CR0.w uint32_t cr2, cr3, cr4; uint32_t dr[8]; From 305b6cc4fdd130989f0c1cf00350e9f8c7c16fb0 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 8 Oct 2018 21:44:30 +0100 Subject: [PATCH 039/181] Added recompiled register versions of FADDP, FDIVP, FDIVRP, FMULP, FSUBP and FSUBRP. --- src/codegen.c | 2 +- src/codegen_ops.c | 47 +++++++++++++++ src/codegen_ops.h | 4 +- src/codegen_ops_fpu_arith.c | 112 +++++++++++++++++++++++++++++------- src/codegen_ops_fpu_arith.h | 10 +++- src/x87.c | 2 +- src/x87_ops.h | 12 ++-- src/x87_ops_arith.h | 24 ++++---- src/x87_ops_loadstore.h | 16 +++--- src/x87_ops_misc.h | 44 +++++++------- 10 files changed, 199 insertions(+), 74 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 409221f..2f36a42 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -416,7 +416,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = NULL;//recomp_opcodes_de; + recomp_op_table = recomp_opcodes_de; opcode_mask = 0xff; over = 1; pc_off = -1; diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 55916ee..6fe6799 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -200,3 +200,50 @@ RecompOpFn recomp_opcodes_dc[512] = /*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, }; + +RecompOpFn recomp_opcodes_de[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, +/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, +/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, +}; diff --git a/src/codegen_ops.h b/src/codegen_ops.h index fbbaed4..432652d 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -14,9 +14,9 @@ extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_da[512]; extern RecompOpFn recomp_opcodes_db[512];*/ extern RecompOpFn recomp_opcodes_dc[512]; -/*extern RecompOpFn recomp_opcodes_dd[512]; +/*extern RecompOpFn recomp_opcodes_dd[512];*/ extern RecompOpFn recomp_opcodes_de[512]; -extern RecompOpFn recomp_opcodes_df[512]; +/*extern RecompOpFn recomp_opcodes_df[512]; extern RecompOpFn recomp_opcodes_REPE[512]; extern RecompOpFn recomp_opcodes_REPNE[512];*/ diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c index 4d2237b..507f937 100644 --- a/src/codegen_ops_fpu_arith.c +++ b/src/codegen_ops_fpu_arith.c @@ -5,10 +5,16 @@ #include "386_common.h" #include "x87.h" #include "codegen.h" +#include "codegen_accumulate.h" #include "codegen_ir.h" #include "codegen_ops.h" #include "codegen_ops_fpu_arith.h" +static void fpu_POP(ir_data_t *ir) +{ + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); +} + uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7; @@ -29,6 +35,17 @@ uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc; } +uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(ir); + + return op_pc; +} uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -40,6 +57,16 @@ uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet return op_pc; } +uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; @@ -50,16 +77,6 @@ uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc; } -uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = fetchdat & 7; - - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - - return op_pc; -} uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; @@ -70,6 +87,28 @@ uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } +uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(ir); + + return op_pc; +} +uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(ir); + + return op_pc; +} uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -91,6 +130,17 @@ uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc; } +uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(ir); + + return op_pc; +} uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -102,6 +152,16 @@ uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet return op_pc; } +uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; @@ -112,16 +172,6 @@ uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc; } -uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = fetchdat & 7; - - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - - return op_pc; -} uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = fetchdat & 7; @@ -132,3 +182,25 @@ uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } +uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(ir); + + return op_pc; +} +uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(ir); + + return op_pc; +} diff --git a/src/codegen_ops_fpu_arith.h b/src/codegen_ops_fpu_arith.h index 063f614..4e60233 100644 --- a/src/codegen_ops_fpu_arith.h +++ b/src/codegen_ops_fpu_arith.h @@ -1,12 +1,18 @@ uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); -uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); -uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/x87.c b/src/x87.c index 625e56e..44f22e0 100644 --- a/src/x87.c +++ b/src/x87.c @@ -70,7 +70,7 @@ void x87_dumpregs() } else { - pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); + pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP&7],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]); } pclog("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); diff --git a/src/x87_ops.h b/src/x87_ops.h index 3756c19..dd46f91 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -38,8 +38,8 @@ static inline void x87_checkexceptions() static inline void x87_push(double i) { - cpu_state.TOP=(cpu_state.TOP-1)&7; - cpu_state.ST[cpu_state.TOP] = i; + cpu_state.TOP--; + cpu_state.ST[cpu_state.TOP&7] = i; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; } @@ -53,16 +53,16 @@ static inline void x87_push_u64(uint64_t i) td.ll = i; - cpu_state.TOP=(cpu_state.TOP-1)&7; - cpu_state.ST[cpu_state.TOP] = td.d; + cpu_state.TOP--; + cpu_state.ST[cpu_state.TOP&7] = td.d; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; } static inline double x87_pop() { - double t = cpu_state.ST[cpu_state.TOP]; + double t = cpu_state.ST[cpu_state.TOP&7]; cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; - cpu_state.TOP=(cpu_state.TOP+1)&7; + cpu_state.TOP++; return t; } diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h index 4561c82..d5810c6 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -11,7 +11,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ ST(0) += use_var; \ if ((cpu_state.npxc >> 10) & 3) \ fesetround(FE_TONEAREST); \ - cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -48,7 +48,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), ST(0), use_var); \ - cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -60,7 +60,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), use_var, ST(0)); \ - cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -72,7 +72,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) *= use_var; \ - cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(11); \ return 0; \ } \ @@ -84,7 +84,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) -= use_var; \ - cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -96,7 +96,7 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) = use_var - ST(0); \ - cpu_state.tag[cpu_state.TOP] = TAG_VALID; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } @@ -121,7 +121,7 @@ static int opFADD(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FADD\n"); ST(0) = ST(0) + ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -232,7 +232,7 @@ static int opFDIV(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIV\n"); x87_div(ST(0), ST(0), ST(fetchdat & 7)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -264,7 +264,7 @@ static int opFDIVR(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(0), ST(fetchdat&7), ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -296,7 +296,7 @@ static int opFMUL(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FMUL\n"); ST(0) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(16); return 0; } @@ -328,7 +328,7 @@ static int opFSUB(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUB\n"); ST(0) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -360,7 +360,7 @@ static int opFSUBR(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSUBR\n"); ST(0) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h index 7a0b938..96c18e6 100644 --- a/src/x87_ops_loadstore.h +++ b/src/x87_ops_loadstore.h @@ -95,8 +95,8 @@ static int opFILDiq_a16(uint32_t fetchdat) temp64 = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] = TAG_VALID | TAG_UINT64; + cpu_state.MM[cpu_state.TOP&7].q = temp64; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; CLOCK_CYCLES(10); return 0; @@ -111,8 +111,8 @@ static int opFILDiq_a32(uint32_t fetchdat) temp64 = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] = TAG_VALID | TAG_UINT64; + cpu_state.MM[cpu_state.TOP&7].q = temp64; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; CLOCK_CYCLES(10); return 0; @@ -180,8 +180,8 @@ static int FISTPiq_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); - if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP].q; + if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64) + temp64 = cpu_state.MM[cpu_state.TOP&7].q; else temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; @@ -196,8 +196,8 @@ static int FISTPiq_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); - if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP].q; + if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64) + temp64 = cpu_state.MM[cpu_state.TOP&7].q; else temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 34a28d0..5ca534c 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -335,8 +335,8 @@ static int opFLD(uint32_t fetchdat) old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; x87_push(ST(fetchdat&7)); - cpu_state.tag[cpu_state.TOP] = old_tag; - cpu_state.MM[cpu_state.TOP].q = old_i64; + cpu_state.tag[cpu_state.TOP&7] = old_tag; + cpu_state.MM[cpu_state.TOP&7].q = old_i64; CLOCK_CYCLES(4); return 0; } @@ -352,11 +352,11 @@ static int opFXCH(uint32_t fetchdat) td = ST(0); ST(0) = ST(fetchdat&7); ST(fetchdat&7) = td; - old_tag = cpu_state.tag[cpu_state.TOP]; - cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; + old_tag = cpu_state.tag[cpu_state.TOP&7]; + cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag; - old_i64 = cpu_state.MM[cpu_state.TOP].q; - cpu_state.MM[cpu_state.TOP].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; + old_i64 = cpu_state.MM[cpu_state.TOP&7].q; + cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64; CLOCK_CYCLES(4); @@ -369,7 +369,7 @@ static int opFCHS(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FCHS\n"); ST(0) = -ST(0); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(6); return 0; } @@ -380,7 +380,7 @@ static int opFABS(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FABS %f\n", ST(0)); ST(0) = fabs(ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(3); return 0; } @@ -488,7 +488,7 @@ static int opF2XM1(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("F2XM1\n"); ST(0) = pow(2.0, ST(0)) - 1.0; - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(200); return 0; } @@ -523,7 +523,7 @@ static int opFPTAN(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FPTAN\n"); ST(0) = tan(ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; x87_push(1.0); cpu_state.npxs &= ~C2; CLOCK_CYCLES(235); @@ -547,7 +547,7 @@ static int opFDECSTP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; if (fplog) pclog("FDECSTP\n"); - cpu_state.TOP = (cpu_state.TOP - 1) & 7; + cpu_state.TOP--; CLOCK_CYCLES(4); return 0; } @@ -557,7 +557,7 @@ static int opFINCSTP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; if (fplog) pclog("FDECSTP\n"); - cpu_state.TOP = (cpu_state.TOP + 1) & 7; + cpu_state.TOP++; CLOCK_CYCLES(4); return 0; } @@ -570,7 +570,7 @@ static int opFPREM(uint32_t fetchdat) if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; if (fplog) pclog("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; @@ -587,7 +587,7 @@ static int opFPREM1(uint32_t fetchdat) if (fplog) pclog("FPREM1 %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; if (fplog) pclog("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; @@ -603,7 +603,7 @@ static int opFSQRT(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSQRT\n"); ST(0) = sqrt(ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(83); return 0; } @@ -616,7 +616,7 @@ static int opFSINCOS(uint32_t fetchdat) if (fplog) pclog("FSINCOS\n"); td = ST(0); ST(0) = sin(td); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; x87_push(cos(td)); cpu_state.npxs &= ~C2; CLOCK_CYCLES(330); @@ -629,7 +629,7 @@ static int opFRNDINT(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FRNDINT %g ", ST(0)); ST(0) = (double)x87_fround(ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; if (fplog) pclog("%g\n", ST(0)); CLOCK_CYCLES(21); return 0; @@ -643,7 +643,7 @@ static int opFSCALE(uint32_t fetchdat) if (fplog) pclog("FSCALE\n"); temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(30); return 0; } @@ -654,7 +654,7 @@ static int opFSIN(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSIN\n"); ST(0) = sin(ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -666,7 +666,7 @@ static int opFCOS(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FCOS\n"); ST(0) = cos(ST(0)); - cpu_state.tag[cpu_state.TOP] = TAG_VALID; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -836,8 +836,8 @@ static int opFSTCW_a32(uint32_t fetchdat) if (fplog) pclog("FCMOV %f\n", ST(fetchdat & 7)); \ if (cond_ ## condition) \ { \ - cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ - cpu_state.MM[cpu_state.TOP].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ + cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ + cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ ST(0) = ST(fetchdat & 7); \ } \ CLOCK_CYCLES(4); \ From d9e38fe37c007bba29490fc3806eb3b710de4f56 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 9 Oct 2018 13:51:05 +0100 Subject: [PATCH 040/181] Fix masking of FPU top-of-stack in several places. Fixes DOS Quake. --- src/386_dynarec.c | 2 +- src/codegen_backend.c | 2 +- src/x87_ops_misc.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3f905bd..91a2b55 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -663,7 +663,7 @@ void exec386_dynarec(int cycs) valid_block = 0; } } - if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP) + if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) { /*FPU top-of-stack does not match the value this block was compiled with, re-compile using dynamic top-of-stack*/ diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 58c092e..7d96ec3 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -303,7 +303,7 @@ void codegen_block_start_recompile(codeblock_t *block) cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; - block->TOP = cpu_state.TOP; + block->TOP = cpu_state.TOP & 7; block->was_recompiled = 1; codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 5ca534c..eb9fffb 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -144,7 +144,7 @@ static int FSAVE() { FP_ENTER(); if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, cpu_state.eaaddr, cpu_state.ismmx); - cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (cpu_state.TOP << 11); + cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { @@ -308,7 +308,7 @@ static int opFSTSW_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); - seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); + seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -318,7 +318,7 @@ static int opFSTSW_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); - seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); + seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } From 829c74f2d548afda844fc7de07cc387ce80622a6 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 9 Oct 2018 14:07:49 +0100 Subject: [PATCH 041/181] Don't write back unchanged registers on flush + invalidate. --- src/codegen_reg.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 556dbbf..fc97b20 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -473,18 +473,22 @@ void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) reg_set = &host_reg_set; for (c = 0; c < reg_set->nr_regs; c++) { - if (!ir_reg_is_invalid(reg_set->regs[c])) + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { codegen_reg_writeback(reg_set, block, c, 1); } + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } reg_set = &host_fp_reg_set; for (c = 0; c < reg_set->nr_regs; c++) { - if (!ir_reg_is_invalid(reg_set->regs[c])) + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { codegen_reg_writeback(reg_set, block, c, 1); } + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } } From e17a94a409970a457ec4448ccbc2347cda014f4d Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 9 Oct 2018 22:10:29 +0100 Subject: [PATCH 042/181] FDIVP/FDIVRP should pop the stack when a divide by zero occurs and the exception is masked. Fixes software rendering on Need for Speed III. --- src/x87_ops.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/x87_ops.h b/src/x87_ops.h index dd46f91..b1cc843 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -18,15 +18,15 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ { \ if (((double)src2) == 0.0) \ { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + cpu_state.npxs |= STATUS_ZERODIVIDE; \ + if (cpu_state.npxc & STATUS_ZERODIVIDE) \ dst = src1 / (double)src2; \ else \ { \ pclog("FPU : divide by zero\n"); \ picint(1 << 13); \ + return 1; \ } \ - return 1; \ } \ else \ dst = src1 / (double)src2; \ From 8a516df476a6f66599b69bf21e2171dcec00201c Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 17 Oct 2018 19:47:04 +0100 Subject: [PATCH 043/181] Added recompiled versions of FLD, FILD, FST and FSTP. --- src/codegen.c | 8 +- src/codegen_backend_arm.c | 72 +++++++++--- src/codegen_backend_arm64.c | 60 +++++++--- src/codegen_backend_arm64_defs.h | 8 +- src/codegen_backend_arm64_ops.c | 87 ++++++++++++-- src/codegen_backend_arm64_ops.h | 15 +++ src/codegen_backend_arm64_uops.c | 94 +++++++++++++++ src/codegen_backend_arm_defs.h | 6 + src/codegen_backend_arm_ops.c | 92 +++++++++++++-- src/codegen_backend_arm_ops.h | 11 ++ src/codegen_backend_arm_uops.c | 98 ++++++++++++++++ src/codegen_backend_x86-64.c | 74 +++++++++--- src/codegen_backend_x86-64_defs.h | 4 + src/codegen_backend_x86-64_ops.c | 62 ++++++++++ src/codegen_backend_x86-64_ops.h | 16 +++ src/codegen_backend_x86-64_uops.c | 99 +++++++++++++++- src/codegen_backend_x86.c | 83 +++++++++---- src/codegen_backend_x86_defs.h | 9 +- src/codegen_backend_x86_ops.c | 92 +++++++++++++-- src/codegen_backend_x86_ops.h | 35 ++++-- src/codegen_backend_x86_uops.c | 141 ++++++++++++++++++---- src/codegen_ir_defs.h | 25 +++- src/codegen_ops.c | 189 ++++++++++++++++++++++++++++++ src/codegen_ops.h | 12 +- src/codegen_ops_fpu_arith.c | 6 +- src/codegen_ops_fpu_loadstore.c | 134 +++++++++++++++++++++ src/codegen_ops_fpu_loadstore.h | 10 ++ src/codegen_ops_helpers.h | 9 ++ 28 files changed, 1400 insertions(+), 151 deletions(-) create mode 100644 src/codegen_ops_fpu_loadstore.c create mode 100644 src/codegen_ops_fpu_loadstore.h diff --git a/src/codegen.c b/src/codegen.c index 2f36a42..88cb01f 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -370,7 +370,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = NULL;//recomp_opcodes_d9; + recomp_op_table = recomp_opcodes_d9; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -388,7 +388,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = NULL;//recomp_opcodes_db; + recomp_op_table = recomp_opcodes_db; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -407,7 +407,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = NULL;//recomp_opcodes_dd; + recomp_op_table = recomp_opcodes_dd; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -425,7 +425,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = NULL;//recomp_opcodes_df; + recomp_op_table = recomp_opcodes_df; opcode_mask = 0xff; over = 1; pc_off = -1; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 3b9c5fe..67711e6 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -20,10 +20,14 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_single; +void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_single; +void *codegen_mem_store_double; int codegen_host_reg_list[CODEGEN_HOST_REGS] = { @@ -48,7 +52,7 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = REG_D15 }; -static void build_load_routine(codeblock_t *block, int size) +static void build_load_routine(codeblock_t *block, int size, int is_float) { uint32_t *branch_offset; uint32_t *misaligned_offset; @@ -78,12 +82,22 @@ static void build_load_routine(codeblock_t *block, int size) } host_arm_CMP_IMM(block, REG_R1, -1); branch_offset = host_arm_BEQ_(block); - if (size == 1) + if (size == 1 && !is_float) host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 2) + else if (size == 2 && !is_float) host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 4) + else if (size == 4 && !is_float) host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 4 && is_float) + { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); + host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); + } + else if (size == 8 && is_float) + { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); + host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); + } host_arm_MOV_IMM(block, REG_R1, 0); host_arm_MOV_REG(block, REG_PC, REG_LR); @@ -97,15 +111,21 @@ static void build_load_routine(codeblock_t *block, int size) host_arm_BL(block, (uintptr_t)readmemwl); else if (size == 4) host_arm_BL(block, (uintptr_t)readmemll); + else if (size == 8) + host_arm_BL(block, (uintptr_t)readmemql); else fatal("build_load_routine - unknown size %i\n", size); + if (size == 4 && is_float) + host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); + else if (size == 8 && is_float) + host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); block_pos = (block_pos + 63) & ~63; } -static void build_store_routine(codeblock_t *block, int size) +static void build_store_routine(codeblock_t *block, int size, int is_float) { uint32_t *branch_offset; uint32_t *misaligned_offset; @@ -135,12 +155,22 @@ static void build_store_routine(codeblock_t *block, int size) } host_arm_CMP_IMM(block, REG_R2, -1); branch_offset = host_arm_BEQ_(block); - if (size == 1) + if (size == 1 && !is_float) host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 2) + else if (size == 2 && !is_float) host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 4) + else if (size == 4 && !is_float) host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 4 && is_float) + { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); + host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0); + } + else if (size == 8 && is_float) + { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); + host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0); + } host_arm_MOV_IMM(block, REG_R1, 0); host_arm_MOV_REG(block, REG_PC, REG_LR); @@ -148,12 +178,18 @@ static void build_store_routine(codeblock_t *block, int size) if (size != 1) *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); + if (size == 4 && is_float) + host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); + else if (size == 8 && is_float) + host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); if (size == 1) host_arm_BL(block, (uintptr_t)writememb386l); else if (size == 2) host_arm_BL(block, (uintptr_t)writememwl); else if (size == 4) host_arm_BL(block, (uintptr_t)writememll); + else if (size == 8) + host_arm_BL_r1(block, (uintptr_t)writememql); else fatal("build_store_routine - unknown size %i\n", size); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); @@ -165,18 +201,26 @@ static void build_store_routine(codeblock_t *block, int size) static void build_loadstore_routines(codeblock_t *block) { codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1); + build_load_routine(block, 1, 0); codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2); + build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4); + build_load_routine(block, 4, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1); + build_store_routine(block, 1, 0); codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2); + build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4); + build_store_routine(block, 4, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } void codegen_backend_init() diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 57eb10b..638c65a 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -20,10 +20,14 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_single; +void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_single; +void *codegen_mem_store_double; int codegen_host_reg_list[CODEGEN_HOST_REGS] = { @@ -51,7 +55,7 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = REG_V15 }; -static void build_load_routine(codeblock_t *block, int size) +static void build_load_routine(codeblock_t *block, int size, int is_float) { uint32_t *branch_offset; uint8_t *misaligned_offset; @@ -84,12 +88,16 @@ static void build_load_routine(codeblock_t *block, int size) } host_arm64_CMPX_IMM(block, REG_X1, -1); branch_offset = host_arm64_BEQ_(block); - if (size == 1) + if (size == 1 && !is_float) host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 2) + else if (size == 2 && !is_float) host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 4) + else if (size == 4 && !is_float) host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 4 && is_float) + host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); + else if (size == 8 && is_float) + host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); host_arm64_MOVZ_IMM(block, REG_W1, 0); host_arm64_RET(block, REG_X30); @@ -103,16 +111,22 @@ static void build_load_routine(codeblock_t *block, int size) host_arm64_call(block, (uintptr_t)readmemwl); else if (size == 4) host_arm64_call(block, (uintptr_t)readmemll); + else if (size == 8) + host_arm64_call(block, (uintptr_t)readmemql); else fatal("build_load_routine - unknown size %i\n", size); codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + if (size == 4 && is_float) + host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); + else if (size == 8 && is_float) + host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); block_pos = (block_pos + 63) & ~63; } -static void build_store_routine(codeblock_t *block, int size) +static void build_store_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; uint8_t *misaligned_offset; @@ -145,12 +159,16 @@ static void build_store_routine(codeblock_t *block, int size) } host_arm64_CMPX_IMM(block, REG_X2, -1); branch_offset = host_arm64_BEQ_(block); - if (size == 1) + if (size == 1 && !is_float) host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 2) + else if (size == 2 && !is_float) host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 4) + else if (size == 4 && !is_float) host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 4 && is_float) + host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0); + else if (size == 8 && is_float) + host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0); host_arm64_MOVZ_IMM(block, REG_X1, 0); host_arm64_RET(block, REG_X30); @@ -158,12 +176,18 @@ static void build_store_routine(codeblock_t *block, int size) if (size != 1) host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); + if (size == 4 && is_float) + host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); + else if (size == 8 && is_float) + host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); if (size == 1) host_arm64_call(block, (uintptr_t)writememb386l); else if (size == 2) host_arm64_call(block, (uintptr_t)writememwl); else if (size == 4) host_arm64_call(block, (uintptr_t)writememll); + else if (size == 8) + host_arm64_call(block, (uintptr_t)writememql); else fatal("build_store_routine - unknown size %i\n", size); codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); @@ -176,18 +200,26 @@ static void build_store_routine(codeblock_t *block, int size) static void build_loadstore_routines(codeblock_t *block) { codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1); + build_load_routine(block, 1, 0); codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2); + build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4); + build_load_routine(block, 4, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1); + build_store_routine(block, 1, 0); codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2); + build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4); + build_store_routine(block, 4, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } void codegen_backend_init() diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 207fd80..f992759 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -109,13 +109,19 @@ #define REG_TEMP REG_X7 #define REG_TEMP2 REG_X6 +#define REG_V_TEMP REG_V0 + #define CODEGEN_HOST_REGS 10 #define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_single; +extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; -extern void *codegen_mem_store_long; \ No newline at end of file +extern void *codegen_mem_store_long; +extern void *codegen_mem_store_single; +extern void *codegen_mem_store_double; \ No newline at end of file diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index a7a3cd6..1c6da2f 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -103,21 +103,33 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BLR (0xd63f0000) #define OPCODE_BR (0xd61f0000) #define OPCODE_FADD_D (0x1e602800) +#define OPCODE_FCVT_D_S (0x1e22c000) +#define OPCODE_FCVT_S_D (0x1e624000) #define OPCODE_FDIV_D (0x1e601800) +#define OPCODE_FMOV_D_D (0x1e604000) +#define OPCODE_FMOV_D_Q (0x9e670000) +#define OPCODE_FMOV_Q_D (0x9e660000) +#define OPCODE_FMOV_S_W (0x1e270000) +#define OPCODE_FMOV_W_S (0x1e260000) #define OPCODE_FMUL_D (0x1e600800) #define OPCODE_FSUB_D (0x1e603800) #define OPCODE_LDR_REG (0xb8606800) #define OPCODE_LDRB_REG (0x38606800) #define OPCODE_LDRH_REG (0x78606800) #define OPCODE_LDRX_REG_LSL3 (0xf8607800) +#define OPCODE_LDR_REG_F32 (0xbc606800) +#define OPCODE_LDR_REG_F64 (0xfc606800) #define OPCODE_LDR_REG_F64_S (0xfc607800) #define OPCODE_LSL (0x1ac02000) #define OPCODE_LSR (0x1ac02400) #define OPCODE_NOP (0xd503201f) #define OPCODE_RET (0xd65f0000) +#define OPCODE_SCVTF_D_W (0x1e620000) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) #define OPCODE_STRH_REG (0x78206800) +#define OPCODE_STR_REG_F32 (0xbc206800) +#define OPCODE_STR_REG_F64 (0xfc206800) #define OPCODE_STR_REG_F64_S (0xfc207800) #define DATPROC_SHIFT(sh) (sh << 10) @@ -490,11 +502,37 @@ void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, in codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + { + codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + } + else + { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } +} +void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVT_D_S | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); @@ -510,21 +548,25 @@ void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg) { - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + codegen_addlong(block, OPCODE_FMOV_D_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_FMOV_D_Q | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FMOV_Q_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FMOV_S_W | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); } void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) @@ -564,10 +606,18 @@ void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offs codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } +void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset) { codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } +void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); @@ -704,6 +754,11 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); } +void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { if (!in_range7_x(offset)) @@ -728,10 +783,18 @@ void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offse codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } +void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_STR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); +} void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset) { codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg)); } +void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_STR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); +} void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index da83275..fb83b83 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -56,6 +56,15 @@ void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg); + +void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -63,7 +72,9 @@ void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offs void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); +void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -95,13 +106,17 @@ void host_arm64_RET(codeblock_t *block, int reg); void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); +void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg); +void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg); void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset); +void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg); void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg); void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index cb8e7cc..ad15f07 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -838,6 +838,40 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_call(block, codegen_mem_load_double); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + + return 0; +} +static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_call(block, codegen_mem_load_single); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_FCVT_D_S(block, dest_reg, REG_V_TEMP); + + return 0; +} static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { @@ -940,6 +974,41 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_FCVT_S_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_single); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_double); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1077,6 +1146,26 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) + { + host_arm64_SCVTF_D_W(block, dest_reg, src_reg); + } + else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) + { + host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); + } + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1591,18 +1680,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 0a246fa..6473fd5 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -41,6 +41,8 @@ #define REG_D14 14 #define REG_D15 15 +#define REG_D_TEMP REG_D0 + #define REG_MASK_R0 (1 << REG_R0) #define REG_MASK_R1 (1 << REG_R1) #define REG_MASK_R2 (1 << REG_R2) @@ -67,7 +69,11 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_single; +extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_single; +extern void *codegen_mem_store_double; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 2146efe..06841ea 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -17,10 +17,16 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) } } -#define Rm(x) (x) -#define Rs(x) ((x) << 8) -#define Rd(x) ((x) << 12) -#define Rn(x) ((x) << 16) +#define Rm(x) (x) +#define Rs(x) ((x) << 8) +#define Rd(x) ((x) << 12) +#define Rt(x) ((x) << 12) +#define Rn(x) ((x) << 16) +#define Rt2(x) ((x) << 16) + +#define Vm(x) (x) +#define Vd(x) ((x) << 12) +#define Vn(x) ((x) << 16) #define DATA_OFFSET_UP (1 << 23) #define DATA_OFFSET_DOWN (0 << 23) @@ -98,10 +104,20 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 #define OPCODE_VADD 0xee300b00 +#define OPCODE_VCVT_D_IS 0xeeb80bc0 +#define OPCODE_VCVT_D_S 0xeeb70ac0 +#define OPCODE_VCVT_S_D 0xeeb70bc0 #define OPCODE_VDIV 0xee800b00 -#define OPCODE_VLDR 0xed900b00 +#define OPCODE_VLDR_D 0xed900b00 +#define OPCODE_VLDR_S 0xed900a00 +#define OPCODE_VMOV_32_S 0xee100a10 +#define OPCODE_VMOV_64_D 0xec500b10 +#define OPCODE_VMOV_D_64 0xec400b10 +#define OPCODE_VMOV_S_32 0xee000a10 +#define OPCODE_VMOV_D_D 0xeeb00b40 #define OPCODE_VMUL 0xee200b00 -#define OPCODE_VSTR 0xed800b00 +#define OPCODE_VSTR_D 0xed800b00 +#define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -305,6 +321,18 @@ void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) else codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); } +void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + { + host_arm_MOV_IMM(block, REG_R1, dest_addr); + host_arm_BLX(block, REG_R1); + } + else + codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); +} void host_arm_BLX(codeblock_t *block, int addr_reg) { codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); @@ -734,6 +762,18 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); +} +void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); +} +void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -741,8 +781,34 @@ void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) - fatal("VLDR bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VLDR | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); + fatal("VLDR_D bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR_D | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); +} +void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if ((offset > 1020) || (offset & 3)) + fatal("VLDR_S bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR_S | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); +} +void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_32_S | Rt(dest_reg) | Vn(src_reg)); +} +void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_64_D | Rt(dest_reg_low) | Rt2(dest_reg_high) | Vm(src_reg)); +} +void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_D_64 | Vm(dest_reg) | Rt(src_reg_low) | Rt2(src_reg_high)); +} +void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_S_32 | Vn(dest_reg) | Rt(src_reg)); +} +void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); } void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { @@ -751,8 +817,14 @@ void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) - fatal("VSTR bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VSTR | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); + fatal("VSTR_D bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR_D | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); +} +void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset) +{ + if ((offset > 1020) || (offset & 3)) + fatal("VSTR_S bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR_S | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); } void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index a446bf1..6e2218e 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -16,6 +16,7 @@ void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_BL(codeblock_t *block, uintptr_t dest_addr); +void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr); void host_arm_BLX(codeblock_t *block, int addr_reg); uint32_t *host_arm_BCC_(codeblock_t *block); @@ -115,8 +116,18 @@ void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg); +void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high); +void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); +void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index d09f0e3..7574234 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -910,6 +910,42 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_BL(block, (uintptr_t)codegen_mem_load_single); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_VCVT_D_S(block, dest_reg, REG_D_TEMP); + + return 0; +} +static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_BL(block, (uintptr_t)codegen_mem_load_double); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + + return 0; +} static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { @@ -1012,6 +1048,42 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_VCVT_S_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t)codegen_mem_store_single); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t)codegen_mem_store_double); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} static int codegen_MOV(codeblock_t *block, uop_t *uop) { @@ -1156,6 +1228,27 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) + { + host_arm_VMOV_S_32(block, REG_D_TEMP, src_reg); + host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); + } + else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) + { + host_arm_SXTH(block, REG_TEMP, src_reg, 0); + host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); + host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); + } + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -1671,18 +1764,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 4fb6fe0..dc43a39 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -19,10 +19,14 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_single; +void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_single; +void *codegen_mem_store_double; int codegen_host_reg_list[CODEGEN_HOST_REGS] = { @@ -44,7 +48,7 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = static void *mem_abrt_rout; -static void build_load_routine(codeblock_t *block, int size) +static void build_load_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; uint8_t *misaligned_offset; @@ -80,12 +84,16 @@ static void build_load_routine(codeblock_t *block, int size) } host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); branch_offset = host_x86_JZ_short(block); - if (size == 1) + if (size == 1 && !is_float) host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 2) + else if (size == 2 && !is_float) host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 4) + else if (size == 4 && !is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 4 && is_float) + host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); + else if (size == 8 && is_float) + host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); else fatal("build_load_routine: size=%i\n", size); host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); @@ -102,21 +110,32 @@ static void build_load_routine(codeblock_t *block, int size) #else host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); #endif - if (size == 1) + if (size == 1 && !is_float) { host_x86_CALL(block, (void *)readmemb386l); host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); } - else if (size == 2) + else if (size == 2 && !is_float) { host_x86_CALL(block, (void *)readmemwl); host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); } - else if (size == 4) + else if (size == 4 && !is_float) { host_x86_CALL(block, (void *)readmemll); host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); } + else if (size == 4 && is_float) + { + host_x86_CALL(block, (void *)readmemll); + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + } + else if (size == 8 && is_float) + { + host_x86_CALL(block, (void *)readmemql); + host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); + } #if WIN64 host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); #endif @@ -127,7 +146,7 @@ static void build_load_routine(codeblock_t *block, int size) block_pos = (block_pos + 63) & ~63; } -static void build_store_routine(codeblock_t *block, int size) +static void build_store_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; uint8_t *misaligned_offset; @@ -164,12 +183,16 @@ static void build_store_routine(codeblock_t *block, int size) } host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); branch_offset = host_x86_JZ_short(block); - if (size == 1) + if (size == 1 && !is_float) host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 2) + else if (size == 2 && !is_float) host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 4) + else if (size == 4 && !is_float) host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 4 && is_float) + host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); + else if (size == 8 && is_float) + host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); else fatal("build_store_routine: size=%i\n", size); host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); @@ -182,7 +205,12 @@ static void build_store_routine(codeblock_t *block, int size) host_x86_PUSH(block, REG_RDX); #if WIN64 host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); - host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data + else if (size == 8 && is_float) + host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data + else + host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address #else //host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address @@ -194,6 +222,8 @@ static void build_store_routine(codeblock_t *block, int size) host_x86_CALL(block, (void *)writememwl); else if (size == 4) host_x86_CALL(block, (void *)writememll); + else if (size == 8) + host_x86_CALL(block, (void *)writememql); #if WIN64 host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); #endif @@ -207,18 +237,26 @@ static void build_store_routine(codeblock_t *block, int size) static void build_loadstore_routines(codeblock_t *block) { codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1); + build_load_routine(block, 1, 0); codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2); + build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4); + build_load_routine(block, 4, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1); + build_store_routine(block, 1, 0); codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2); + build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4); + build_store_routine(block, 4, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } void codegen_backend_init() diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index 8334b74..01c0c26 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -50,7 +50,11 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_single; +extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_single; +extern void *codegen_mem_store_double; diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 1fe0e58..21dd087 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -341,6 +341,26 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); @@ -837,6 +857,25 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -875,6 +914,12 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int } } +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -912,11 +957,28 @@ void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 codegen_addlong(block, addr); } } + +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } +void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 5b16a0e..08b6892 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -27,6 +27,11 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_JMP(codeblock_t *block, void *p); @@ -92,6 +97,14 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p); @@ -99,6 +112,9 @@ void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg); void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 534bb91..15d904a 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -771,7 +771,6 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) if (REG_IS_B(dest_size)) { host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); -// fatal("Here\n"); } else if (REG_IS_W(dest_size)) { @@ -784,6 +783,42 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} +static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { @@ -882,6 +917,43 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -974,6 +1046,26 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) + { + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); + } + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1386,18 +1478,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, [UOP_MOV & UOP_MASK] = codegen_MOV, [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index d09bb21..ab6a3be 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -19,10 +19,14 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_single; +void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_single; +void *codegen_mem_store_double; int codegen_host_reg_list[CODEGEN_HOST_REGS] = { @@ -38,13 +42,12 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = REG_XMM2, REG_XMM3, REG_XMM4, - REG_XMM5, - REG_XMM6 + REG_XMM5 }; static void *mem_abrt_rout; -static void build_load_routine(codeblock_t *block, int size) +static void build_load_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; uint8_t *misaligned_offset = NULL; @@ -79,12 +82,16 @@ static void build_load_routine(codeblock_t *block, int size) } host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); branch_offset = host_x86_JZ_short(block); - if (size == 1) + if (size == 1 && !is_float) host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 2) + else if (size == 2 && !is_float) host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 4) + else if (size == 4 && !is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 4 && is_float) + host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); + else if (size == 8 && is_float) + host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); else fatal("build_load_routine: size=%i\n", size); host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); @@ -102,13 +109,26 @@ static void build_load_routine(codeblock_t *block, int size) host_x86_CALL(block, (void *)readmemwl); else if (size == 4) host_x86_CALL(block, (void *)readmemll); + else if (size == 8) + host_x86_CALL(block, (void *)readmemql); host_x86_POP(block, REG_ECX); - if (size == 1) + if (size == 1 && !is_float) host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); - else if (size == 2) + else if (size == 2 && !is_float) host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); - else if (size == 4) + else if (size == 4 && !is_float) host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + else if (size == 4 && is_float) + { + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + } + else if (size == 8 && is_float) + { + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); + host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2); + } host_x86_POP(block, REG_EDX); host_x86_POP(block, REG_EAX); host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); @@ -116,7 +136,7 @@ static void build_load_routine(codeblock_t *block, int size) block_pos = (block_pos + 63) & ~63; } -static void build_store_routine(codeblock_t *block, int size) +static void build_store_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; uint8_t *misaligned_offset = NULL; @@ -152,23 +172,34 @@ static void build_store_routine(codeblock_t *block, int size) } host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); branch_offset = host_x86_JZ_short(block); - if (size == 1) + if (size == 1 && !is_float) host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 2) + else if (size == 2 && !is_float) host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 4) + else if (size == 4 && !is_float) host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 4 && is_float) + host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); + else if (size == 8 && is_float) + host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); else - fatal("build_store_routine: size=%i\n", size); + fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); host_x86_PUSH(block, REG_EAX); host_x86_PUSH(block, REG_EDX); host_x86_PUSH(block, REG_ECX); + if (size == 8 && is_float) + { + host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); + host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 8); + } host_x86_PUSH(block, REG_EDI); if (size == 1) host_x86_CALL(block, (void *)writememb386l); @@ -176,7 +207,11 @@ static void build_store_routine(codeblock_t *block, int size) host_x86_CALL(block, (void *)writememwl); else if (size == 4) host_x86_CALL(block, (void *)writememll); + else if (size == 8) + host_x86_CALL(block, (void *)writememql); host_x86_POP(block, REG_EDI); + if (size == 8 && is_float) + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 8); host_x86_POP(block, REG_ECX); host_x86_POP(block, REG_EDX); host_x86_POP(block, REG_EAX); @@ -188,18 +223,26 @@ static void build_store_routine(codeblock_t *block, int size) static void build_loadstore_routines(codeblock_t *block) { codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1); + build_load_routine(block, 1, 0); codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2); + build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4); + build_load_routine(block, 4, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1); + build_store_routine(block, 1, 0); codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2); + build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4); + build_store_routine(block, 4, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } void codegen_backend_init() diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 93d6569..5a5ea69 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -19,17 +19,22 @@ #define REG_XMM6 6 #define REG_XMM7 7 -#define REG_XMM_TEMP REG_XMM7 +#define REG_XMM_TEMP REG_XMM7 +#define REG_XMM_TEMP2 REG_XMM6 #define CODEGEN_HOST_REGS 3 -#define CODEGEN_HOST_FP_REGS 7 +#define CODEGEN_HOST_FP_REGS 6 extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_single; +extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_single; +extern void *codegen_mem_store_double; #endif diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 3dad4db..ae601b7 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -185,7 +185,7 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } -void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } @@ -309,7 +309,27 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } -void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); } @@ -714,7 +734,26 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } -void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -729,7 +768,7 @@ void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) codegen_addlong(block, (uint32_t)p); } } -void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ if (addr < 0x80 || addr >= 0xffffff80) @@ -742,8 +781,33 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int codegen_addlong(block, addr); } } +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) +{ + if (!offset) + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ + codegen_addbyte(block, 0x24); + } + else if (offset >= -80 || offset < 0x80) + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte2(block, 0x24, offset & 0xff); + } + else + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte(block, 0x24); + codegen_addlong(block, offset); + } -void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) +} + +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -758,7 +822,7 @@ void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addlong(block, (uint32_t)p); } } -void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) { codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ if (addr < 0x80 || addr >= 0xffffff80) @@ -771,7 +835,12 @@ void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 codegen_addlong(block, addr); } } -void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } @@ -840,7 +909,7 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ } -void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1078,7 +1147,7 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } -void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1109,6 +1178,11 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if (dst_reg != src_reg_a) diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index d6ff697..19ef66a 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -8,7 +8,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); @@ -27,7 +27,14 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); -void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg); + +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg); +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_JMP(codeblock_t *block, void *p); @@ -94,12 +101,20 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); -void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); -void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg); -void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg); + +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); @@ -114,7 +129,7 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); @@ -162,7 +177,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); @@ -170,6 +185,8 @@ void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data); +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index b153804..04803d7 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -545,7 +545,7 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_ADDSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); } else fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -559,13 +559,13 @@ static int codegen_FDIV(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_DIVSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { - host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); - host_x86_DIVSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } else fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -579,7 +579,7 @@ static int codegen_FMUL(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_MULSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); } else fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -593,13 +593,13 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_SUBSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { - host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } else fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -773,6 +773,43 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} + +static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { @@ -871,6 +908,43 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} +static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + + return 0; +} + static int codegen_MOV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -963,6 +1037,26 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) + { + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) + { + host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); + } + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1369,20 +1463,25 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_MOV & UOP_MASK] = codegen_MOV, + [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, @@ -1442,7 +1541,7 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) } void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_REG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { @@ -1451,7 +1550,7 @@ void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); - host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) @@ -1477,7 +1576,7 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int } void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_REG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { @@ -1486,7 +1585,7 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 3, host_reg); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index e949bdf..c935d0c 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -62,6 +62,8 @@ #define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) /*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/ #define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) +/*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/ +#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25) /*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) /*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ @@ -99,8 +101,16 @@ #define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/ #define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_LOAD_SINGLE - dest_reg = (float)src_reg_a:[src_reg_b]*/ +#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/ #define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_LOAD_DOUBLE - dest_reg = (double)src_reg_a:[src_reg_b]*/ +#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_SINGLE - src_reg_a:[src_reg_b] = src_reg_c*/ +#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER) +/*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/ +#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER) /*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/ #define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) @@ -467,18 +477,23 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) #define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0) #define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset) +#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0) #define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) #define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0) #define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset) #define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) #define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) #define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0) -#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) -#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) -#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) -#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) -#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) +#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) +#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) +#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) +#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) +#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 6fe6799..547b627 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -5,6 +5,7 @@ #include "codegen_ops_arith.h" #include "codegen_ops_branch.h" #include "codegen_ops_fpu_arith.h" +#include "codegen_ops_fpu_loadstore.h" #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" @@ -154,6 +155,100 @@ RecompOpFn recomp_opcodes_d8[512] = /*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, }; +RecompOpFn recomp_opcodes_d9[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + +RecompOpFn recomp_opcodes_db[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + RecompOpFn recomp_opcodes_dc[512] = { /*16-bit data*/ @@ -201,6 +296,53 @@ RecompOpFn recomp_opcodes_dc[512] = /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, }; +RecompOpFn recomp_opcodes_dd[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + RecompOpFn recomp_opcodes_de[512] = { /*16-bit data*/ @@ -247,3 +389,50 @@ RecompOpFn recomp_opcodes_de[512] = /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, }; + +RecompOpFn recomp_opcodes_df[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; diff --git a/src/codegen_ops.h b/src/codegen_ops.h index 432652d..7231e0e 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -10,14 +10,14 @@ typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t extern RecompOpFn recomp_opcodes[512]; extern RecompOpFn recomp_opcodes_0f[512]; extern RecompOpFn recomp_opcodes_d8[512]; -/*extern RecompOpFn recomp_opcodes_d9[512]; -extern RecompOpFn recomp_opcodes_da[512]; -extern RecompOpFn recomp_opcodes_db[512];*/ +extern RecompOpFn recomp_opcodes_d9[512]; +/*extern RecompOpFn recomp_opcodes_da[512];*/ +extern RecompOpFn recomp_opcodes_db[512]; extern RecompOpFn recomp_opcodes_dc[512]; -/*extern RecompOpFn recomp_opcodes_dd[512];*/ +extern RecompOpFn recomp_opcodes_dd[512]; extern RecompOpFn recomp_opcodes_de[512]; -/*extern RecompOpFn recomp_opcodes_df[512]; -extern RecompOpFn recomp_opcodes_REPE[512]; +extern RecompOpFn recomp_opcodes_df[512]; +/*extern RecompOpFn recomp_opcodes_REPE[512]; extern RecompOpFn recomp_opcodes_REPNE[512];*/ #define REG_EAX 0 diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c index 507f937..6746d0d 100644 --- a/src/codegen_ops_fpu_arith.c +++ b/src/codegen_ops_fpu_arith.c @@ -9,11 +9,7 @@ #include "codegen_ir.h" #include "codegen_ops.h" #include "codegen_ops_fpu_arith.h" - -static void fpu_POP(ir_data_t *ir) -{ - uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); -} +#include "codegen_ops_helpers.h" uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c new file mode 100644 index 0000000..cfee360 --- /dev/null +++ b/src/codegen_ops_fpu_loadstore.c @@ -0,0 +1,134 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "x87.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_fpu_arith.h" +#include "codegen_ops_helpers.h" + +uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(ir); + + return op_pc+1; +} +uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(ir); + + return op_pc+1; +} + +uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + + return op_pc+1; +} +uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(ir); + + return op_pc+1; +} +uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + + return op_pc+1; +} +uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(ir); + + return op_pc+1; +} + + +uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(ir); + + return op_pc+1; +} +uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(ir); + + return op_pc+1; +} diff --git a/src/codegen_ops_fpu_loadstore.h b/src/codegen_ops_fpu_loadstore.h new file mode 100644 index 0000000..727f715 --- /dev/null +++ b/src/codegen_ops_fpu_loadstore.h @@ -0,0 +1,10 @@ +uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index 55cb99a..8d9d911 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -41,3 +41,12 @@ static inline void SUB_SP(ir_data_t *ir, int offset) else uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); } + +static inline void fpu_POP(ir_data_t *ir) +{ + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); +} +static inline void fpu_PUSH(ir_data_t *ir) +{ + uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); +} From 6d8af5df4a9acbbfea1b6a4823bbab4521af3f05 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 20 Oct 2018 20:03:28 +0100 Subject: [PATCH 044/181] Added recompiled versions of memory variants of F[I]ADD, F[I]DIV, F[I]DIVR, F[I]MUL, F[I]SUB and F[I]SUBR. --- src/codegen.c | 2 +- src/codegen_backend_arm64_uops.c | 8 ++ src/codegen_backend_arm_uops.c | 8 ++ src/codegen_backend_x86-64_ops.c | 56 +++++++-- src/codegen_backend_x86-64_ops.h | 18 +-- src/codegen_backend_x86-64_uops.c | 42 ++++--- src/codegen_backend_x86_ops.c | 38 +++++- src/codegen_backend_x86_ops.h | 2 + src/codegen_backend_x86_uops.c | 8 ++ src/codegen_ir_defs.h | 2 + src/codegen_ops.c | 155 +++++++++++++++-------- src/codegen_ops.h | 2 +- src/codegen_ops_fpu_arith.c | 196 ++++++++++++++++++++++++++++++ src/codegen_ops_fpu_arith.h | 26 ++++ src/codegen_reg.c | 21 ++++ src/codegen_reg.h | 4 + 16 files changed, 495 insertions(+), 93 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 88cb01f..d06438c 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -379,7 +379,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = NULL;//recomp_opcodes_da; + recomp_op_table = recomp_opcodes_da; opcode_mask = 0xff; over = 1; pc_off = -1; diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index ad15f07..193d7dd 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1850,6 +1850,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32_stack - not in range\n"); } +void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_arm64_LDR_IMM_F64(block, host_reg, REG_SP, stack_offset); +} void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { @@ -1858,6 +1862,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos else fatal("codegen_direct_write_32_stack - not in range\n"); } +void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_arm64_STR_IMM_F64(block, host_reg, REG_SP, stack_offset); +} void codegen_set_jump_dest(codeblock_t *block, void *p) { diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 7574234..b09b005 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1927,6 +1927,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); +} void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { @@ -1935,6 +1939,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); +} void codegen_set_jump_dest(codeblock_t *block, void *p) { diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 21dd087..7eb7f20 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -212,7 +212,7 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } -void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } @@ -361,7 +361,7 @@ void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base codegen_addbyte(block, base_reg | (idx_reg << 3)); } -void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); } @@ -876,7 +876,7 @@ void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -897,7 +897,7 @@ void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg) codegen_addlong(block, (uint32_t)(uintptr_t)p); } } -void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); @@ -919,8 +919,26 @@ void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} -void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -941,7 +959,7 @@ void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addlong(block, (uint32_t)(uintptr_t)p); } } -void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) { if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); @@ -957,13 +975,31 @@ void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 codegen_addlong(block, addr); } } - void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } -void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); +} + +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } @@ -1041,7 +1077,7 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); } -void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1325,7 +1361,7 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } -void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); } diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 08b6892..4fbffdb 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -7,7 +7,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); @@ -32,7 +32,7 @@ void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_JMP(codeblock_t *block, void *p); @@ -105,12 +105,12 @@ void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); -void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg); -void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); @@ -130,7 +130,7 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); -void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); @@ -179,7 +179,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 15d904a..2a76566 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -534,7 +534,7 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_ADDSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); } else fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -548,13 +548,13 @@ static int codegen_FDIV(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_DIVSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { - host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); - host_x86_DIVSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } else fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -568,7 +568,7 @@ static int codegen_FMUL(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_MULSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); } else fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -582,13 +582,13 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { - host_x86_SUBSD_REG_REG(block, dest_reg, src_reg_b); + host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { - host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBSD_REG_REG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } else fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -797,7 +797,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) host_x86_CALL(block, codegen_mem_load_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); - host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); return 0; } @@ -815,7 +815,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_CALL(block, codegen_mem_load_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); - host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); return 0; } @@ -946,7 +946,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); - host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); @@ -1554,7 +1554,7 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) } void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_REG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { @@ -1563,7 +1563,7 @@ void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); - host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) @@ -1589,7 +1589,7 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int } void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_REG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { @@ -1598,7 +1598,7 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 3, host_reg); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) @@ -1614,11 +1614,19 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } +void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); +} void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } +void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); +} void codegen_set_jump_dest(codeblock_t *block, void *p) { diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index ae601b7..7db67b9 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -783,9 +783,27 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int } void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) { if (!offset) @@ -840,6 +858,24 @@ void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); +} void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 19ef66a..fba62f9 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -109,11 +109,13 @@ void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg); void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg); void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 04803d7..003b4ae 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1601,11 +1601,19 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } +void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); +} void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); } +void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); +} void codegen_set_jump_dest(codeblock_t *block, void *p) { diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index c935d0c..41bacd7 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -516,8 +516,10 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset); +void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); +void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_set_jump_dest(codeblock_t *block, void *p); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 547b627..b9285dd 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -112,20 +112,20 @@ RecompOpFn recomp_opcodes_d8[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, +/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, +/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, +/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -134,20 +134,20 @@ RecompOpFn recomp_opcodes_d8[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, +/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, +/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, +/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -202,6 +202,53 @@ RecompOpFn recomp_opcodes_d9[512] = /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; +RecompOpFn recomp_opcodes_da[512] = +{ + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, +/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, + +/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, +/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, + +/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, +/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, +/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, + +/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, +/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, + +/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, +/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + RecompOpFn recomp_opcodes_db[512] = { /*16-bit data*/ @@ -253,20 +300,20 @@ RecompOpFn recomp_opcodes_dc[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, +/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, +/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, +/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -275,20 +322,20 @@ RecompOpFn recomp_opcodes_dc[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, +/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, +/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, +/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -347,20 +394,20 @@ RecompOpFn recomp_opcodes_de[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, +/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, +/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, +/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -369,20 +416,20 @@ RecompOpFn recomp_opcodes_de[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, +/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, -/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, +/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, -/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, +/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops.h b/src/codegen_ops.h index 7231e0e..6e86be6 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -11,7 +11,7 @@ extern RecompOpFn recomp_opcodes[512]; extern RecompOpFn recomp_opcodes_0f[512]; extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; -/*extern RecompOpFn recomp_opcodes_da[512];*/ +extern RecompOpFn recomp_opcodes_da[512]; extern RecompOpFn recomp_opcodes_db[512]; extern RecompOpFn recomp_opcodes_dc[512]; extern RecompOpFn recomp_opcodes_dd[512]; diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c index 6746d0d..ae62746 100644 --- a/src/codegen_ops_fpu_arith.c +++ b/src/codegen_ops_fpu_arith.c @@ -200,3 +200,199 @@ uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } + +#define ropF_arith_mem(name, load_uop) \ +uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFSUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFSUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} + +ropF_arith_mem(s, uop_MEM_LOAD_SINGLE) +ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) + +#define ropFI_arith_mem(name, temp_reg) \ +uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFIDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFIMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFISUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc+1; \ +} + +ropFI_arith_mem(l, IREG_temp0) +ropFI_arith_mem(w, IREG_temp0_W) diff --git a/src/codegen_ops_fpu_arith.h b/src/codegen_ops_fpu_arith.h index 4e60233..2cbafb7 100644 --- a/src/codegen_ops_fpu_arith.h +++ b/src/codegen_ops_fpu_arith.h @@ -16,3 +16,29 @@ uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFADDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFADDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFDIVRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFMULs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFMULd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSUBRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFIADDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIADDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIDIVl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIDIVw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIDIVRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIDIVRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIMULl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFIMULw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISUBl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISUBw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISUBRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISUBRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index fc97b20..991c8c5 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -33,6 +33,7 @@ enum REG_DWORD, REG_QWORD, REG_POINTER, + REG_DOUBLE, REG_FPU_ST_BYTE, REG_FPU_ST_DOUBLE }; @@ -119,6 +120,8 @@ struct [IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER}, [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER}, [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER}, + + [IREG_temp0d] = {REG_DOUBLE, (void *)48, REG_FP} }; void codegen_reg_reset() @@ -188,6 +191,15 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, codegen_direct_read_32(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; + case REG_DOUBLE: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n"); + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_double_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_double(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; + case REG_FPU_ST_DOUBLE: if (block->flags & CODEBLOCK_STATIC_TOP) codegen_direct_read_double(block, reg_set->reg_list[c], &cpu_state.ST[ir_reg.reg & 7]); @@ -244,6 +256,15 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i codegen_direct_write_ptr(block, p, reg_set->reg_list[c]); break; + case REG_DOUBLE: + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n"); + if ((uintptr_t)p < 256) + codegen_direct_write_double_stack(block, (int)p, reg_set->reg_list[c]); + else + codegen_direct_write_double(block, p, reg_set->reg_list[c]); + break; + case REG_FPU_ST_BYTE: if (block->flags & CODEBLOCK_STATIC_TOP) codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c]); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 986f0aa..358d6a8 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -67,6 +67,8 @@ enum IREG_FPU_TOP = 37, + IREG_temp0d = 39, + /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() to access. When CODEBLOCK_STATIC_TOP is set, the physical register number will be @@ -129,6 +131,8 @@ enum IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, + IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, + IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, From bce9ad4f3dcf617de6f54861d8329d837d60aefe Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 21 Oct 2018 16:22:20 +0100 Subject: [PATCH 045/181] Added recompiled versions of FFREE, FLD, FST, FSTP and FXCH. --- src/codegen_backend_arm64_uops.c | 57 ++++++++++++++++++++++++++--- src/codegen_backend_arm_uops.c | 52 +++++++++++++++++++++++++-- src/codegen_backend_x86-64_ops.c | 36 +++++++++++++++++++ src/codegen_backend_x86-64_ops.h | 3 ++ src/codegen_backend_x86-64_uops.c | 52 +++++++++++++++++++++++++-- src/codegen_backend_x86_ops.c | 28 +++++++++++++++ src/codegen_backend_x86_ops.h | 3 ++ src/codegen_backend_x86_uops.c | 60 +++++++++++++++++++++++++++++-- src/codegen_ir_defs.h | 9 ++++- src/codegen_ops.c | 17 ++++----- src/codegen_reg.c | 48 +++++++++++++++++++++++-- src/codegen_reg.h | 26 +++++++++++--- 12 files changed, 364 insertions(+), 27 deletions(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 193d7dd..7ec43dc 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -18,6 +18,7 @@ #define REG_IS_B(size) (size == IREG_SIZE_B) #define REG_IS_BH(size) (size == IREG_SIZE_BH) #define REG_IS_D(size) (size == IREG_SIZE_D) +#define REG_IS_Q(size) (size == IREG_SIZE_Q) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -1040,6 +1041,14 @@ static int codegen_MOV(codeblock_t *block, uop_t *uop) host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) + { + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + } + else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + } else fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -1767,6 +1776,13 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_double - not in range\n"); +} void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) @@ -1774,6 +1790,22 @@ void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_double - not in range\n"); } +void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); +} +void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); +} void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); @@ -1804,6 +1836,20 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); +} void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); @@ -1812,12 +1858,13 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_double - not in range\n"); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index b09b005..22e546d 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -76,6 +76,7 @@ void host_arm_nop(codeblock_t *block) #define REG_IS_B(size) (size == IREG_SIZE_B) #define REG_IS_BH(size) (size == IREG_SIZE_BH) #define REG_IS_D(size) (size == IREG_SIZE_D) +#define REG_IS_Q(size) (size == IREG_SIZE_Q) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -1116,6 +1117,14 @@ static int codegen_MOV(codeblock_t *block, uop_t *uop) host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) + { + host_arm_VMOV_D_D(block, dest_reg, src_reg); + } + else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + host_arm_VMOV_D_D(block, dest_reg, src_reg); + } else fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -1830,6 +1839,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FSUB & UOP_MASK] = codegen_FSUB }; +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +{ + if (in_range_h(p, &cpu_state)) + host_arm_LDRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_8 - not in range\n"); +} void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { if (in_range_h(p, &cpu_state)) @@ -1847,10 +1863,30 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +{ + host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); +} void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); } +void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_LDRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); +} +void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); +} void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); @@ -1884,6 +1920,14 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +{ + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); +} void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); @@ -1892,9 +1936,13 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 7eb7f20..38cf727 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -663,6 +663,27 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_r codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ } +void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOV8_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } + else if (offset < (1ull << 32)) + { + codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } + else + { + fatal("host_x86_MOV8_REG_ABS - out of range\n"); + } +} void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -709,6 +730,21 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) } } +void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } + else + { + codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 4fbffdb..6d8a8f0 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -75,9 +75,12 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift); + void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 2a76566..367f36e 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -21,6 +21,7 @@ #define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) #define REG_IS_BH(size) (size == IREG_SIZE_BH) #define REG_IS_D(size) (size == IREG_SIZE_D) +#define REG_IS_Q(size) (size == IREG_SIZE_Q) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -971,6 +972,14 @@ static int codegen_MOV(codeblock_t *block, uop_t *uop) { host_x86_MOV8_REG_REG(block, dest_reg, src_reg); } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } + else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } else fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -1544,6 +1553,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FSUB & UOP_MASK] = codegen_FSUB }; +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV8_REG_ABS(block, host_reg, p); +} void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { host_x86_MOV16_REG_ABS(block, host_reg, p); @@ -1552,10 +1565,32 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); } +void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOVQ_XREG_ABS(block, host_reg, p); +} void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { host_x86_MOVQ_XREG_ABS(block, host_reg, p); } +void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 0); +} +void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); +} void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); @@ -1578,6 +1613,14 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOVQ_ABS_XREG(block, p, host_reg); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOVQ_ABS_XREG(block, p, host_reg); +} void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); @@ -1587,9 +1630,14 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 7db67b9..6d5521a 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -571,6 +571,21 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ } +void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } + else + { + codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t)p); + } +} void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -607,6 +622,19 @@ void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p codegen_addlong(block, (uint32_t)p); } +void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int idx_reg, int shift) +{ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } + else + { + codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index fba62f9..102639a 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -79,11 +79,14 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg); void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg); +void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift); +void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_addr, uint32_t addr, int base_reg, int idx_reg, int shift); + void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 003b4ae..d060bdd 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -31,6 +31,7 @@ #define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) #define REG_IS_BH(size) (size == IREG_SIZE_BH) #define REG_IS_D(size) (size == IREG_SIZE_D) +#define REG_IS_Q(size) (size == IREG_SIZE_Q) static int codegen_ADD(codeblock_t *block, uop_t *uop) { @@ -962,6 +963,14 @@ static int codegen_MOV(codeblock_t *block, uop_t *uop) { host_x86_MOV8_REG_REG(block, dest_reg, src_reg); } + else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } + else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } else fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -1531,6 +1540,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FSUB & UOP_MASK] = codegen_FSUB }; +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV8_REG_ABS(block, host_reg, p); +} void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { host_x86_MOV16_REG_ABS(block, host_reg, p); @@ -1539,10 +1552,32 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); } +void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOVQ_XREG_ABS(block, host_reg, p); +} void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { host_x86_MOVQ_XREG_ABS(block, host_reg, p); } +void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 0); +} +void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); +} void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); @@ -1565,6 +1600,14 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { host_x86_MOV32_ABS_REG(block, p, host_reg); } +void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOVQ_ABS_XREG(block, p, host_reg); +} +void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOVQ_ABS_XREG(block, p, host_reg); +} void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); @@ -1574,9 +1617,14 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { @@ -1601,6 +1649,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); @@ -1610,6 +1662,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos { host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); } +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 41bacd7..036493e 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -501,21 +501,28 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) #define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); +void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p); +void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx); +void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx); void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx); void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg); void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg); +void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg); void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg); void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset); +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index b9285dd..56fff16 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -6,6 +6,7 @@ #include "codegen_ops_branch.h" #include "codegen_ops_fpu_arith.h" #include "codegen_ops_fpu_loadstore.h" +#include "codegen_ops_fpu_misc.h" #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" @@ -174,8 +175,8 @@ RecompOpFn recomp_opcodes_d9[512] = /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -196,8 +197,8 @@ RecompOpFn recomp_opcodes_d9[512] = /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -362,8 +363,8 @@ RecompOpFn recomp_opcodes_dd[512] = /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -384,8 +385,8 @@ RecompOpFn recomp_opcodes_dd[512] = /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 991c8c5..ac1e417 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -35,7 +35,8 @@ enum REG_POINTER, REG_DOUBLE, REG_FPU_ST_BYTE, - REG_FPU_ST_DOUBLE + REG_FPU_ST_DOUBLE, + REG_FPU_ST_QWORD }; enum @@ -113,6 +114,15 @@ struct [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_MM0] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM1] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM2] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM3] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM4] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM5] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM6] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM7] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ @@ -121,7 +131,8 @@ struct [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER}, [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER}, - [IREG_temp0d] = {REG_DOUBLE, (void *)48, REG_FP} + [IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP}, + [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP}, }; void codegen_reg_reset() @@ -200,7 +211,27 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, codegen_direct_read_double(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; + case REG_FPU_ST_BYTE: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n"); + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_8(block, reg_set->reg_list[c], &cpu_state.tag[ir_reg.reg & 7]); + else + codegen_direct_read_st_8(block, reg_set->reg_list[c], &cpu_state.tag[0], ir_reg.reg & 7); + break; + + case REG_FPU_ST_QWORD: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n"); + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_64(block, reg_set->reg_list[c], &cpu_state.MM[ir_reg.reg & 7]); + else + codegen_direct_read_st_64(block, reg_set->reg_list[c], &cpu_state.MM[0], ir_reg.reg & 7); + break; + case REG_FPU_ST_DOUBLE: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n"); if (block->flags & CODEBLOCK_STATIC_TOP) codegen_direct_read_double(block, reg_set->reg_list[c], &cpu_state.ST[ir_reg.reg & 7]); else @@ -266,13 +297,26 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i break; case REG_FPU_ST_BYTE: + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n"); if (block->flags & CODEBLOCK_STATIC_TOP) codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c]); else codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]); break; + case REG_FPU_ST_QWORD: + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n"); + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c]); + else + codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]); + break; + case REG_FPU_ST_DOUBLE: + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n"); if (block->flags & CODEBLOCK_STATIC_TOP) codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c]); else diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 358d6a8..2830d40 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -13,6 +13,7 @@ #define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) #define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) #define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) +#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) enum { @@ -67,7 +68,8 @@ enum IREG_FPU_TOP = 37, - IREG_temp0d = 39, + IREG_temp0d = 38, + IREG_temp1d = 39, /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() to access. @@ -93,9 +95,18 @@ enum IREG_tag6 = 54, IREG_tag7 = 55, - IREG_COUNT = 56, + IREG_MM0 = 56, + IREG_MM1 = 57, + IREG_MM2 = 58, + IREG_MM3 = 59, + IREG_MM4 = 60, + IREG_MM5 = 61, + IREG_MM6 = 62, + IREG_MM7 = 63, + + IREG_COUNT = 64, - IREG_INVALID = 63, + IREG_INVALID = 255, IREG_AX = IREG_EAX + IREG_SIZE_W, IREG_CX = IREG_ECX + IREG_SIZE_W, @@ -130,9 +141,13 @@ enum IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, - + IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, - + IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, + + IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q, + IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q, + IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, @@ -148,6 +163,7 @@ enum #define IREG_32(reg) ((reg) + IREG_EAX) #define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) +#define IREG_MM(r) (IREG_MM0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) #define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) #define IREG_TOP_diff_stack_offset 32 From 589f50e479f5a50fc5cf563b79d26402d18404dc Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 22 Oct 2018 21:23:09 +0100 Subject: [PATCH 046/181] Added recompiled version of FILDq. --- src/codegen_backend_arm.c | 7 +++++-- src/codegen_backend_arm64.c | 7 +++++-- src/codegen_backend_arm64_defs.h | 1 + src/codegen_backend_arm64_ops.c | 5 +++++ src/codegen_backend_arm64_ops.h | 1 + src/codegen_backend_arm64_uops.c | 15 ++++++++++++++- src/codegen_backend_arm_defs.h | 1 + src/codegen_backend_arm_uops.c | 20 ++++++++++++++++++++ src/codegen_backend_x86-64.c | 7 +++++-- src/codegen_backend_x86-64_defs.h | 1 + src/codegen_backend_x86-64_ops.c | 7 ++++++- src/codegen_backend_x86-64_ops.h | 18 +++++++++--------- src/codegen_backend_x86-64_uops.c | 13 +++++++++++++ src/codegen_backend_x86.c | 7 +++++-- src/codegen_backend_x86_defs.h | 1 + src/codegen_backend_x86_ops.c | 16 ++++++++++++++++ src/codegen_backend_x86_ops.h | 3 +++ src/codegen_backend_x86_uops.c | 17 +++++++++++++++++ src/codegen_ops.c | 12 ++++++------ src/codegen_ops_fpu_loadstore.c | 16 ++++++++++++++++ src/codegen_ops_fpu_loadstore.h | 1 + 21 files changed, 151 insertions(+), 25 deletions(-) diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 67711e6..7e46a7b 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -20,6 +20,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -93,7 +94,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); } - else if (size == 8 && is_float) + else if (size == 8) { host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); @@ -117,7 +118,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) fatal("build_load_routine - unknown size %i\n", size); if (size == 4 && is_float) host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); - else if (size == 8 && is_float) + else if (size == 8) host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); @@ -206,6 +207,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 638c65a..be5a474 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -20,6 +20,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -96,7 +97,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); else if (size == 4 && is_float) host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); - else if (size == 8 && is_float) + else if (size == 8) host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); host_arm64_MOVZ_IMM(block, REG_W1, 0); host_arm64_RET(block, REG_X30); @@ -118,7 +119,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); if (size == 4 && is_float) host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); - else if (size == 8 && is_float) + else if (size == 8) host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); @@ -205,6 +206,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index f992759..1a91768 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -117,6 +117,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 1c6da2f..9603132 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -124,6 +124,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LSR (0x1ac02400) #define OPCODE_NOP (0xd503201f) #define OPCODE_RET (0xd65f0000) +#define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) @@ -754,6 +755,10 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); } +void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SCVTF_D_Q | Rd(dst_reg) | Rn(src_reg)); +} void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index fb83b83..ad759ea 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -106,6 +106,7 @@ void host_arm64_RET(codeblock_t *block, int reg); void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); +void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 7ec43dc..b3aa3c6 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -817,8 +817,12 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm64_call(block, codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_arm64_call(block, codegen_mem_load_quad); + } else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); if (REG_IS_B(dest_size)) { @@ -836,6 +840,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); } + else if (REG_IS_Q(dest_size)) + { + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + } return 0; } @@ -1169,6 +1177,11 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + host_arm64_FMOV_Q_D(block, REG_TEMP, src_reg); + host_arm64_SCVTF_D_Q(block, dest_reg, REG_TEMP); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 6473fd5..9901b29 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -69,6 +69,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 22e546d..b60f792 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -888,6 +888,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm_BL(block, (uintptr_t)codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_arm_BL(block, (uintptr_t)codegen_mem_load_quad); + } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_arm_TST_REG(block, REG_R1, REG_R1); @@ -908,6 +912,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_arm_MOV_REG(block, dest_reg, REG_R0); } + else if (REG_IS_Q(dest_size)) + { + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } return 0; } @@ -1237,6 +1245,10 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) return 0; } +static double int64_to_double(int64_t a) +{ + return (double)a; +} static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -1253,6 +1265,14 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + /*ARMv7 has no instructions to convert a 64-bit integer to a double. + For simplicity, call a C function and let the compiler do it.*/ + host_arm_VMOV_64_D(block, REG_R0, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t)int64_to_double); /*Input - R0/R1, Output - D0*/ + host_arm_VMOV_D_D(block, dest_reg, REG_D0); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index dc43a39..6306741 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -19,6 +19,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -92,7 +93,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); else if (size == 4 && is_float) host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); - else if (size == 8 && is_float) + else if (size == 8) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); else fatal("build_load_routine: size=%i\n", size); @@ -131,7 +132,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); } - else if (size == 8 && is_float) + else if (size == 8) { host_x86_CALL(block, (void *)readmemql); host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); @@ -242,6 +243,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index 01c0c26..4f7fe4f 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -50,6 +50,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 38cf727..3c3d6c1 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -348,7 +348,12 @@ void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 6d8a8f0..5286d2b 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -29,6 +29,7 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); @@ -75,6 +76,8 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); +void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); + void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); @@ -105,18 +108,17 @@ void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); - -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); @@ -125,8 +127,6 @@ void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg); -void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); - void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 367f36e..15060cf 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -765,6 +765,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_quad); + } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -781,6 +785,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_Q(dest_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } return 0; } @@ -1069,6 +1077,11 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); + host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index ab6a3be..71a5d0c 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -19,6 +19,7 @@ void *codegen_mem_load_byte; void *codegen_mem_load_word; void *codegen_mem_load_long; +void *codegen_mem_load_quad; void *codegen_mem_load_single; void *codegen_mem_load_double; @@ -90,7 +91,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); else if (size == 4 && is_float) host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else if (size == 8 && is_float) + else if (size == 8/* && is_float*/) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); else fatal("build_load_routine: size=%i\n", size); @@ -123,7 +124,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); } - else if (size == 8 && is_float) + else if (size == 8)// && is_float) { host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); @@ -228,6 +229,8 @@ static void build_loadstore_routines(codeblock_t *block) build_load_routine(block, 2, 0); codegen_mem_load_long = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); codegen_mem_load_single = &codeblock[block_current].data[block_pos]; build_load_routine(block, 4, 1); codegen_mem_load_double = &codeblock[block_current].data[block_pos]; diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 5a5ea69..e2ca668 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -28,6 +28,7 @@ extern void *codegen_mem_load_byte; extern void *codegen_mem_load_word; extern void *codegen_mem_load_long; +extern void *codegen_mem_load_quad; extern void *codegen_mem_load_single; extern void *codegen_mem_load_double; diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 6d5521a..360c1a3 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1316,4 +1316,20 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 } } +void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + else + codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ +} + +void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + else + codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ +} + #endif diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 102639a..1ebffeb 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -199,3 +199,6 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); + +void host_x87_FILDq_BASE(codeblock_t *block, int base_reg); +void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index d060bdd..ef9496f 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -755,6 +755,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_long); } + else if (REG_IS_Q(dest_size)) + { + host_x86_CALL(block, codegen_mem_load_quad); + } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -771,6 +775,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_Q(dest_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } return 0; } @@ -1060,6 +1068,15 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); } + else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) + { + /*There is no SSE instruction to convert a 64-bit integer to a floating point value. + Instead we have to bounce the integer through memory via x87.*/ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FILDq_BASE(block, REG_ESP); + host_x87_FSTPd_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + } else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 56fff16..2a4191b 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -444,17 +444,17 @@ RecompOpFn recomp_opcodes_df[512] = /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -466,17 +466,17 @@ RecompOpFn recomp_opcodes_df[512] = /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c index cfee360..90682e2 100644 --- a/src/codegen_ops_fpu_loadstore.c +++ b/src/codegen_ops_fpu_loadstore.c @@ -132,3 +132,19 @@ uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc+1; } +uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_MM(-1)); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); + fpu_PUSH(ir); + + return op_pc+1; +} diff --git a/src/codegen_ops_fpu_loadstore.h b/src/codegen_ops_fpu_loadstore.h index 727f715..58d4121 100644 --- a/src/codegen_ops_fpu_loadstore.h +++ b/src/codegen_ops_fpu_loadstore.h @@ -8,3 +8,4 @@ uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 87191dde55a64add6258db3b9d05a603da5b2cbb Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 25 Oct 2018 20:54:33 +0100 Subject: [PATCH 047/181] Added recompiled versions of FIST and FISTP. --- src/codegen_backend_arm.c | 77 +++++++++++++++++++++++++++- src/codegen_backend_arm64.c | 73 ++++++++++++++++++++++++++- src/codegen_backend_arm64_defs.h | 6 ++- src/codegen_backend_arm64_ops.c | 81 +++++++++++++++++++++++++++++ src/codegen_backend_arm64_ops.h | 19 +++++++ src/codegen_backend_arm64_uops.c | 55 +++++++++++++++++++- src/codegen_backend_arm_defs.h | 6 ++- src/codegen_backend_arm_ops.c | 21 ++++++-- src/codegen_backend_arm_ops.h | 3 ++ src/codegen_backend_arm_uops.c | 84 +++++++++++++++++++++++++++++++ src/codegen_backend_x86-64.c | 17 ++++++- src/codegen_backend_x86-64_defs.h | 1 + src/codegen_backend_x86-64_ops.c | 28 +++++++++++ src/codegen_backend_x86-64_ops.h | 6 +++ src/codegen_backend_x86-64_uops.c | 58 ++++++++++++++++++++- src/codegen_backend_x86.c | 26 +++++++--- src/codegen_backend_x86_defs.h | 1 + src/codegen_backend_x86_ops.c | 61 +++++++++++++++++++++- src/codegen_backend_x86_ops.h | 9 ++++ src/codegen_backend_x86_uops.c | 82 +++++++++++++++++++++++++++--- src/codegen_ir.c | 2 +- src/codegen_ir_defs.h | 20 ++++++++ src/codegen_ops.c | 36 ++++++------- src/codegen_ops_fpu_loadstore.c | 79 +++++++++++++++++++++++++++++ src/codegen_ops_fpu_loadstore.h | 6 +++ src/codegen_reg.h | 1 + src/ibm.h | 6 ++- src/x87.h | 6 +++ src/x87_ops_misc.h | 16 +++--- 29 files changed, 829 insertions(+), 57 deletions(-) diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 7e46a7b..5852294 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -8,6 +8,7 @@ #include "codegen_backend_arm_ops.h" #include "codegen_reg.h" #include "x86.h" +#include "x87.h" #if defined(__linux__) || defined(__APPLE__) #include @@ -27,9 +28,12 @@ void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_quad; void *codegen_mem_store_single; void *codegen_mem_store_double; +void *codegen_fp_round; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_R4, @@ -167,7 +171,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0); } - else if (size == 8 && is_float) + else if (size == 8) { host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0); @@ -181,7 +185,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); if (size == 4 && is_float) host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); - else if (size == 8 && is_float) + else if (size == 8) host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); if (size == 1) host_arm_BL(block, (uintptr_t)writememb386l); @@ -220,12 +224,65 @@ static void build_loadstore_routines(codeblock_t *block) build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); codegen_mem_store_single = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 1); codegen_mem_store_double = &codeblock[block_current].data[block_pos]; build_store_routine(block, 8, 1); } +/*VFP has a specific round-to-zero instruction, and the default rounding mode + is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/ +#define FPCSR_ROUNDING_MASK (3 << 22) +#define FPCSR_ROUNDING_UP (1 << 22) +#define FPCSR_ROUNDING_DOWN (2 << 22) + +static void build_fp_round_routine(codeblock_t *block) +{ + uint32_t *jump_table; + + host_arm_MOV_REG(block, REG_TEMP2, REG_LR); + host_arm_MOV_REG(block, REG_LR, REG_TEMP2); + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); + host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); + addlong(0); + + jump_table = (uint32_t *)&block->data[block_pos]; + addlong(0); + addlong(0); + addlong(0); + addlong(0); + + jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); + host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); + host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP); + host_arm_VMSR_FPSCR(block, REG_TEMP2); + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_VMSR_FPSCR(block, REG_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); + host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); + host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN); + host_arm_VMSR_FPSCR(block, REG_TEMP2); + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_VMSR_FPSCR(block, REG_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero + host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + block_pos = (block_pos + 63) & ~63; +} + void codegen_backend_init() { int c; @@ -265,6 +322,22 @@ void codegen_backend_init() block_current = BLOCK_SIZE; block_pos = 0; build_loadstore_routines(&codeblock[block_current]); + + codegen_fp_round = &codeblock[block_current].data[block_pos]; + build_fp_round_routine(&codeblock[block_current]); + + asm("vmrs %0, fpscr\n" + : "=r" (cpu_state.old_fp_control) + ); + if ((cpu_state.old_fp_control >> 22) & 3) + fatal("VFP not in nearest rounding mode\n"); +} + +void codegen_set_rounding_mode(int mode) +{ + if (mode < 0 || mode > 3) + fatal("codegen_set_rounding_mode - invalid mode\n"); + cpu_state.new_fp_control = mode << 2; } /*R10 - cpu_state*/ diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index be5a474..f201c4b 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -8,6 +8,7 @@ #include "codegen_backend_arm64_ops.h" #include "codegen_reg.h" #include "x86.h" +#include "x87.h" #if defined(__linux__) || defined(__APPLE__) #include @@ -27,9 +28,13 @@ void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_quad; void *codegen_mem_store_single; void *codegen_mem_store_double; +void *codegen_fp_round; +void *codegen_fp_round_quad; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_X19, @@ -168,7 +173,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); else if (size == 4 && is_float) host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0); - else if (size == 8 && is_float) + else if (size == 8) host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0); host_arm64_MOVZ_IMM(block, REG_X1, 0); host_arm64_RET(block, REG_X30); @@ -179,7 +184,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); if (size == 4 && is_float) host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); - else if (size == 8 && is_float) + else if (size == 8) host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); if (size == 1) host_arm64_call(block, (uintptr_t)writememb386l); @@ -219,12 +224,60 @@ static void build_loadstore_routines(codeblock_t *block) build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); codegen_mem_store_single = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 1); codegen_mem_store_double = &codeblock[block_current].data[block_pos]; build_store_routine(block, 8, 1); } +static void build_fp_round_routine(codeblock_t *block, int is_quad) +{ + uint64_t *jump_table; + + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); + host_arm64_ADR(block, REG_TEMP2, 12); + host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); + host_arm64_BR(block, REG_TEMP2); + + jump_table = &block->data[block_pos]; + addquad(0); + addquad(0); + addquad(0); + addquad(0); + + jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even + if (is_quad) + host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); + + jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf + if (is_quad) + host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); + + jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf + if (is_quad) + host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); + + jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero + if (is_quad) + host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); + + block_pos = (block_pos + 63) & ~63; +} + void codegen_backend_init() { int c; @@ -265,6 +318,22 @@ void codegen_backend_init() block_pos = 0; codegen_reset_literal_pool(&codeblock[block_current]); build_loadstore_routines(&codeblock[block_current]); + + codegen_fp_round = &codeblock[block_current].data[block_pos]; + build_fp_round_routine(&codeblock[block_current], 0); + codegen_fp_round_quad = &codeblock[block_current].data[block_pos]; + build_fp_round_routine(&codeblock[block_current], 1); + + asm("mrs %0, fpcr\n" + : "=r" (cpu_state.old_fp_control) + ); +} + +void codegen_set_rounding_mode(int mode) +{ + if (mode < 0 || mode > 3) + fatal("codegen_set_rounding_mode - invalid mode\n"); + cpu_state.new_fp_control = mode << 3; } /*R11 - literal pool diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index 1a91768..cd771cb 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -124,5 +124,9 @@ extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; -extern void *codegen_mem_store_double; \ No newline at end of file +extern void *codegen_mem_store_double; + +extern void *codegen_fp_round; +extern void *codegen_fp_round_quad; \ No newline at end of file diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 9603132..d3d62c2 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -48,6 +48,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) #define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) +#define OPCODE_ADR (0x10 << OPCODE_SHIFT) #define OPCODE_B (0x14 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) @@ -59,6 +60,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) +#define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) #define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_ANDS_IMM (0x0e4 << 23) @@ -69,6 +71,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BFI (0x0cc << 22) #define OPCODE_LDR_IMM_W (0x2e5 << 22) +#define OPCODE_LDR_IMM_X (0x3e5 << 22) #define OPCODE_LDR_IMM_F64 (0x3f5 << 22) #define OPCODE_LDRB_IMM_W (0x0e5 << 22) #define OPCODE_LDRH_IMM (0x1e5 << 22) @@ -105,6 +108,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_FADD_D (0x1e602800) #define OPCODE_FCVT_D_S (0x1e22c000) #define OPCODE_FCVT_S_D (0x1e624000) +#define OPCODE_FCVTMS_W_D (0x1e700000) +#define OPCODE_FCVTMS_X_D (0x9e700000) +#define OPCODE_FCVTNS_W_D (0x1e600000) +#define OPCODE_FCVTNS_X_D (0x9e600000) +#define OPCODE_FCVTPS_W_D (0x1e680000) +#define OPCODE_FCVTPS_X_D (0x9e680000) +#define OPCODE_FCVTZS_W_D (0x1e780000) +#define OPCODE_FCVTZS_X_D (0x9e780000) #define OPCODE_FDIV_D (0x1e601800) #define OPCODE_FMOV_D_D (0x1e604000) #define OPCODE_FMOV_D_Q (0x9e670000) @@ -112,8 +123,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_FMOV_S_W (0x1e270000) #define OPCODE_FMOV_W_S (0x1e260000) #define OPCODE_FMUL_D (0x1e600800) +#define OPCODE_FRINTX_D (0x1e674000) #define OPCODE_FSUB_D (0x1e603800) #define OPCODE_LDR_REG (0xb8606800) +#define OPCODE_LDRX_REG (0xf8606800) #define OPCODE_LDRB_REG (0x38606800) #define OPCODE_LDRH_REG (0x78606800) #define OPCODE_LDRX_REG_LSL3 (0xf8607800) @@ -122,6 +135,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LDR_REG_F64_S (0xfc607800) #define OPCODE_LSL (0x1ac02000) #define OPCODE_LSR (0x1ac02400) +#define OPCODE_MSR_FPCR (0xd51b4400) #define OPCODE_NOP (0xd503201f) #define OPCODE_RET (0xd65f0000) #define OPCODE_SCVTF_D_Q (0x9e620000) @@ -145,7 +159,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define IMMR(immr) ((immr) << 16) #define IMMS(imms) ((imms) << 10) +#define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) + #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) +#define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5)) #define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) #define OFFSET12_B(offset) (offset << 10) @@ -254,6 +271,11 @@ void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) +{ + codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset)); +} + void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ @@ -534,6 +556,39 @@ void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTMS_W_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTMS_X_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTNS_W_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTNS_X_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTPS_W_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTPS_X_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTZS_W_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); @@ -570,6 +625,11 @@ void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { if (!in_range7_x(offset)) @@ -583,6 +643,12 @@ void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int of fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); } +void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if (!in_range12_q(offset)) + fatal("host_arm64_LDR_IMM_X out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); +} void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) { @@ -606,6 +672,10 @@ void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offs { codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } +void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +{ + codegen_addlong(block, OPCODE_LDRX_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); +} void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { @@ -711,6 +781,11 @@ void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); } +void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg) +{ + codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg)); +} + void host_arm64_NOP(codeblock_t *block) { codegen_addlong(block, OPCODE_NOP); @@ -862,6 +937,12 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) +{ + codegen_addlong(block, OPCODE_TBNZ | Rt(reg) | BIT_TBxZ(bit)); + return (uint32_t *)&block->data[block_pos-4]; +} + void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index ad759ea..3409335 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -2,6 +2,8 @@ void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset); + void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); @@ -59,18 +61,31 @@ void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); +void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset); void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); +void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -97,6 +112,8 @@ void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shi void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data); +void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg); + void host_arm64_NOP(codeblock_t *block); void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); @@ -130,6 +147,8 @@ void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit); + #define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data) void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index b3aa3c6..649c72f 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -942,8 +942,13 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_arm64_MOV_REG(block, REG_W1, src_reg, 0); host_arm64_call(block, codegen_mem_store_long); } + else if (REG_IS_Q(src_size)) + { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_quad); + } else - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); return 0; @@ -1187,6 +1192,52 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) + { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round); + host_arm64_MOV_REG(block, dest_reg, REG_TEMP, 0); + } + else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) + { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) + { + uint8_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_arm64_FMOV_D_D(block, dest_reg, src_64_reg); + branch_offset = host_arm64_TBNZ(block, tag_reg, 7); + + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round_quad); + host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); + + host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + } + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -1719,6 +1770,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 9901b29..7deb72f 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -22,7 +22,8 @@ #define REG_CPUSTATE REG_R10 -#define REG_TEMP REG_R3 +#define REG_TEMP REG_R3 +#define REG_TEMP2 REG_R2 #define REG_D0 0 #define REG_D1 1 @@ -76,5 +77,8 @@ extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; + +extern void *codegen_fp_round; \ No newline at end of file diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 06841ea..98653e7 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -104,9 +104,11 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 #define OPCODE_VADD 0xee300b00 -#define OPCODE_VCVT_D_IS 0xeeb80bc0 -#define OPCODE_VCVT_D_S 0xeeb70ac0 -#define OPCODE_VCVT_S_D 0xeeb70bc0 +#define OPCODE_VCVT_D_IS 0xeeb80bc0 +#define OPCODE_VCVT_D_S 0xeeb70ac0 +#define OPCODE_VCVT_IS_D 0xeebd0bc0 +#define OPCODE_VCVT_S_D 0xeeb70bc0 +#define OPCODE_VCVTR_IS_D 0xeebd0b40 #define OPCODE_VDIV 0xee800b00 #define OPCODE_VLDR_D 0xed900b00 #define OPCODE_VLDR_S 0xed900a00 @@ -115,6 +117,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMOV_D_64 0xec400b10 #define OPCODE_VMOV_S_32 0xee000a10 #define OPCODE_VMOV_D_D 0xeeb00b40 +#define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 @@ -770,10 +773,18 @@ void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVTR_IS_D | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -810,6 +821,10 @@ void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); +} void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 6e2218e..478d232 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -118,7 +118,9 @@ void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -127,6 +129,7 @@ void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high); void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index b60f792..5b00a61 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1,7 +1,9 @@ #ifdef __ARM_EABI__ +#include #include "ibm.h" #include "x86.h" +#include "x87.h" #include "386_common.h" #include "codegen.h" #include "codegen_backend.h" @@ -1013,6 +1015,11 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_arm_MOV_REG(block, REG_R1, src_reg); host_arm_BL(block, (uintptr_t)codegen_mem_store_long); } + else if (REG_IS_Q(src_size)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t)codegen_mem_store_quad); + } else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); host_arm_TST_REG(block, REG_R1, REG_R1); @@ -1278,6 +1285,81 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t)codegen_fp_round); + host_arm_VMOV_32_S(block, dest_reg, REG_D_TEMP); + } + else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t)codegen_fp_round); + host_arm_VMOV_32_S(block, REG_TEMP, REG_D_TEMP); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int64_t x87_fround64(double b) +{ + int64_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int64_t)floor(b); + c = (int64_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t)floor(b); + case 2: /*Up*/ + return (int64_t)ceil(b); + case 3: /*Chop*/ + return (int64_t)b; + } + + return 0; +} +static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) + { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_arm_VMOV_D_D(block, dest_reg, src_64_reg); + host_arm_TST_IMM(block, tag_reg, TAG_UINT64); + branch_offset = host_arm_BNE_(block); + + /*VFP/NEON has no instructions to convert a float to 64-bit integer, + so call out to C.*/ + host_arm_VMOV_D_D(block, REG_D0, src_reg); + host_arm_call(block, x87_fround64); + host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); + + *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + } + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -1810,6 +1892,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 6306741..bb92241 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -26,6 +26,7 @@ void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_quad; void *codegen_mem_store_single; void *codegen_mem_store_double; @@ -192,7 +193,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); else if (size == 4 && is_float) host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); - else if (size == 8 && is_float) + else if (size == 8) host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); else fatal("build_store_routine: size=%i\n", size); @@ -208,7 +209,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); if (size == 4 && is_float) host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data - else if (size == 8 && is_float) + else if (size == 8) host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data else host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data @@ -256,6 +257,8 @@ static void build_loadstore_routines(codeblock_t *block) build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); codegen_mem_store_single = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 1); codegen_mem_store_double = &codeblock[block_current].data[block_pos]; @@ -300,6 +303,16 @@ void codegen_backend_init() block_pos = 0; build_loadstore_routines(&codeblock[block_current]); // fatal("Here\n"); + + asm( + "stmxcsr %0\n" + : "=m" (cpu_state.old_fp_control) + ); +} + +void codegen_set_rounding_mode(int mode) +{ + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); } static inline void call(codeblock_t *block, uintptr_t func) diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index 4f7fe4f..7f93633 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -57,5 +57,6 @@ extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 3c3d6c1..bfa71d1 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -341,6 +341,15 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ +} +void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); @@ -392,6 +401,11 @@ uint8_t *host_x86_JNZ_short(codeblock_t *block) codegen_addbyte2(block, 0x75, 0); /*JNZ*/ return &block->data[block_pos-1]; } +uint8_t *host_x86_JS_short(codeblock_t *block) +{ + codegen_addbyte2(block, 0x78, 0); /*JS*/ + return &block->data[block_pos-1]; +} uint8_t *host_x86_JZ_short(codeblock_t *block) { codegen_addbyte2(block, 0x74, 0); /*JZ*/ @@ -483,6 +497,20 @@ uint32_t *host_x86_JZ_long(codeblock_t *block) return (uint32_t *)&block->data[block_pos-4]; } +void host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } + else + { + fatal("host_x86_LDMXCSR - out of range %p\n", p); + } +} + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) { if (offset) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 5286d2b..5c9e298 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -27,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg); @@ -41,6 +43,7 @@ void host_x86_JNZ(codeblock_t *block, void *p); void host_x86_JZ(codeblock_t *block, void *p); uint8_t *host_x86_JNZ_short(codeblock_t *block); +uint8_t *host_x86_JS_short(codeblock_t *block); uint8_t *host_x86_JZ_short(codeblock_t *block); uint32_t *host_x86_JNB_long(codeblock_t *block); @@ -58,6 +61,8 @@ uint32_t *host_x86_JO_long(codeblock_t *block); uint32_t *host_x86_JS_long(codeblock_t *block); uint32_t *host_x86_JZ_long(codeblock_t *block); +void host_x86_LDMXCSR(codeblock_t *block, void *p); + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset); void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); @@ -111,6 +116,7 @@ void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg); void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 15060cf..5c54d8a 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -918,8 +918,13 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); } + else if (REG_IS_Q(src_size)) + { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_quad); + } else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); @@ -1087,6 +1092,55 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) + { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } + else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) + { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) + { + uint8_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + branch_offset = host_x86_JS_short(block); + + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); + + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + } + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -1517,6 +1571,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 71a5d0c..daeff4d 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -26,6 +26,7 @@ void *codegen_mem_load_double; void *codegen_mem_store_byte; void *codegen_mem_store_word; void *codegen_mem_store_long; +void *codegen_mem_store_quad; void *codegen_mem_store_single; void *codegen_mem_store_double; @@ -91,7 +92,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); else if (size == 4 && is_float) host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else if (size == 8/* && is_float*/) + else if (size == 8) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); else fatal("build_load_routine: size=%i\n", size); @@ -124,7 +125,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); } - else if (size == 8)// && is_float) + else if (size == 8) { host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); @@ -181,7 +182,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); else if (size == 4 && is_float) host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); - else if (size == 8 && is_float) + else if (size == 8) host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); else fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); @@ -196,7 +197,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_PUSH(block, REG_EAX); host_x86_PUSH(block, REG_EDX); host_x86_PUSH(block, REG_ECX); - if (size == 8 && is_float) + if (size == 8) { host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 8); @@ -211,7 +212,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) else if (size == 8) host_x86_CALL(block, (void *)writememql); host_x86_POP(block, REG_EDI); - if (size == 8 && is_float) + if (size == 8) host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 8); host_x86_POP(block, REG_ECX); host_x86_POP(block, REG_EDX); @@ -242,6 +243,8 @@ static void build_loadstore_routines(codeblock_t *block) build_store_routine(block, 2, 0); codegen_mem_store_long = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); codegen_mem_store_single = &codeblock[block_current].data[block_pos]; build_store_routine(block, 4, 1); codegen_mem_store_double = &codeblock[block_current].data[block_pos]; @@ -298,12 +301,23 @@ void codegen_backend_init() build_loadstore_routines(&codeblock[block_current]); //fatal("Here\n"); + cpu_state.old_fp_control = 0; asm( "fstcw %0\n" - : "=m" (cpu_state.old_npxc) + "stmxcsr %1\n" + : "=m" (cpu_state.old_fp_control2), + "=m" (cpu_state.old_fp_control) ); } +void codegen_set_rounding_mode(int mode) +{ + /*SSE*/ + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); + /*x87 - used for double -> i64 conversions*/ + cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10); +} + void codegen_backend_prologue(codeblock_t *block) { block_pos = 0; /*Entry code*/ diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index e2ca668..03b2a2e 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -35,6 +35,7 @@ extern void *codegen_mem_load_double; extern void *codegen_mem_store_byte; extern void *codegen_mem_store_word; extern void *codegen_mem_store_long; +extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 360c1a3..d68f203 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -309,14 +309,18 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ +} void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ } void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) @@ -339,6 +343,12 @@ void host_x86_JMP(codeblock_t *block, void *p) codegen_addbyte(block, 0xe9); /*JMP*/ codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); } +uint32_t *host_x86_JMP_long(codeblock_t *block) +{ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, 0); + return (uint32_t *)&block->data[block_pos-4]; +} void host_x86_JNZ(codeblock_t *block, void *p) { @@ -356,6 +366,11 @@ uint8_t *host_x86_JNZ_short(codeblock_t *block) codegen_addbyte2(block, 0x75, 0); /*JNZ*/ return &block->data[block_pos-1]; } +uint8_t *host_x86_JS_short(codeblock_t *block) +{ + codegen_addbyte2(block, 0x78, 0); /*JS*/ + return &block->data[block_pos-1]; +} uint8_t *host_x86_JZ_short(codeblock_t *block) { codegen_addbyte2(block, 0x74, 0); /*JZ*/ @@ -447,6 +462,21 @@ uint32_t *host_x86_JZ_long(codeblock_t *block) return (uint32_t *)&block->data[block_pos-4]; } +void host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } + else + { + codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) { if (offset) @@ -1323,7 +1353,34 @@ void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) else codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ } +void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ + else + codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ +} +void host_x87_FLDCW(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + if (offset >= -128 && offset < 127) + { + codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ + } + else + { + codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ + else + codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ +} void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 1ebffeb..943ba40 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -27,6 +27,7 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg); @@ -37,11 +38,14 @@ void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_JMP(codeblock_t *block, void *p); +uint32_t *host_x86_JMP_short(codeblock_t *block); +uint32_t *host_x86_JMP_long(codeblock_t *block); void host_x86_JNZ(codeblock_t *block, void *p); void host_x86_JZ(codeblock_t *block, void *p); uint8_t *host_x86_JNZ_short(codeblock_t *block); +uint8_t *host_x86_JS_short(codeblock_t *block); uint8_t *host_x86_JZ_short(codeblock_t *block); uint32_t *host_x86_JNB_long(codeblock_t *block); @@ -59,6 +63,8 @@ uint32_t *host_x86_JO_long(codeblock_t *block); uint32_t *host_x86_JS_long(codeblock_t *block); uint32_t *host_x86_JZ_long(codeblock_t *block); +void host_x86_LDMXCSR(codeblock_t *block, void *p); + void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset); void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); @@ -201,4 +207,7 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); void host_x87_FILDq_BASE(codeblock_t *block, int base_reg); +void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg); +void host_x87_FLDCW(codeblock_t *block, void *p); +void host_x87_FLDd_BASE(codeblock_t *block, int base_reg); void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index ef9496f..8537c3d 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -630,6 +630,12 @@ static int codegen_JMP(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_JMP_DEST(codeblock_t *block, uop_t *uop) +{ + uop->p = host_x86_JMP_long(block); + + return 0; +} static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) { @@ -872,8 +878,13 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); } + else if (REG_IS_Q(src_size)) + { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_quad); + } else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); @@ -1082,6 +1093,60 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) + { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } + else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) + { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) + { + uint8_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + branch_offset = host_x86_JS_short(block); + + /*There is no SSE instruction to convert a floating point value to a 64-bit integer. + Instead we have to bounce through memory via x87.*/ + host_x87_FLDCW(block, &cpu_state.new_fp_control2); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FLDd_BASE(block, REG_ESP); + host_x87_FISTPq_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + host_x87_FLDCW(block, &cpu_state.old_fp_control2); + + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + } + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -1473,6 +1538,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_JMP_DEST & UOP_MASK] = codegen_JMP_DEST, [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, @@ -1502,12 +1568,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, + [UOP_MOV & UOP_MASK] = codegen_MOV, + [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, + [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, + [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, + [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_ir.c b/src/codegen_ir.c index c179632..bd0e541 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -66,7 +66,7 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) } if (!uop_handlers[uop->type & UOP_MASK]) - fatal("!uop_handlers[uop->type & UOP_MASK]\n"); + fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type); uop_handlers[uop->type & UOP_MASK](block, uop); if (uop->type & UOP_TYPE_JUMP) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 036493e..d893067 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -52,6 +52,8 @@ #define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER) /*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/ #define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) +/*UOP_JMP_DEST - jump to ptr*/ +#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_MOV_PTR - dest_reg = p*/ #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) /*UOP_MOV_IMM - dest_reg = imm_data*/ @@ -64,6 +66,10 @@ #define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) /*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/ #define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25) +/*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ +#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26) +/*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ +#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27) /*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) /*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ @@ -322,6 +328,17 @@ static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, in uop->imm_data = imm; } +static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->dest_reg_a = codegen_reg_write(dest_reg); +} + static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) { uop_t *uop = uop_alloc(ir); @@ -471,6 +488,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; } while (0) #define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) +#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) #define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) @@ -494,6 +512,8 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) #define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) #define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) +#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/) +#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 2a4191b..4a6d0a2 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -255,17 +255,17 @@ RecompOpFn recomp_opcodes_db[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -277,17 +277,17 @@ RecompOpFn recomp_opcodes_db[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -443,19 +443,19 @@ RecompOpFn recomp_opcodes_df[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, /*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, /*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -465,19 +465,19 @@ RecompOpFn recomp_opcodes_df[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, /*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, /*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c index 90682e2..8be00d2 100644 --- a/src/codegen_ops_fpu_loadstore.c +++ b/src/codegen_ops_fpu_loadstore.c @@ -148,3 +148,82 @@ uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc+1; } + +uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + + return op_pc+1; +} +uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(ir); + + return op_pc+1; +} +uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + + return op_pc+1; +} +uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(ir); + + return op_pc+1; +} +uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_MM(0), IREG_tag(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(ir); + + return op_pc+1; +} diff --git a/src/codegen_ops_fpu_loadstore.h b/src/codegen_ops_fpu_loadstore.h index 58d4121..b206f96 100644 --- a/src/codegen_ops_fpu_loadstore.h +++ b/src/codegen_ops_fpu_loadstore.h @@ -9,3 +9,9 @@ uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 2830d40..ad890ae 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -165,6 +165,7 @@ enum #define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) #define IREG_MM(r) (IREG_MM0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) #define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) +#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) #define IREG_TOP_diff_stack_offset 32 diff --git a/src/ibm.h b/src/ibm.h index 6503b67..c829b51 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -177,8 +177,10 @@ struct MMX_REG MM[8]; - uint16_t old_npxc, new_npxc; - + uint32_t old_fp_control, new_fp_control; +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ + uint16_t old_fp_control2, new_fp_control2; +#endif x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs; union diff --git a/src/x87.h b/src/x87.h index cd4ccbb..3960efa 100644 --- a/src/x87.h +++ b/src/x87.h @@ -24,3 +24,9 @@ void x87_reset(); /*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ #define TAG_UINT64 (1 << 7) +#define X87_ROUNDING_NEAREST 0 +#define X87_ROUNDING_DOWN 1 +#define X87_ROUNDING_UP 2 +#define X87_ROUNDING_CHOP 3 + +void codegen_set_rounding_mode(int mode); diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index eb9fffb..4354cb2 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -32,7 +32,7 @@ static int opFINIT(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; cpu_state.npxc = 0x37F; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + codegen_set_rounding_mode(X87_ROUNDING_NEAREST); cpu_state.npxs = 0; *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; @@ -86,7 +86,7 @@ static int FSTOR() case 0x000: /*16-bit real mode*/ case 0x001: /*16-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -95,7 +95,7 @@ static int FSTOR() case 0x100: /*32-bit real mode*/ case 0x101: /*32-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -276,7 +276,7 @@ static int FSAVE() } cpu_state.npxc = 0x37F; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + codegen_set_rounding_mode(X87_ROUNDING_NEAREST); cpu_state.npxs = 0; *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; @@ -682,7 +682,7 @@ static int FLDENV() case 0x000: /*16-bit real mode*/ case 0x001: /*16-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -690,7 +690,7 @@ static int FLDENV() case 0x100: /*32-bit real mode*/ case 0x101: /*32-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -727,7 +727,7 @@ static int opFLDCW_a16(uint32_t fetchdat) tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); CLOCK_CYCLES(4); return 0; } @@ -741,7 +741,7 @@ static int opFLDCW_a32(uint32_t fetchdat) tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); CLOCK_CYCLES(4); return 0; } From b814bcc80dd272fd86bff0cc8426c443fcd8e20d Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 25 Oct 2018 21:43:32 +0100 Subject: [PATCH 048/181] Added recompiled versions of FSTCW and FSTSW. --- src/codegen_ops.c | 29 +++++----- src/codegen_ops_fpu_misc.c | 111 +++++++++++++++++++++++++++++++++++++ src/codegen_ops_fpu_misc.h | 12 ++++ src/codegen_reg.c | 3 + src/codegen_reg.h | 10 +++- 5 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 src/codegen_ops_fpu_misc.c create mode 100644 src/codegen_ops_fpu_misc.h diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 4a6d0a2..a36bd40 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -5,6 +5,7 @@ #include "codegen_ops_arith.h" #include "codegen_ops_branch.h" #include "codegen_ops_fpu_arith.h" +#include "codegen_ops_fpu_constant.h" #include "codegen_ops_fpu_loadstore.h" #include "codegen_ops_fpu_misc.h" #include "codegen_ops_jump.h" @@ -163,17 +164,17 @@ RecompOpFn recomp_opcodes_d9[512] = /*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, /*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, /*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, @@ -185,17 +186,17 @@ RecompOpFn recomp_opcodes_d9[512] = /*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, /*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, /*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, @@ -351,17 +352,17 @@ RecompOpFn recomp_opcodes_dd[512] = /*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, /*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, /*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, /*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, @@ -373,17 +374,17 @@ RecompOpFn recomp_opcodes_dd[512] = /*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, /*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, /*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, /*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, @@ -459,7 +460,7 @@ RecompOpFn recomp_opcodes_df[512] = /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ @@ -481,6 +482,6 @@ RecompOpFn recomp_opcodes_df[512] = /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/src/codegen_ops_fpu_misc.c b/src/codegen_ops_fpu_misc.c new file mode 100644 index 0000000..2509cc7 --- /dev/null +++ b/src/codegen_ops_fpu_misc.c @@ -0,0 +1,111 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "x87.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_fpu_misc.h" +#include "codegen_ops_helpers.h" + +uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY); + + return op_pc; +} + +uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); + uop_MOV(ir, IREG_MM(-1), IREG_MM(src_reg)); + uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); + fpu_PUSH(ir); + + return op_pc; +} + +uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + + return op_pc; +} +uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + fpu_POP(ir); + + return op_pc; +} + +uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC); + + return op_pc; +} +uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS); + + return op_pc; +} +uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_AX, IREG_NPXS); + + return op_pc; +} + +uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_temp0_D, IREG_ST(0)); + uop_MOV(ir, IREG_temp1_Q, IREG_MM(0)); + uop_MOV(ir, IREG_temp2, IREG_tag(0)); + uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV(ir, IREG_MM(0), IREG_MM(dest_reg)); + uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg)); + uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D); + uop_MOV(ir, IREG_MM(dest_reg), IREG_temp1_Q); + uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2); + + return op_pc; +} diff --git a/src/codegen_ops_fpu_misc.h b/src/codegen_ops_fpu_misc.h new file mode 100644 index 0000000..257aa7a --- /dev/null +++ b/src/codegen_ops_fpu_misc.h @@ -0,0 +1,12 @@ +uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index ac1e417..2e76874 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -123,6 +123,9 @@ struct [IREG_MM6] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, [IREG_MM7] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER}, + [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ diff --git a/src/codegen_reg.h b/src/codegen_reg.h index ad890ae..3bb69b2 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -103,8 +103,11 @@ enum IREG_MM5 = 61, IREG_MM6 = 62, IREG_MM7 = 63, + + IREG_NPXCx = 64, + IREG_NPXSx = 65, - IREG_COUNT = 64, + IREG_COUNT = 66, IREG_INVALID = 255, @@ -155,7 +158,10 @@ enum IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W, IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W, IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, - IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W + IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, + + IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, + IREG_NPXS = IREG_NPXSx + IREG_SIZE_W }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) From 0055238ade02112d56526be97f0796bc710360c1 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 14 Nov 2018 21:42:20 +0000 Subject: [PATCH 049/181] Added recompiled versions of FCOM, FCOMP, FCOMPP, FICOM, FICOM, FUCOM, FUCOMP and FUCOMPP. --- src/codegen_backend_arm64_ops.c | 21 +++++ src/codegen_backend_arm64_ops.h | 6 ++ src/codegen_backend_arm64_uops.c | 23 +++++ src/codegen_backend_arm_ops.c | 39 ++++----- src/codegen_backend_arm_ops.h | 30 ++++++- src/codegen_backend_arm_uops.c | 20 +++++ src/codegen_backend_x86-64_ops.c | 10 +++ src/codegen_backend_x86-64_ops.h | 4 + src/codegen_backend_x86-64_uops.c | 26 ++++++ src/codegen_backend_x86_ops.c | 10 +++ src/codegen_backend_x86_ops.h | 4 + src/codegen_backend_x86_uops.c | 28 +++++- src/codegen_ir_defs.h | 5 +- src/codegen_ops.c | 68 +++++++-------- src/codegen_ops_fpu_arith.c | 138 ++++++++++++++++++++++++++++++ src/codegen_ops_fpu_arith.h | 14 +++ src/x87.h | 5 ++ src/x87_ops.h | 5 -- 18 files changed, 390 insertions(+), 66 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index d3d62c2..724ea8b 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -44,6 +44,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define COND_GT (0xc) #define COND_LE (0xd) +#define CSEL_COND(cond) ((cond) << 12) #define OPCODE_SHIFT 24 #define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) @@ -93,6 +94,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_AND_ROR (0x056 << 21) #define OPCODE_ANDS_LSL (0x350 << 21) #define OPCODE_CMP_LSL (0x358 << 21) +#define OPCODE_CSEL (0x0d4 << 21) #define OPCODE_EOR_LSL (0x250 << 21) #define OPCODE_ORR_ASR (0x154 << 21) #define OPCODE_ORR_LSL (0x150 << 21) @@ -106,6 +108,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BLR (0xd63f0000) #define OPCODE_BR (0xd61f0000) #define OPCODE_FADD_D (0x1e602800) +#define OPCODE_FCMP_D (0x1e602000) #define OPCODE_FCVT_D_S (0x1e22c000) #define OPCODE_FCVT_S_D (0x1e624000) #define OPCODE_FCVTMS_W_D (0x1e700000) @@ -525,6 +528,19 @@ void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, in codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_CC) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_EQ) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ @@ -547,6 +563,11 @@ void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FCMP_D | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_FCVT_D_S | Rd(dst_reg) | Rn(src_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 3409335..ccccae6 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -50,10 +50,16 @@ void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); #define host_arm64_CMP_REG(block, src_n_reg, src_m_reg) host_arm64_CMP_REG_LSL(block, src_n_reg, src_m_reg, 0) void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift); + +void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg); void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 649c72f..1d8aec5 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "x86.h" +#include "x87.h" #include "386_common.h" #include "codegen.h" #include "codegen_backend.h" @@ -613,6 +614,27 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm64_MOVZ_IMM(block, dest_reg, 0); + host_arm64_FCMP_D(block, src_reg_a, src_reg_b); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0|C2|C3); + host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); + host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); + } + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} static int codegen_FDIV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1816,6 +1838,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FCOM & UOP_MASK] = codegen_FCOM, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 98653e7..85d3646 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -31,23 +31,6 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define DATA_OFFSET_UP (1 << 23) #define DATA_OFFSET_DOWN (0 << 23) -#define COND_SHIFT 28 -#define COND_EQ (0x0 << COND_SHIFT) -#define COND_NE (0x1 << COND_SHIFT) -#define COND_CS (0x2 << COND_SHIFT) -#define COND_CC (0x3 << COND_SHIFT) -#define COND_MI (0x4 << COND_SHIFT) -#define COND_PL (0x5 << COND_SHIFT) -#define COND_VS (0x6 << COND_SHIFT) -#define COND_VC (0x7 << COND_SHIFT) -#define COND_HI (0x8 << COND_SHIFT) -#define COND_LS (0x9 << COND_SHIFT) -#define COND_GE (0xa << COND_SHIFT) -#define COND_LT (0xb << COND_SHIFT) -#define COND_GT (0xc << COND_SHIFT) -#define COND_LE (0xd << COND_SHIFT) -#define COND_AL (0xe << COND_SHIFT) - #define OPCODE_SHIFT 20 #define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) #define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) @@ -104,6 +87,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 #define OPCODE_VADD 0xee300b00 +#define OPCODE_VCMP_D 0xeeb40b40 #define OPCODE_VCVT_D_IS 0xeeb80bc0 #define OPCODE_VCVT_D_S 0xeeb70ac0 #define OPCODE_VCVT_IS_D 0xeebd0bc0 @@ -117,6 +101,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMOV_D_64 0xec400b10 #define OPCODE_VMOV_S_32 0xee000a10 #define OPCODE_VMOV_D_D 0xeeb00b40 +#define OPCODE_VMRS_APSR 0xeef1fa10 #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 #define OPCODE_VSTR_D 0xed800b00 @@ -208,7 +193,7 @@ static inline int in_range(void *addr, void *base) void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +//void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) @@ -614,24 +599,24 @@ void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm) { uint32_t arm_imm; if (get_arm_imm(imm, &arm_imm)) { - codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + codegen_addlong(block, cond | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); } else { host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + host_arm_ORR_REG_LSL_cond(block, cond, dst_reg, src_reg, REG_TEMP, 0); } } -void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) @@ -765,6 +750,10 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); +} void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); @@ -825,6 +814,10 @@ void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); } +void host_arm_VMRS_APSR(codeblock_t *block) +{ + codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); +} void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 478d232..1fdd609 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -1,3 +1,20 @@ +#define COND_SHIFT 28 +#define COND_EQ (0x0 << COND_SHIFT) +#define COND_NE (0x1 << COND_SHIFT) +#define COND_CS (0x2 << COND_SHIFT) +#define COND_CC (0x3 << COND_SHIFT) +#define COND_MI (0x4 << COND_SHIFT) +#define COND_PL (0x5 << COND_SHIFT) +#define COND_VS (0x6 << COND_SHIFT) +#define COND_VC (0x7 << COND_SHIFT) +#define COND_HI (0x8 << COND_SHIFT) +#define COND_LS (0x9 << COND_SHIFT) +#define COND_GE (0xa << COND_SHIFT) +#define COND_LT (0xb << COND_SHIFT) +#define COND_GT (0xc << COND_SHIFT) +#define COND_LE (0xd << COND_SHIFT) +#define COND_AL (0xe << COND_SHIFT) + void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); #define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0) void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); @@ -77,8 +94,15 @@ void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift); -void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); -void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm); +void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift); + +#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm) +#define host_arm_ORR_REG_LSL(block, dst_reg, src_reg_a, src_reg_b, shift) host_arm_ORR_REG_LSL_cond(block, COND_AL, dst_reg, src_reg_a, src_reg_b, shift) + +#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm) +#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) +#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); @@ -116,6 +140,7 @@ void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m); void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); @@ -129,6 +154,7 @@ void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high); void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 5b00a61..08ae666 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -689,6 +689,25 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + host_arm_VCMP_D(block, src_reg_a, src_reg_b); + host_arm_MOV_IMM(block, dest_reg, 0); + host_arm_VMRS_APSR(block); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0|C2|C3); + } + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} static int codegen_FDIV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1938,6 +1957,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FCOM & UOP_MASK] = codegen_FCOM, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index bfa71d1..c3f1b90 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -341,6 +341,11 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); +} + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ @@ -497,6 +502,11 @@ uint32_t *host_x86_JZ_long(codeblock_t *block) return (uint32_t *)&block->data[block_pos-4]; } +void host_x86_LAHF(codeblock_t *block) +{ + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + void host_x86_LDMXCSR(codeblock_t *block, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 5c9e298..ee7a82e 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -27,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -61,6 +63,8 @@ uint32_t *host_x86_JO_long(codeblock_t *block); uint32_t *host_x86_JS_long(codeblock_t *block); uint32_t *host_x86_JZ_long(codeblock_t *block); +void host_x86_LAHF(codeblock_t *block); + void host_x86_LDMXCSR(codeblock_t *block, void *p); void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 5c54d8a..4fd1768 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "x86.h" +#include "x87.h" #include "386_common.h" #include "codegen.h" #include "codegen_backend.h" @@ -542,6 +543,30 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + if (dest_reg != REG_EAX) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); + } + } + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} static int codegen_FDIV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1617,6 +1642,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, + [UOP_FCOM & UOP_MASK] = codegen_FCOM, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index d68f203..0dace79 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -309,6 +309,11 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); +} + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ @@ -462,6 +467,11 @@ uint32_t *host_x86_JZ_long(codeblock_t *block) return (uint32_t *)&block->data[block_pos-4]; } +void host_x86_LAHF(codeblock_t *block) +{ + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + void host_x86_LDMXCSR(codeblock_t *block, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 943ba40..96ace96 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -27,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -63,6 +65,8 @@ uint32_t *host_x86_JO_long(codeblock_t *block); uint32_t *host_x86_JS_long(codeblock_t *block); uint32_t *host_x86_JZ_long(codeblock_t *block); +void host_x86_LAHF(codeblock_t *block); + void host_x86_LDMXCSR(codeblock_t *block, void *p); void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 8537c3d..9ef533e 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "x86.h" +#include "x87.h" #include "386_common.h" #include "codegen.h" #include "codegen_backend.h" @@ -553,6 +554,30 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) + { + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + if (dest_reg != REG_EAX) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); + } + } + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} static int codegen_FDIV(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1622,7 +1647,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB + [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FCOM & UOP_MASK] = codegen_FCOM }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index d893067..998017b 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -177,8 +177,10 @@ #define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83) /*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/ #define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) +/*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/ +#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) -#define UOP_MAX 0x85 +#define UOP_MAX 0x86 #define UOP_MASK 0xffff @@ -481,6 +483,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) #define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b) #define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b) #define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) #define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index a36bd40..347a32e 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -115,44 +115,44 @@ RecompOpFn recomp_opcodes_d8[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, /*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, /*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, /*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, /*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, /*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, /*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, /*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, /*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, /*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, }; @@ -209,44 +209,44 @@ RecompOpFn recomp_opcodes_da[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, /*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, /*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, /*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, /*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, /*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, /*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, /*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, /*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, /*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, /*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, /*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, /*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, /*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, /*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, /*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, /*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -303,44 +303,44 @@ RecompOpFn recomp_opcodes_dc[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, /*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, /*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, /*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, /*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, /*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, /*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, /*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, }; @@ -366,7 +366,7 @@ RecompOpFn recomp_opcodes_dd[512] = /*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ @@ -388,7 +388,7 @@ RecompOpFn recomp_opcodes_dd[512] = /*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -397,44 +397,44 @@ RecompOpFn recomp_opcodes_de[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, /*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, /*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, /*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, /*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, /*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, /*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, /*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, /*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, -/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, /*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, /*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, -/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, /*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, /*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, }; diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c index ae62746..d903959 100644 --- a/src/codegen_ops_fpu_arith.c +++ b/src/codegen_ops_fpu_arith.c @@ -43,6 +43,41 @@ uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return op_pc; } +uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + + return op_pc; +} +uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(ir); + + return op_pc; +} +uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(ir); + fpu_POP(ir); + + return op_pc; +} + uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = fetchdat & 7; @@ -201,6 +236,41 @@ uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f return op_pc; } +uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + + return op_pc; +} +uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = fetchdat & 7; + + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(ir); + + return op_pc; +} +uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(ir); + fpu_POP(ir); + + return op_pc; +} + #define ropF_arith_mem(name, load_uop) \ uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ @@ -217,6 +287,39 @@ uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint \ return op_pc+1; \ } \ +uint32_t ropFCOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(ir); \ + \ + return op_pc+1; \ +} \ uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ @@ -313,6 +416,41 @@ uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uin \ return op_pc+1; \ } \ +uint32_t ropFICOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc+1; \ +} \ +uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(ir); \ + \ + return op_pc+1; \ +} \ uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ x86seg *target_seg; \ diff --git a/src/codegen_ops_fpu_arith.h b/src/codegen_ops_fpu_arith.h index 2cbafb7..e61d4ae 100644 --- a/src/codegen_ops_fpu_arith.h +++ b/src/codegen_ops_fpu_arith.h @@ -1,6 +1,9 @@ uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); @@ -16,9 +19,16 @@ uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFADDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFADDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOMs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOMd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOMPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCOMPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFDIVRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); @@ -32,6 +42,10 @@ uint32_t ropFSUBRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uint32_t ropFIADDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFIADDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFICOMl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFICOMw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFICOMPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFICOMPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFIDIVl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFIDIVw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFIDIVRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/x87.h b/src/x87.h index 3960efa..2ec4405 100644 --- a/src/x87.h +++ b/src/x87.h @@ -1,3 +1,8 @@ +#define C0 (1<<8) +#define C1 (1<<9) +#define C2 (1<<10) +#define C3 (1<<14) + uint32_t x87_pc_off,x87_op_off; uint16_t x87_pc_seg,x87_op_seg; diff --git a/src/x87_ops.h b/src/x87_ops.h index b1cc843..1208854 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -7,11 +7,6 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ #define ST(x) cpu_state.ST[((cpu_state.TOP+(x))&7)] -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) - #define STATUS_ZERODIVIDE 4 #define x87_div(dst, src1, src2) do \ From 964b20e8202287b34e174ca1f588a01afa68c279 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 14 Nov 2018 21:43:22 +0000 Subject: [PATCH 050/181] Added recompiled versions of FLD1 and FLDZ. --- src/codegen_ops.c | 4 ++-- src/codegen_ops_fpu_constant.c | 33 +++++++++++++++++++++++++++++++++ src/codegen_ops_fpu_constant.h | 2 ++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/codegen_ops_fpu_constant.c create mode 100644 src/codegen_ops_fpu_constant.h diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 347a32e..a2d6fb1 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -178,7 +178,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ @@ -200,7 +200,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/src/codegen_ops_fpu_constant.c b/src/codegen_ops_fpu_constant.c new file mode 100644 index 0000000..187850c --- /dev/null +++ b/src/codegen_ops_fpu_constant.c @@ -0,0 +1,33 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "x87.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_fpu_constant.h" +#include "codegen_ops_helpers.h" + +uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_temp0, 1); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(ir); + + return op_pc; +} +uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_temp0, 0); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(ir); + + return op_pc; +} diff --git a/src/codegen_ops_fpu_constant.h b/src/codegen_ops_fpu_constant.h new file mode 100644 index 0000000..29384b5 --- /dev/null +++ b/src/codegen_ops_fpu_constant.h @@ -0,0 +1,2 @@ +uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From fa4ccece48e4951abd001fbb0ab162d8b97d9175 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 20 Nov 2018 09:40:54 +0000 Subject: [PATCH 051/181] Fixed pixel clock on S3 ViRGE. --- src/vid_s3_virge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c index 7f2b72e..a7059e0 100644 --- a/src/vid_s3_virge.c +++ b/src/vid_s3_virge.c @@ -643,7 +643,7 @@ static void s3_virge_recalctimings(svga_t *svga) int m = svga->seqregs[0x13] & 0x7f; double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0; - svga->clock = cpuclock / freq; + svga->clock = (cpuclock * (float)(1ull << 32)) / freq; } } From f545d9d57f681c5d6606378eef0b36935a478382 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 21 Nov 2018 12:44:47 +0000 Subject: [PATCH 052/181] Rename FPU stack-based integer mirror registers, to avoid confusion with non-stack-based MMX registers. --- src/codegen_ops_fpu_loadstore.c | 6 +++--- src/codegen_ops_fpu_misc.c | 12 ++++++------ src/codegen_reg.c | 16 ++++++++-------- src/codegen_reg.h | 20 ++++++++++---------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c index 8be00d2..04ee62a 100644 --- a/src/codegen_ops_fpu_loadstore.c +++ b/src/codegen_ops_fpu_loadstore.c @@ -141,8 +141,8 @@ uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe op_pc--; target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_MM(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_MM(-1)); + uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1)); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); fpu_PUSH(ir); @@ -220,7 +220,7 @@ uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f op_pc--; target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_MM(0), IREG_tag(0)); + uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); fpu_POP(ir); diff --git a/src/codegen_ops_fpu_misc.c b/src/codegen_ops_fpu_misc.c index 2509cc7..18d6f88 100644 --- a/src/codegen_ops_fpu_misc.c +++ b/src/codegen_ops_fpu_misc.c @@ -27,7 +27,7 @@ uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc uop_FP_ENTER(ir); uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); - uop_MOV(ir, IREG_MM(-1), IREG_MM(src_reg)); + uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg)); uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); fpu_PUSH(ir); @@ -40,7 +40,7 @@ uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc uop_FP_ENTER(ir); uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(0)); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); return op_pc; @@ -51,7 +51,7 @@ uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_FP_ENTER(ir); uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(0)); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); fpu_POP(ir); @@ -98,13 +98,13 @@ uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_FP_ENTER(ir); uop_MOV(ir, IREG_temp0_D, IREG_ST(0)); - uop_MOV(ir, IREG_temp1_Q, IREG_MM(0)); + uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0)); uop_MOV(ir, IREG_temp2, IREG_tag(0)); uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV(ir, IREG_MM(0), IREG_MM(dest_reg)); + uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg)); uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg)); uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D); - uop_MOV(ir, IREG_MM(dest_reg), IREG_temp1_Q); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q); uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2); return op_pc; diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 2e76874..6e51f7d 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -114,14 +114,14 @@ struct [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_MM0] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM1] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM2] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM3] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM4] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM5] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM6] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM7] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER}, [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 3bb69b2..4568382 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -95,14 +95,14 @@ enum IREG_tag6 = 54, IREG_tag7 = 55, - IREG_MM0 = 56, - IREG_MM1 = 57, - IREG_MM2 = 58, - IREG_MM3 = 59, - IREG_MM4 = 60, - IREG_MM5 = 61, - IREG_MM6 = 62, - IREG_MM7 = 63, + IREG_ST0_i64 = 56, + IREG_ST1_i64 = 57, + IREG_ST2_i64 = 58, + IREG_ST3_i64 = 59, + IREG_ST4_i64 = 60, + IREG_ST5_i64 = 61, + IREG_ST6_i64 = 62, + IREG_ST7_i64 = 63, IREG_NPXCx = 64, IREG_NPXSx = 65, @@ -168,8 +168,8 @@ enum #define IREG_16(reg) ((reg) + IREG_AX) #define IREG_32(reg) ((reg) + IREG_EAX) -#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) -#define IREG_MM(r) (IREG_MM0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) +#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) +#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) #define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) #define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) From 76115568f2282d7db9aff21341f380b236481ace Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 21 Nov 2018 17:02:20 +0000 Subject: [PATCH 053/181] Added recompiled versions of MOVD and MOVQ. --- src/codegen_backend_arm64_uops.c | 37 ++++++++++- src/codegen_backend_arm_uops.c | 39 ++++++++++- src/codegen_backend_x86-64_uops.c | 42 +++++++++++- src/codegen_backend_x86_uops.c | 33 +++++++++- src/codegen_ir_defs.h | 11 +++- src/codegen_ops.c | 9 +-- src/codegen_ops_mmx_loadstore.c | 106 ++++++++++++++++++++++++++++++ src/codegen_ops_mmx_loadstore.h | 5 ++ src/codegen_reg.c | 27 ++++++++ src/codegen_reg.h | 26 +++++++- 10 files changed, 320 insertions(+), 15 deletions(-) create mode 100644 src/codegen_ops_mmx_loadstore.c create mode 100644 src/codegen_ops_mmx_loadstore.h diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 1d8aec5..5464148 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -699,6 +699,32 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); + + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); + + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); + + host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); + host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); + + return 0; +} static int codegen_JMP(codeblock_t *block, uop_t *uop) { @@ -1162,7 +1188,15 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_arm64_FMOV_D_Q(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_arm64_FMOV_W_S(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); } @@ -1836,6 +1870,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FCOM & UOP_MASK] = codegen_FCOM, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 08ae666..1f132de 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -772,6 +772,33 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + + *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + + host_arm_MOV_IMM(block, REG_TEMP, 0); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); + host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); + + return 0; +} static int codegen_JMP(codeblock_t *block, uop_t *uop) { @@ -1238,7 +1265,16 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_IMM(block, REG_TEMP, 0); + host_arm_VMOV_D_64(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_arm_VMOV_32_S(block, dest_reg, src_reg, REG_TEMP); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { host_arm_UXTB(block, dest_reg, src_reg, 0); } @@ -1955,6 +1991,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FCOM & UOP_MASK] = codegen_FCOM, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 4fd1768..d27edae 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -641,6 +641,29 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint8_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_short(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +#if WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +#else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +#endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; +} static int codegen_JMP(codeblock_t *block, uop_t *uop) { @@ -1076,7 +1099,15 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); } @@ -1640,6 +1671,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FCOM & UOP_MASK] = codegen_FCOM, @@ -1757,6 +1789,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); @@ -1766,6 +1802,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos { host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 9ef533e..a61592a 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -649,6 +649,26 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint8_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_short(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; +} + static int codegen_JMP(codeblock_t *block, uop_t *uop) { host_x86_JMP(block, uop->p); @@ -1073,7 +1093,15 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) + { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) + { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } + else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); } @@ -1642,7 +1670,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, + [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, [UOP_FADD & UOP_MASK] = codegen_FADD, [UOP_FDIV & UOP_MASK] = codegen_FDIV, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 998017b..5c5d290 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -167,7 +167,7 @@ /*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/ #define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) -/*UOP_FP_ENTER - */ +/*UOP_FP_ENTER - must be called before any FPU register accessed*/ #define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) /*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/ #define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) @@ -180,7 +180,10 @@ /*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/ #define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) -#define UOP_MAX 0x86 +/*UOP_MMX_ENTER - must be called before any MMX registers accessed*/ +#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) + +#define UOP_MAX 0x91 #define UOP_MASK 0xffff @@ -488,7 +491,8 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) #define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; } while (0) +#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0) +#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0) #define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) #define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) @@ -549,6 +553,7 @@ void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_of void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_set_jump_dest(codeblock_t *block, void *p); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index a2d6fb1..28dc422 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -11,6 +11,7 @@ #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" +#include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" @@ -74,8 +75,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -96,8 +97,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c new file mode 100644 index 0000000..e0ea5f7 --- /dev/null +++ b/src/codegen_ops_mmx_loadstore.c @@ -0,0 +1,106 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_loadstore.h" +#include "codegen_ops_helpers.h" + +uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); + } + + return op_pc + 1; + +} +uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } + + return op_pc + 1; +} + +uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; + +} + +uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); + } + + return op_pc + 1; +} diff --git a/src/codegen_ops_mmx_loadstore.h b/src/codegen_ops_mmx_loadstore.h new file mode 100644 index 0000000..4b473ad --- /dev/null +++ b/src/codegen_ops_mmx_loadstore.h @@ -0,0 +1,5 @@ +uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 6e51f7d..3e801a9 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -123,6 +123,15 @@ struct [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP}, + [IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP}, + [IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP}, + [IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP}, + [IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP}, + [IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP}, + [IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP}, + [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER}, [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, @@ -204,6 +213,15 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, else codegen_direct_read_32(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; + + case REG_QWORD: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_QWORD !REG_FP\n"); + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_64_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_64(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; case REG_DOUBLE: if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) @@ -282,6 +300,15 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i codegen_direct_write_32(block, p, reg_set->reg_list[c]); break; + case REG_QWORD: + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n"); + if ((uintptr_t)p < 256) + codegen_direct_write_64_stack(block, (int)p, reg_set->reg_list[c]); + else + codegen_direct_write_64(block, p, reg_set->reg_list[c]); + break; + case REG_POINTER: if (ireg_data[ir_reg].type != REG_INTEGER) fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 4568382..8474ef9 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -104,10 +104,19 @@ enum IREG_ST6_i64 = 62, IREG_ST7_i64 = 63, - IREG_NPXCx = 64, - IREG_NPXSx = 65, + IREG_MM0x = 64, + IREG_MM1x = 65, + IREG_MM2x = 66, + IREG_MM3x = 67, + IREG_MM4x = 68, + IREG_MM5x = 69, + IREG_MM6x = 70, + IREG_MM7x = 71, + + IREG_NPXCx = 72, + IREG_NPXSx = 73, - IREG_COUNT = 66, + IREG_COUNT = 74, IREG_INVALID = 255, @@ -160,6 +169,15 @@ enum IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, + IREG_MM0 = IREG_MM0x + IREG_SIZE_Q, + IREG_MM1 = IREG_MM1x + IREG_SIZE_Q, + IREG_MM2 = IREG_MM2x + IREG_SIZE_Q, + IREG_MM3 = IREG_MM3x + IREG_SIZE_Q, + IREG_MM4 = IREG_MM4x + IREG_SIZE_Q, + IREG_MM5 = IREG_MM5x + IREG_SIZE_Q, + IREG_MM6 = IREG_MM6x + IREG_SIZE_Q, + IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, + IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, IREG_NPXS = IREG_NPXSx + IREG_SIZE_W }; @@ -173,6 +191,8 @@ enum #define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) #define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) +#define IREG_MM(reg) ((reg) + IREG_MM0) + #define IREG_TOP_diff_stack_offset 32 static inline int ireg_seg_base(x86seg *seg) From 78c604c73136420ea179f8377915414731d1108f Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 21 Nov 2018 20:51:34 +0000 Subject: [PATCH 054/181] Added recompiled versions of PAND, PANDN, POR and PXOR --- src/codegen_backend_arm64_ops.c | 23 ++++++- src/codegen_backend_arm64_ops.h | 7 +- src/codegen_backend_arm64_uops.c | 34 +++++++++- src/codegen_backend_arm_ops.c | 22 +++++- src/codegen_backend_arm_ops.h | 4 ++ src/codegen_backend_arm_uops.c | 33 ++++++++- src/codegen_backend_x86-64_ops.c | 17 +++++ src/codegen_backend_x86-64_ops.h | 5 ++ src/codegen_backend_x86-64_uops.c | 34 +++++++++- src/codegen_backend_x86_ops.c | 17 +++++ src/codegen_backend_x86_ops.h | 5 ++ src/codegen_backend_x86_uops.c | 36 ++++++++-- src/codegen_ir_defs.h | 23 ++++--- src/codegen_ops.c | 9 +-- src/codegen_ops_mmx_logic.c | 108 ++++++++++++++++++++++++++++++ src/codegen_ops_mmx_logic.h | 4 ++ 16 files changed, 351 insertions(+), 30 deletions(-) create mode 100644 src/codegen_ops_mmx_logic.c create mode 100644 src/codegen_ops_mmx_logic.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 724ea8b..d4e975c 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -104,9 +104,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SUB_LSR (0x25a << 21) #define OPCODE_SUBX_LSL (0x658 << 21) +#define OPCODE_AND_V (0x0e201c00) #define OPCODE_ASR (0x1ac02800) +#define OPCODE_BIC_V (0x0e601c00) #define OPCODE_BLR (0xd63f0000) #define OPCODE_BR (0xd61f0000) +#define OPCODE_EOR_V (0x2e201c00) #define OPCODE_FADD_D (0x1e602800) #define OPCODE_FCMP_D (0x1e602000) #define OPCODE_FCVT_D_S (0x1e22c000) @@ -140,6 +143,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LSR (0x1ac02400) #define OPCODE_MSR_FPCR (0xd51b4400) #define OPCODE_NOP (0xd503201f) +#define OPCODE_ORR_V (0x0ea01c00) #define OPCODE_RET (0xd65f0000) #define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) @@ -319,6 +323,10 @@ void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_AND_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { @@ -461,6 +469,11 @@ void host_arm64_BEQ(codeblock_t *block, void *dest) host_arm64_branch_set_offset(opcode, dest); } +void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_BIC_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) { int offset = dest - (uintptr_t)&block->data[block_pos]; @@ -557,6 +570,10 @@ void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_EOR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { @@ -840,6 +857,10 @@ void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_ { codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ORR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_RET(codeblock_t *block, int reg) { @@ -995,4 +1016,4 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) } } -#endif \ No newline at end of file +#endif diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index ccccae6..724f939 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -8,6 +8,7 @@ void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); @@ -40,6 +41,8 @@ void host_arm64_branch_set_offset(uint32_t *opcode, void *dest); void host_arm64_BR(codeblock_t *block, int addr_reg); +void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); @@ -57,6 +60,7 @@ void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_ void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg); @@ -124,6 +128,7 @@ void host_arm64_NOP(codeblock_t *block); void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_RET(codeblock_t *block, int reg); @@ -173,4 +178,4 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); -int add_literal_q(codeblock_t *block, uint64_t data); \ No newline at end of file +int add_literal_q(codeblock_t *block, uint64_t data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 5464148..baa12fb 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -105,7 +105,11 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_AND_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_arm64_AND_REG(block, dest_reg, src_reg_a, src_reg_b, 0); } @@ -200,6 +204,21 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ANDN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_BIC_REG_V(block, dest_reg, src_reg_b, src_reg_a); + } + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { host_arm64_call(block, uop->p); @@ -1300,7 +1319,11 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_ORR_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); } @@ -1723,7 +1746,11 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_EOR_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_arm64_EOR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); } @@ -1834,6 +1861,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, [UOP_AND & UOP_MASK] = codegen_AND, [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_ANDN & UOP_MASK] = codegen_ANDN, [UOP_OR & UOP_MASK] = codegen_OR, [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, [UOP_SUB & UOP_MASK] = codegen_SUB, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 85d3646..4e34980 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -87,6 +87,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 #define OPCODE_VADD 0xee300b00 +#define OPCODE_VAND_D 0xf2000110 +#define OPCODE_VBIC_D 0xf2100110 #define OPCODE_VCMP_D 0xeeb40b40 #define OPCODE_VCVT_D_IS 0xeeb80bc0 #define OPCODE_VCVT_D_S 0xeeb70ac0 @@ -94,6 +96,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VCVT_S_D 0xeeb70bc0 #define OPCODE_VCVTR_IS_D 0xeebd0b40 #define OPCODE_VDIV 0xee800b00 +#define OPCODE_VEOR_D 0xf3000110 #define OPCODE_VLDR_D 0xed900b00 #define OPCODE_VLDR_S 0xed900a00 #define OPCODE_VMOV_32_S 0xee100a10 @@ -104,6 +107,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMRS_APSR 0xeef1fa10 #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 +#define OPCODE_VORR_D 0xf2200110 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 @@ -750,6 +754,14 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VAND_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VBIC_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); @@ -778,6 +790,10 @@ void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) @@ -822,6 +838,10 @@ void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) @@ -839,4 +859,4 @@ void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -#endif \ No newline at end of file +#endif diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 1fdd609..9530e72 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -140,6 +140,8 @@ void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m); void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); @@ -147,6 +149,7 @@ void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg); @@ -157,6 +160,7 @@ void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 1f132de..c5f8b0a 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -169,7 +169,11 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VAND_D(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_arm_AND_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); } @@ -273,6 +277,20 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ANDN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VBIC_D(block, dest_reg, src_reg_b, src_reg_a); + } + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { @@ -1421,7 +1439,11 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VORR_D(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); } @@ -1844,7 +1866,11 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VEOR_D(block, dest_reg, src_reg_a, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); } @@ -1955,6 +1981,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, [UOP_AND & UOP_MASK] = codegen_AND, [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_ANDN & UOP_MASK] = codegen_ANDN, [UOP_OR & UOP_MASK] = codegen_OR, [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, [UOP_SUB & UOP_MASK] = codegen_SUB, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index c3f1b90..736c8b2 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1229,6 +1229,23 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index ee7a82e..d05ecb6 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -153,6 +153,11 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index d27edae..1c8e8bc 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -101,7 +101,11 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); @@ -154,6 +158,21 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ANDN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); @@ -1203,7 +1222,11 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); @@ -1545,7 +1568,11 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_x86_XOR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } @@ -1634,6 +1661,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, [UOP_AND & UOP_MASK] = codegen_AND, + [UOP_ANDN & UOP_MASK] = codegen_ANDN, [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, [UOP_OR & UOP_MASK] = codegen_OR, [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 0dace79..ca24075 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1087,6 +1087,23 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ } } +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + void host_x86_POP(codeblock_t *block, int src_reg) { codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 96ace96..0f0b469 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -154,6 +154,11 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index a61592a..84ec52f 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -111,7 +111,11 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); @@ -164,6 +168,21 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ANDN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); @@ -1206,7 +1225,11 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); @@ -1544,7 +1567,11 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { host_x86_XOR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } @@ -1557,7 +1584,7 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); return 0; } @@ -1635,6 +1662,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, [UOP_AND & UOP_MASK] = codegen_AND, [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, + [UOP_ANDN & UOP_MASK] = codegen_ANDN, [UOP_OR & UOP_MASK] = codegen_OR, [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, [UOP_SUB & UOP_MASK] = codegen_SUB, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 5c5d290..e2cd008 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -93,6 +93,8 @@ #define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) /*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/ #define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) +/*UOP_ANDN - dest_reg = ~src_reg_a & src_reg_b*/ +#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b) /*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/ #define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/ @@ -444,17 +446,18 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) -#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) +#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) #define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift) -#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) -#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) -#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) +#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) +#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) +#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) #define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg) #define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 28dc422..6531dfc 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -12,6 +12,7 @@ #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" #include "codegen_ops_mmx_loadstore.h" +#include "codegen_ops_mmx_logic.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" @@ -84,8 +85,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPAND, NULL, NULL, NULL, ropPANDN, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPOR, NULL, NULL, NULL, ropPXOR, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ @@ -106,8 +107,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPAND, NULL, NULL, NULL, ropPANDN, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPOR, NULL, NULL, NULL, ropPXOR, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/src/codegen_ops_mmx_logic.c b/src/codegen_ops_mmx_logic.c new file mode 100644 index 0000000..428a591 --- /dev/null +++ b/src/codegen_ops_mmx_logic.c @@ -0,0 +1,108 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_logic.h" +#include "codegen_ops_helpers.h" + +uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 1; + +} +uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 1; + +} +uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 1; + +} +uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 1; + +} diff --git a/src/codegen_ops_mmx_logic.h b/src/codegen_ops_mmx_logic.h new file mode 100644 index 0000000..f8f3009 --- /dev/null +++ b/src/codegen_ops_mmx_logic.h @@ -0,0 +1,4 @@ +uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 35b9e0811bca2933b736a2c0a86a293a8ae6fc12 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 22 Nov 2018 15:57:44 +0000 Subject: [PATCH 055/181] Added recompiled versions of PADD* and PSUB*. --- src/codegen_backend_arm64_ops.c | 71 ++++++++++ src/codegen_backend_arm64_ops.h | 16 +++ src/codegen_backend_arm64_uops.c | 219 +++++++++++++++++++++++++++++- src/codegen_backend_arm_ops.c | 70 ++++++++++ src/codegen_backend_arm_ops.h | 14 ++ src/codegen_backend_arm_uops.c | 219 +++++++++++++++++++++++++++++- src/codegen_backend_x86-64_ops.c | 56 ++++++++ src/codegen_backend_x86-64_ops.h | 14 ++ src/codegen_backend_x86-64_uops.c | 216 ++++++++++++++++++++++++++++- src/codegen_backend_x86_ops.c | 56 ++++++++ src/codegen_backend_x86_ops.h | 14 ++ src/codegen_backend_x86_uops.c | 216 ++++++++++++++++++++++++++++- src/codegen_ir_defs.h | 46 ++++++- src/codegen_ops.c | 13 +- src/codegen_ops_mmx_arith.c | 52 +++++++ src/codegen_ops_mmx_arith.h | 15 ++ 16 files changed, 1296 insertions(+), 11 deletions(-) create mode 100644 src/codegen_ops_mmx_arith.c create mode 100644 src/codegen_ops_mmx_arith.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index d4e975c..8a372f0 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -104,6 +104,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SUB_LSR (0x25a << 21) #define OPCODE_SUBX_LSL (0x658 << 21) +#define OPCODE_ADD_V8B (0x0e208400) +#define OPCODE_ADD_V4H (0x0e608400) +#define OPCODE_ADD_V2S (0x0ea08400) #define OPCODE_AND_V (0x0e201c00) #define OPCODE_ASR (0x1ac02800) #define OPCODE_BIC_V (0x0e601c00) @@ -147,12 +150,23 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_RET (0xd65f0000) #define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) +#define OPCODE_SQADD_V8B (0x0e200c00) +#define OPCODE_SQADD_V4H (0x0e600c00) +#define OPCODE_SQSUB_V8B (0x0e202c00) +#define OPCODE_SQSUB_V4H (0x0e602c00) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) #define OPCODE_STRH_REG (0x78206800) #define OPCODE_STR_REG_F32 (0xbc206800) #define OPCODE_STR_REG_F64 (0xfc206800) #define OPCODE_STR_REG_F64_S (0xfc207800) +#define OPCODE_SUB_V8B (0x2e208400) +#define OPCODE_SUB_V4H (0x2e608400) +#define OPCODE_SUB_V2S (0x2ea08400) +#define OPCODE_UQADD_V8B (0x2e200c00) +#define OPCODE_UQADD_V4H (0x2e600c00) +#define OPCODE_UQSUB_V8B (0x2e202c00) +#define OPCODE_UQSUB_V4H (0x2e602c00) #define DATPROC_SHIFT(sh) (sh << 10) #define DATPROC_IMM_SHIFT(sh) (sh << 22) @@ -277,6 +291,18 @@ void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) { @@ -881,6 +907,23 @@ void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} + void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { if (!in_range7_x(offset)) @@ -978,6 +1021,18 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) { @@ -990,6 +1045,22 @@ void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); } +void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} +void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} void host_arm64_call(codeblock_t *block, void *dst_addr) { diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 724f939..a1a1910 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -1,6 +1,9 @@ void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset); @@ -137,6 +140,11 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -157,6 +165,9 @@ void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offs void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit); @@ -164,6 +175,11 @@ uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit); void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); +void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index baa12fb..ae5dc5a 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1384,6 +1384,207 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_ADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_ADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_ADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_UQADD_V8H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_UQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_UQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_UQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -1904,7 +2105,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FCOM & UOP_MASK] = codegen_FCOM, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB + [UOP_FSUB & UOP_MASK] = codegen_FSUB, + + [UOP_PADDB & UOP_MASK] = codegen_PADDB, + [UOP_PADDW & UOP_MASK] = codegen_PADDW, + [UOP_PADDD & UOP_MASK] = codegen_PADDD, + [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, + [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, + [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, + [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, + [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, + [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, + [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, + [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, + [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 4e34980..2818e55 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -87,6 +87,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 #define OPCODE_VADD 0xee300b00 +#define OPCODE_VADD_I8 0xf2000800 +#define OPCODE_VADD_I16 0xf2100800 +#define OPCODE_VADD_I32 0xf2200800 #define OPCODE_VAND_D 0xf2000110 #define OPCODE_VBIC_D 0xf2100110 #define OPCODE_VCMP_D 0xeeb40b40 @@ -108,9 +111,20 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 #define OPCODE_VORR_D 0xf2200110 +#define OPCODE_VQADD_S8 0xf2000010 +#define OPCODE_VQADD_S16 0xf2100010 +#define OPCODE_VQADD_U8 0xf3000010 +#define OPCODE_VQADD_U16 0xf3100010 +#define OPCODE_VQSUB_S8 0xf2000210 +#define OPCODE_VQSUB_S16 0xf2100210 +#define OPCODE_VQSUB_U8 0xf3000210 +#define OPCODE_VQSUB_U16 0xf3100210 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 +#define OPCODE_VSUB_I8 0xf3000800 +#define OPCODE_VSUB_I16 0xf3100800 +#define OPCODE_VSUB_I32 0xf3200800 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -754,6 +768,18 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VADD_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VADD_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VAND_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -842,6 +868,38 @@ void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQADD_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQADD_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQADD_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQSUB_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQSUB_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQSUB_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) @@ -858,5 +916,17 @@ void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VSUB_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VSUB_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} #endif diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 9530e72..166656c 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -140,6 +140,9 @@ void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m); @@ -161,6 +164,17 @@ void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index c5f8b0a..329459e 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1504,6 +1504,207 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VADD_I8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VADD_I16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VADD_I32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQADD_S8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQADD_S16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQADD_U8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQADD_U16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VSUB_I8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VSUB_I16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VSUB_I32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQSUB_S8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQSUB_S16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQSUB_U8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQSUB_U16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2024,7 +2225,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FCOM & UOP_MASK] = codegen_FCOM, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB + [UOP_FSUB & UOP_MASK] = codegen_FSUB, + + [UOP_PADDB & UOP_MASK] = codegen_PADDB, + [UOP_PADDW & UOP_MASK] = codegen_PADDW, + [UOP_PADDD & UOP_MASK] = codegen_PADDD, + [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, + [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, + [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, + [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, + [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, + [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, + [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, + [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, + [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 736c8b2..efc7e3d 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1229,6 +1229,34 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ +} void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ @@ -1241,6 +1269,34 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ +} void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index d05ecb6..5f16760 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -153,9 +153,23 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POP(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 1c8e8bc..0eddc13 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1270,6 +1270,204 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -1705,7 +1903,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FCOM & UOP_MASK] = codegen_FCOM, [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB + [UOP_FSUB & UOP_MASK] = codegen_FSUB, + + [UOP_PADDB & UOP_MASK] = codegen_PADDB, + [UOP_PADDW & UOP_MASK] = codegen_PADDW, + [UOP_PADDD & UOP_MASK] = codegen_PADDD, + [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, + [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, + [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, + [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, + [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, + [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, + [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, + [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, + [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index ca24075..2d4fb79 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1087,6 +1087,34 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ } } +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ +} void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ @@ -1099,6 +1127,34 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ +} void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 0f0b469..ca5f3ff 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -154,9 +154,23 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POP(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 84ec52f..d84c0c2 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1273,6 +1273,204 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -1705,7 +1903,23 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FDIV & UOP_MASK] = codegen_FDIV, [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, - [UOP_FCOM & UOP_MASK] = codegen_FCOM + [UOP_FCOM & UOP_MASK] = codegen_FCOM, + + [UOP_PADDB & UOP_MASK] = codegen_PADDB, + [UOP_PADDW & UOP_MASK] = codegen_PADDW, + [UOP_PADDD & UOP_MASK] = codegen_PADDD, + [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, + [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, + [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, + [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, + [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, + [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, + [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, + [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, + [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index e2cd008..7c7bb39 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -184,8 +184,36 @@ /*UOP_MMX_ENTER - must be called before any MMX registers accessed*/ #define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) +/*UOP_PADDB - (packed byte) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91) +/*UOP_PADDW - (packed word) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92) +/*UOP_PADDD - (packed long) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93) +/*UOP_PADDSB - (packed byte with signed saturation) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94) +/*UOP_PADDSW - (packed word with signed saturation) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95) +/*UOP_PADDUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96) +/*UOP_PADDUSW - (packed word with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97) +/*UOP_PSUBB - (packed byte) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98) +/*UOP_PSUBW - (packed word) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99) +/*UOP_PSUBD - (packed long) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a) +/*UOP_PSUBSB - (packed byte with signed saturation) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b) +/*UOP_PSUBSW - (packed word with signed saturation) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c) +/*UOP_PSUBUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) +/*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) -#define UOP_MAX 0x91 +#define UOP_MAX 0x9f #define UOP_MASK 0xffff @@ -525,6 +553,22 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/) #define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) +#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) + +#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b) + #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 6531dfc..4b17b81 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -11,6 +11,7 @@ #include "codegen_ops_jump.h" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" +#include "codegen_ops_mmx_arith.h" #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mmx_logic.h" #include "codegen_ops_mov.h" @@ -85,9 +86,9 @@ RecompOpFn recomp_opcodes_0f[512] = /*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPAND, NULL, NULL, NULL, ropPANDN, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPOR, NULL, NULL, NULL, ropPXOR, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -107,9 +108,9 @@ RecompOpFn recomp_opcodes_0f[512] = /*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPAND, NULL, NULL, NULL, ropPANDN, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPOR, NULL, NULL, NULL, ropPXOR, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, }; RecompOpFn recomp_opcodes_d8[512] = diff --git a/src/codegen_ops_mmx_arith.c b/src/codegen_ops_mmx_arith.c new file mode 100644 index 0000000..848c046 --- /dev/null +++ b/src/codegen_ops_mmx_arith.c @@ -0,0 +1,52 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_arith.h" +#include "codegen_ops_helpers.h" + +#define ropParith(func) \ +uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + int src_reg = fetchdat & 7; \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } \ + else \ + { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ +} + +ropParith(PADDB) +ropParith(PADDW) +ropParith(PADDD) +ropParith(PADDSB) +ropParith(PADDSW) +ropParith(PADDUSB) +ropParith(PADDUSW) + +ropParith(PSUBB) +ropParith(PSUBW) +ropParith(PSUBD) +ropParith(PSUBSB) +ropParith(PSUBSW) +ropParith(PSUBUSB) +ropParith(PSUBUSW) diff --git a/src/codegen_ops_mmx_arith.h b/src/codegen_ops_mmx_arith.h new file mode 100644 index 0000000..e848c8d --- /dev/null +++ b/src/codegen_ops_mmx_arith.h @@ -0,0 +1,15 @@ +uint32_t ropPADDB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPADDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPADDD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPADDSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPADDSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPADDUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPADDUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPSUBB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSUBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSUBD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSUBSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSUBSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSUBUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSUBUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From e43a2a6be04d2fa15f53742af44a4d8837c20182 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 22 Nov 2018 18:43:36 +0000 Subject: [PATCH 056/181] Added recompiled versions of PSLL*, PSLR* and PSAR* with immediate shifts. --- src/codegen_backend_arm64_ops.c | 105 ++++++++++++++----- src/codegen_backend_arm64_ops.h | 32 ++++-- src/codegen_backend_arm64_uops.c | 164 ++++++++++++++++++++++++++++++ src/codegen_backend_arm_ops.c | 67 ++++++++++++ src/codegen_backend_arm_ops.h | 11 ++ src/codegen_backend_arm_uops.c | 164 ++++++++++++++++++++++++++++++ src/codegen_backend_x86-64_ops.c | 49 +++++++++ src/codegen_backend_x86-64_ops.h | 13 +++ src/codegen_backend_x86-64_uops.c | 137 +++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 49 +++++++++ src/codegen_backend_x86_ops.h | 13 +++ src/codegen_backend_x86_uops.c | 137 +++++++++++++++++++++++++ src/codegen_ir_defs.h | 30 +++++- src/codegen_ops.c | 5 +- src/codegen_ops_mmx_shift.c | 87 ++++++++++++++++ src/codegen_ops_mmx_shift.h | 7 ++ 16 files changed, 1029 insertions(+), 41 deletions(-) create mode 100644 src/codegen_ops_mmx_shift.c create mode 100644 src/codegen_ops_mmx_shift.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 8a372f0..06d431e 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -154,6 +154,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SQADD_V4H (0x0e600c00) #define OPCODE_SQSUB_V8B (0x0e202c00) #define OPCODE_SQSUB_V4H (0x0e602c00) +#define OPCODE_SHL_VD (0x0e005400) +#define OPCODE_SHL_VQ (0x4e005400) +#define OPCODE_SSHR_VD (0x0e004400) +#define OPCODE_SSHR_VQ (0x4e004400) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) #define OPCODE_STRH_REG (0x78206800) @@ -167,6 +171,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UQADD_V4H (0x2e600c00) #define OPCODE_UQSUB_V8B (0x2e202c00) #define OPCODE_UQSUB_V4H (0x2e602c00) +#define OPCODE_USHR_VD (0x2e004400) +#define OPCODE_USHR_VQ (0x6e004400) #define DATPROC_SHIFT(sh) (sh << 10) #define DATPROC_IMM_SHIFT(sh) (sh << 22) @@ -191,6 +197,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OFFSET12_W(offset) ((offset >> 2) << 10) #define OFFSET12_Q(offset) ((offset >> 3) << 10) +#define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) +#define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) +#define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) + static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) { @@ -291,17 +301,17 @@ void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) @@ -907,21 +917,47 @@ void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); +} +void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); +} +void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); +} + +void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); +} +void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); +} +void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) @@ -1021,17 +1057,17 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) @@ -1045,21 +1081,34 @@ void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); } -void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); +} +void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); +} +void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } void host_arm64_call(codeblock_t *block, void *dst_addr) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index a1a1910..699988d 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -1,9 +1,9 @@ void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset); @@ -140,10 +140,18 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); -void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + +void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); + +void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); @@ -165,9 +173,9 @@ void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offs void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit); @@ -180,6 +188,10 @@ void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); + void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index ae5dc5a..f19d6b8 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1483,6 +1483,160 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); + else + host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); + else + host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); + else + host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2115,6 +2269,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 2818e55..17c29f9 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -119,6 +119,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VQSUB_S16 0xf2100210 #define OPCODE_VQSUB_U8 0xf3000210 #define OPCODE_VQSUB_U16 0xf3100210 +#define OPCODE_VSHL_D_IMM_16 0xf2900510 +#define OPCODE_VSHL_D_IMM_32 0xf2a00510 +#define OPCODE_VSHL_D_IMM_64 0xf2800590 +#define OPCODE_VSHR_D_S16 0xf2900010 +#define OPCODE_VSHR_D_S32 0xf2a00010 +#define OPCODE_VSHR_D_S64 0xf2800090 +#define OPCODE_VSHR_D_U16 0xf3900010 +#define OPCODE_VSHR_D_U32 0xf3a00010 +#define OPCODE_VSHR_D_U64 0xf3800090 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 @@ -157,6 +166,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define LDRH_IMM(imm) (((imm) & 0xf) | (((imm) & 0xf0) << 4)) #define STRH_IMM(imm) LDRH_IMM(imm) +#define VSHIFT_IMM(shift) ((shift) << 16) static inline uint32_t arm_data_offset(int offset) { @@ -868,6 +878,7 @@ void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } + void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -900,6 +911,62 @@ void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_ { codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } + +void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 15) + fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 31) + fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 63) + fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_SD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 15) + fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_SD_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_SD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 31) + fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_SD_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_SD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 63) + fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_SD_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_UD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 15) + fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_UD_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_UD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 31) + fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_UD_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_UD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 63) + fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_UD_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} + void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 166656c..5a1f792 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -172,6 +172,17 @@ void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_r void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); + +void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_S16(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_S32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_U16(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift); + void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 329459e..75d01b0 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1603,6 +1603,160 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); + else + host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); + else + host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); + else + host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2235,6 +2389,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index efc7e3d..97bab1f 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1257,6 +1257,7 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } + void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ @@ -1269,6 +1270,53 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ @@ -1297,6 +1345,7 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } + void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 5f16760..119f854 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -160,9 +160,21 @@ void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -170,6 +182,7 @@ void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POP(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 0eddc13..331a12f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1369,6 +1369,133 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1913,6 +2040,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 2d4fb79..1dbee0b 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1115,6 +1115,7 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } + void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ @@ -1127,6 +1128,53 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ @@ -1155,6 +1203,7 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } + void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index ca5f3ff..f7483c2 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -161,9 +161,21 @@ void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -171,6 +183,7 @@ void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POP(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index d84c0c2..7b5a8de 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1372,6 +1372,133 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1913,6 +2040,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 7c7bb39..1fdd3a8 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -212,8 +212,26 @@ #define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) /*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ #define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) +/*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/ +#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f) +/*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/ +#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0) +/*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/ +#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1) +/*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2) +/*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3) +/*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4) +/*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5) +/*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) +/*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) -#define UOP_MAX 0x9f +#define UOP_MAX 0xb0 #define UOP_MASK 0xffff @@ -561,6 +579,16 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm) + #define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 4b17b81..fa7f769 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -14,6 +14,7 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mmx_logic.h" +#include "codegen_ops_mmx_shift.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" @@ -78,7 +79,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -100,7 +101,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_mmx_shift.c b/src/codegen_ops_mmx_shift.c new file mode 100644 index 0000000..ad0f597 --- /dev/null +++ b/src/codegen_ops_mmx_shift.c @@ -0,0 +1,87 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_shift.h" +#include "codegen_ops_helpers.h" + +uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); + + uop_MMX_ENTER(ir); + switch (op) + { + case 0x10: /*PSRLW*/ + uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAW*/ + uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLW*/ + uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + + } + + return op_pc + 2; +} +uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); + + uop_MMX_ENTER(ir); + switch (op) + { + case 0x10: /*PSRLD*/ + uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAD*/ + uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLD*/ + uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + + } + + return op_pc + 2; +} +uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); + + uop_MMX_ENTER(ir); + switch (op) + { + case 0x10: /*PSRLQ*/ + uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAQ*/ + uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLQ*/ + uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + + } + + return op_pc + 2; +} diff --git a/src/codegen_ops_mmx_shift.h b/src/codegen_ops_mmx_shift.h new file mode 100644 index 0000000..3a3b712 --- /dev/null +++ b/src/codegen_ops_mmx_shift.h @@ -0,0 +1,7 @@ +uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPSLLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSLLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSLLQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From a991bc3249fd054b492334221d1483d7b4d46079 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 23 Nov 2018 15:17:21 +0000 Subject: [PATCH 057/181] Added recompiled versions of PCMP* --- src/codegen_backend_arm64_ops.c | 31 +++++++++++ src/codegen_backend_arm64_ops.h | 7 +++ src/codegen_backend_arm64_uops.c | 92 +++++++++++++++++++++++++++++++ src/codegen_backend_arm_ops.c | 32 +++++++++++ src/codegen_backend_arm_ops.h | 8 +++ src/codegen_backend_arm_uops.c | 92 +++++++++++++++++++++++++++++++ src/codegen_backend_x86-64_ops.c | 34 ++++++++++-- src/codegen_backend_x86-64_ops.h | 10 +++- src/codegen_backend_x86-64_uops.c | 92 +++++++++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 34 ++++++++++-- src/codegen_backend_x86_ops.h | 10 +++- src/codegen_backend_x86_uops.c | 92 +++++++++++++++++++++++++++++++ src/codegen_ir_defs.h | 19 +++++++ src/codegen_ops.c | 9 +-- src/codegen_ops_mmx_cmp.c | 43 +++++++++++++++ src/codegen_ops_mmx_cmp.h | 6 ++ 16 files changed, 593 insertions(+), 18 deletions(-) create mode 100644 src/codegen_ops_mmx_cmp.c create mode 100644 src/codegen_ops_mmx_cmp.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 06d431e..576b12f 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -112,6 +112,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BIC_V (0x0e601c00) #define OPCODE_BLR (0xd63f0000) #define OPCODE_BR (0xd61f0000) +#define OPCODE_CMEQ_V8B (0x2e208c00) +#define OPCODE_CMEQ_V4H (0x2e608c00) +#define OPCODE_CMEQ_V2S (0x2ea08c00) +#define OPCODE_CMGT_V8B (0x0e203400) +#define OPCODE_CMGT_V4H (0x0e603400) +#define OPCODE_CMGT_V2S (0x0ea03400) #define OPCODE_EOR_V (0x2e201c00) #define OPCODE_FADD_D (0x1e602800) #define OPCODE_FCMP_D (0x1e602000) @@ -518,6 +524,31 @@ void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); } +void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMEQ_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMEQ_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMGT_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMGT_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) { if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 699988d..4dba688 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -48,6 +48,13 @@ void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); +void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index f19d6b8..4600f21 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1483,6 +1483,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_CMEQ_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2269,6 +2354,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 17c29f9..b604f7e 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -92,6 +92,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VADD_I32 0xf2200800 #define OPCODE_VAND_D 0xf2000110 #define OPCODE_VBIC_D 0xf2100110 +#define OPCODE_VCEQ_I8 0xf3000810 +#define OPCODE_VCEQ_I16 0xf3100810 +#define OPCODE_VCEQ_I32 0xf3200810 +#define OPCODE_VCGT_S8 0xf2000300 +#define OPCODE_VCGT_S16 0xf2100300 +#define OPCODE_VCGT_S32 0xf2200300 #define OPCODE_VCMP_D 0xeeb40b40 #define OPCODE_VCVT_D_IS 0xeeb80bc0 #define OPCODE_VCVT_D_S 0xeeb70ac0 @@ -802,6 +808,32 @@ void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); } + +void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCEQ_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGT_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGT_S32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} + void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 5a1f792..6c7081a 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -146,6 +146,14 @@ void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m); + +void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); + void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 75d01b0..9f57130 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1603,6 +1603,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCEQ_I8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCEQ_I16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCEQ_I32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCGT_S8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCGT_S16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCGT_S32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2389,6 +2474,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 97bab1f..83a24fd 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1270,6 +1270,35 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { @@ -1346,11 +1375,6 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 119f854..ba2c0a5 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -164,6 +164,14 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); @@ -183,8 +191,6 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 331a12f..4bd8b0e 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1369,6 +1369,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -2040,6 +2125,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 1dbee0b..a3e63b7 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1128,6 +1128,35 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { @@ -1204,11 +1233,6 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - void host_x86_POP(codeblock_t *block, int src_reg) { codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index f7483c2..bf1e492 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -165,6 +165,14 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); @@ -184,8 +192,6 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 7b5a8de..e8b11b9 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1372,6 +1372,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -2040,6 +2125,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 1fdd3a8..694b585 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -230,6 +230,18 @@ #define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) /*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ #define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) +/*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8) +/*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9) +/*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa) +/*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab) +/*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) +/*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) #define UOP_MAX 0xb0 @@ -579,6 +591,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) + #define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) #define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) #define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index fa7f769..0ec4059 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -12,6 +12,7 @@ #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" #include "codegen_ops_mmx_arith.h" +#include "codegen_ops_mmx_cmp.h" #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mmx_logic.h" #include "codegen_ops_mmx_shift.h" @@ -78,8 +79,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*60*/ NULL, NULL, NULL, NULL, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -100,8 +101,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*60*/ NULL, NULL, NULL, NULL, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_mmx_cmp.c b/src/codegen_ops_mmx_cmp.c new file mode 100644 index 0000000..f56f413 --- /dev/null +++ b/src/codegen_ops_mmx_cmp.c @@ -0,0 +1,43 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_cmp.h" +#include "codegen_ops_helpers.h" + +#define ropPcmp(func) \ +uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + int src_reg = fetchdat & 7; \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } \ + else \ + { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ +} + +ropPcmp(PCMPEQB) +ropPcmp(PCMPEQW) +ropPcmp(PCMPEQD) +ropPcmp(PCMPGTB) +ropPcmp(PCMPGTW) +ropPcmp(PCMPGTD) diff --git a/src/codegen_ops_mmx_cmp.h b/src/codegen_ops_mmx_cmp.h new file mode 100644 index 0000000..6069ad1 --- /dev/null +++ b/src/codegen_ops_mmx_cmp.h @@ -0,0 +1,6 @@ +uint32_t ropPCMPEQB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPEQW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPEQD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPGTB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPGTW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPGTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 77af266ab2a389316d50d519a47186ba76023cc8 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 23 Nov 2018 18:34:30 +0000 Subject: [PATCH 058/181] Added recompiled versions of PACK* and PUNPCK * --- src/codegen_backend_arm64_ops.c | 48 +++++++++ src/codegen_backend_arm64_ops.h | 12 +++ src/codegen_backend_arm64_uops.c | 147 +++++++++++++++++++++++++- src/codegen_backend_arm_ops.c | 27 +++++ src/codegen_backend_arm_ops.h | 7 ++ src/codegen_backend_arm_uops.c | 168 +++++++++++++++++++++++++++++- src/codegen_backend_x86-64_ops.c | 50 +++++++++ src/codegen_backend_x86-64_ops.h | 11 ++ src/codegen_backend_x86-64_uops.c | 141 ++++++++++++++++++++++++- src/codegen_backend_x86_ops.c | 50 +++++++++ src/codegen_backend_x86_ops.h | 11 ++ src/codegen_backend_x86_uops.c | 143 ++++++++++++++++++++++++- src/codegen_ir_defs.h | 31 +++++- src/codegen_ops.c | 5 +- src/codegen_ops_mmx_pack.c | 46 ++++++++ src/codegen_ops_mmx_pack.h | 9 ++ 16 files changed, 898 insertions(+), 8 deletions(-) create mode 100644 src/codegen_ops_mmx_pack.c create mode 100644 src/codegen_ops_mmx_pack.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 576b12f..c5e7fb0 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -160,6 +160,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SQADD_V4H (0x0e600c00) #define OPCODE_SQSUB_V8B (0x0e202c00) #define OPCODE_SQSUB_V4H (0x0e602c00) +#define OPCODE_SQXTN_V8B_8H (0x0e214800) +#define OPCODE_SQXTN_V4H_4S (0x0e614800) #define OPCODE_SHL_VD (0x0e005400) #define OPCODE_SHL_VQ (0x4e005400) #define OPCODE_SSHR_VD (0x0e004400) @@ -177,8 +179,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UQADD_V4H (0x2e600c00) #define OPCODE_UQSUB_V8B (0x2e202c00) #define OPCODE_UQSUB_V4H (0x2e602c00) +#define OPCODE_UQXTN_V8B_8H (0x2e214800) #define OPCODE_USHR_VD (0x2e004400) #define OPCODE_USHR_VQ (0x6e004400) +#define OPCODE_ZIP1_V8B (0x0e003800) +#define OPCODE_ZIP1_V4H (0x0e403800) +#define OPCODE_ZIP1_V2S (0x0e803800) +#define OPCODE_ZIP2_V8B (0x0e007800) +#define OPCODE_ZIP2_V4H (0x0e407800) +#define OPCODE_ZIP2_V2S (0x0e807800) #define DATPROC_SHIFT(sh) (sh << 10) #define DATPROC_IMM_SHIFT(sh) (sh << 22) @@ -965,6 +974,15 @@ void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int sr codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_SQXTN_V4B_4H(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SQXTN_V4B_4H | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) { codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); @@ -1129,6 +1147,11 @@ void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int sr codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_UQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) { codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); @@ -1142,6 +1165,31 @@ void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } +void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP1_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP1_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP1_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP2_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP2_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP2_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_call(codeblock_t *block, void *dst_addr) { int offset = add_literal_q(block, (uintptr_t)dst_addr); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 4dba688..77c02c7 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -152,6 +152,9 @@ void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_SQXTN_V4H_4D(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); @@ -195,10 +198,19 @@ void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 4600f21..68f1122 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1384,6 +1384,55 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_VZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm64_UQXTN_V4H_4D(block, dest_reg, dest_reg); + host_arm64_UQXTN_V4H_4D(block, REG_V_TEMP, src_reg_b); + host_arm64_VZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_VZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PADDB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1824,6 +1873,91 @@ static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_VZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_VZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_VZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_VZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_VZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm64_VZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2346,6 +2480,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, + [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, + [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PADDB & UOP_MASK] = codegen_PADDB, [UOP_PADDW & UOP_MASK] = codegen_PADDW, [UOP_PADDD & UOP_MASK] = codegen_PADDD, @@ -2377,7 +2515,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index b604f7e..815c894 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -121,6 +121,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VQADD_S16 0xf2100010 #define OPCODE_VQADD_U8 0xf3000010 #define OPCODE_VQADD_U16 0xf3100010 +#define OPCODE_VQMOVN_S16 0xf3b20280 +#define OPCODE_VQMOVN_S32 0xf3b60280 +#define OPCODE_VQMOVN_U16 0xf3b202c0 #define OPCODE_VQSUB_S8 0xf2000210 #define OPCODE_VQSUB_S16 0xf2100210 #define OPCODE_VQSUB_U8 0xf3000210 @@ -140,6 +143,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VSUB_I8 0xf3000800 #define OPCODE_VSUB_I16 0xf3100800 #define OPCODE_VSUB_I32 0xf3200800 +#define OPCODE_VZIP_D16 0xf3b60180 +#define OPCODE_VZIP_D32 0xf3ba0180 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -944,6 +949,19 @@ void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_ codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VQMOVN_S16 | Vd(dst_reg) | Vm(src_reg)); +} +void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VQMOVN_S32 | Vd(dst_reg) | Vm(src_reg)); +} +void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); +} + void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift) { if (shift > 15) @@ -1028,4 +1046,13 @@ void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) +{ + codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); +} +void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg) +{ + codegen_addlong(block, OPCODE_VZIP_D32 | Vd(d_reg) | Vm(m_reg)); +} + #endif diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 6c7081a..28c3299 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -181,6 +181,10 @@ void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_r void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg); +void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg); +void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg); + void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift); @@ -197,3 +201,6 @@ void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); + +void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg); +void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 9f57130..7e9b6f8 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1504,6 +1504,55 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VQMOVN_S16(block, dest_reg, dest_reg); + host_arm_VQMOVN_S16(block, REG_D_TEMP, src_reg_b); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm_VQMOVN_S32(block, dest_reg, dest_reg); + host_arm_VQMOVN_S32(block, REG_D_TEMP, src_reg_b); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm_VQMOVN_U16(block, dest_reg, dest_reg); + host_arm_VQMOVN_U16(block, REG_D_TEMP, src_reg_b); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PADDB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1944,6 +1993,112 @@ static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); + } + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); + } + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2466,6 +2621,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, + [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, + [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PADDB & UOP_MASK] = codegen_PADDB, [UOP_PADDW & UOP_MASK] = codegen_PADDW, [UOP_PADDD & UOP_MASK] = codegen_PADDD, @@ -2497,7 +2656,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 83a24fd..9aabc0e 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1229,6 +1229,25 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} + void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ @@ -1375,6 +1394,37 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index ba2c0a5..67bccb7 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -153,6 +153,10 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -191,6 +195,13 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 4bd8b0e..d960dca 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1270,6 +1270,49 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PADDB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1680,6 +1723,91 @@ static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2117,6 +2245,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, + [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, + [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PADDB & UOP_MASK] = codegen_PADDB, [UOP_PADDW & UOP_MASK] = codegen_PADDW, [UOP_PADDD & UOP_MASK] = codegen_PADDD, @@ -2148,7 +2280,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index a3e63b7..8376908 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1087,6 +1087,25 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ } } +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} + void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ @@ -1233,6 +1252,37 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + void host_x86_POP(codeblock_t *block, int src_reg) { codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index bf1e492..491c719 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -154,6 +154,10 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -192,6 +196,13 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e8b11b9..654843b 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1273,6 +1273,49 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PADDB(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -1683,6 +1726,91 @@ static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2116,7 +2244,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, [UOP_FCOM & UOP_MASK] = codegen_FCOM, - + + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, + [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, + [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PADDB & UOP_MASK] = codegen_PADDB, [UOP_PADDW & UOP_MASK] = codegen_PADDW, [UOP_PADDD & UOP_MASK] = codegen_PADDD, @@ -2148,7 +2280,14 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW + [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 694b585..4029c2c 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -242,8 +242,26 @@ #define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) /*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ #define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) +/*UOP_PUNPCKLBW - (packed byte) dest_reg = interleave low src_reg_a/src_reg_b*/ +#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae) +/*UOP_PUNPCKLWD - (packed word) dest_reg = interleave low src_reg_a/src_reg_b*/ +#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf) +/*UOP_PUNPCKLDQ - (packed long) dest_reg = interleave low src_reg_a/src_reg_b*/ +#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0) +/*UOP_PUNPCKHBW - (packed byte) dest_reg = interleave high src_reg_a/src_reg_b*/ +#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1) +/*UOP_PUNPCKHWD - (packed word) dest_reg = interleave high src_reg_a/src_reg_b*/ +#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2) +/*UOP_PUNPCKHDQ - (packed long) dest_reg = interleave high src_reg_a/src_reg_b*/ +#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3) +/*UOP_PACKSSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with signed saturation*/ +#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4) +/*UOP_PACKSSDW - dest_reg = interleave src_reg_a/src_reg_b, converting longs to words with signed saturation*/ +#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5) +/*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/ +#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6) -#define UOP_MAX 0xb0 +#define UOP_MAX 0xb7 #define UOP_MASK 0xffff @@ -583,6 +601,10 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/) #define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) +#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b) + #define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b) @@ -616,6 +638,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b) + #define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) #define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 0ec4059..71a2e86 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -15,6 +15,7 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mmx_logic.h" +#include "codegen_ops_mmx_pack.h" #include "codegen_ops_mmx_shift.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" @@ -79,7 +80,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, /*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, @@ -101,7 +102,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, /*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, diff --git a/src/codegen_ops_mmx_pack.c b/src/codegen_ops_mmx_pack.c new file mode 100644 index 0000000..7bf1941 --- /dev/null +++ b/src/codegen_ops_mmx_pack.c @@ -0,0 +1,46 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_mmx_pack.h" +#include "codegen_ops_helpers.h" + +#define ropPpack(func) \ +uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + int src_reg = fetchdat & 7; \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } \ + else \ + { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ +} + +ropPpack(PACKSSWB) +ropPpack(PACKSSDW) +ropPpack(PACKUSWB) +ropPpack(PUNPCKLBW) +ropPpack(PUNPCKLWD) +ropPpack(PUNPCKLDQ) +ropPpack(PUNPCKHBW) +ropPpack(PUNPCKHWD) +ropPpack(PUNPCKHDQ) diff --git a/src/codegen_ops_mmx_pack.h b/src/codegen_ops_mmx_pack.h new file mode 100644 index 0000000..f46eea6 --- /dev/null +++ b/src/codegen_ops_mmx_pack.h @@ -0,0 +1,9 @@ +uint32_t ropPACKSSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPACKSSDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPACKUSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUNPCKLBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUNPCKLWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUNPCKLDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUNPCKHBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUNPCKHWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUNPCKHDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 086422b79fec0a1bcad6b39cb1e88f63187e6438 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 24 Nov 2018 12:52:08 +0000 Subject: [PATCH 059/181] Added recompiled versions of PMULLW, PMULHW and PMADDWD. --- src/codegen_backend_arm64_ops.c | 36 +++++++++++++++++++---- src/codegen_backend_arm64_ops.h | 8 +++++ src/codegen_backend_arm64_uops.c | 49 +++++++++++++++++++++++++++++++ src/codegen_backend_arm_ops.c | 18 ++++++++++++ src/codegen_backend_arm_ops.h | 7 +++++ src/codegen_backend_arm_uops.c | 49 +++++++++++++++++++++++++++++++ src/codegen_backend_x86-64_ops.c | 13 ++++++++ src/codegen_backend_x86-64_ops.h | 4 +++ src/codegen_backend_x86-64_uops.c | 47 +++++++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 13 ++++++++ src/codegen_backend_x86_ops.h | 4 +++ src/codegen_backend_x86_uops.c | 47 +++++++++++++++++++++++++++++ src/codegen_ir_defs.h | 12 +++++++- src/codegen_ops.c | 12 ++++---- src/codegen_ops_mmx_arith.c | 4 +++ src/codegen_ops_mmx_arith.h | 4 +++ 16 files changed, 314 insertions(+), 13 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index c5e7fb0..1ae57d9 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -151,9 +151,11 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_LSL (0x1ac02000) #define OPCODE_LSR (0x1ac02400) #define OPCODE_MSR_FPCR (0xd51b4400) +#define OPCODE_MUL_V4H (0x0e609c00) #define OPCODE_NOP (0xd503201f) #define OPCODE_ORR_V (0x0ea01c00) #define OPCODE_RET (0xd65f0000) +#define OPCODE_SADDLP_V2S_4H (0x0e602800) #define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) #define OPCODE_SQADD_V8B (0x0e200c00) @@ -164,6 +166,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SQXTN_V4H_4S (0x0e614800) #define OPCODE_SHL_VD (0x0e005400) #define OPCODE_SHL_VQ (0x4e005400) +#define OPCODE_SHRN (0x0f008400) +#define OPCODE_SMULL_V4S_4H (0x0e60c000) #define OPCODE_SSHR_VD (0x0e004400) #define OPCODE_SSHR_VQ (0x4e004400) #define OPCODE_STR_REG (0xb8206800) @@ -900,6 +904,11 @@ void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg) codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg)); } +void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_MUL_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_NOP(codeblock_t *block) { codegen_addlong(block, OPCODE_NOP); @@ -943,6 +952,11 @@ void host_arm64_RET(codeblock_t *block, int reg) codegen_addlong(block, OPCODE_RET | Rn(reg)); } +void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) +{ + codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); +} + void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); @@ -957,6 +971,16 @@ void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_SHRN_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | SHIFT_IMM_V2S(shift)); +} + +void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_SMULL_V4S_4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); @@ -983,28 +1007,28 @@ void host_arm64_SQXTN_V4B_4H(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SQXTN_V4B_4H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); } -void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); } -void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } -void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); } -void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); } -void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 77c02c7..01dd50c 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -134,6 +134,8 @@ void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data); void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg); +void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_NOP(codeblock_t *block); void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); @@ -142,6 +144,8 @@ void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_RET(codeblock_t *block, int reg); +void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg); + void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); @@ -159,6 +163,10 @@ void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift) void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); + +void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 68f1122..18b1d48 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1617,6 +1617,51 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_SADDLP_V2S_4H(block, dest_reg, dest_reg); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm64_SMULL_V4S_4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_SHRN_V4H_4S(block, dest_reg, dest_reg, 16); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2499,6 +2544,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, + [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, + [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 815c894..c0a5a6a 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -116,7 +116,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMRS_APSR 0xeef1fa10 #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 +#define OPCODE_VMUL_S16 0xf2100510 +#define OPCODE_VMULL_S16 0xf2900c00 #define OPCODE_VORR_D 0xf2200110 +#define OPCODE_VPADDL_S16 0xf3b40200 #define OPCODE_VQADD_S8 0xf2000010 #define OPCODE_VQADD_S16 0xf2100010 #define OPCODE_VQADD_U8 0xf3000010 @@ -907,15 +910,30 @@ void host_arm_VMRS_APSR(codeblock_t *block) { codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); } + void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VMULL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VMULL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} + void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); +} + void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 28c3299..946d7d5 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -170,8 +170,15 @@ void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); + void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m); +void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m); + void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); + +void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg); + void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 7e9b6f8..11e9f8f 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1737,6 +1737,51 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); + host_arm_VPADDL_S16(block, dest_reg, dest_reg); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm_VMULL_S16(block, dest_reg, src_reg_a, src_reg_b); + host_arm_VSHRN_16(block, dest_reg, dest_reg, 16); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2640,6 +2685,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, + [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, + [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 9aabc0e..ed57f2a 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1319,6 +1319,19 @@ void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} + void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 67bccb7..35510d0 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -177,6 +177,10 @@ void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index d960dca..faf5c33 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1497,6 +1497,49 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -2264,6 +2307,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, + [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, + [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 8376908..e477122 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1177,6 +1177,19 @@ void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} + void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 491c719..cd9eb4e 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -178,6 +178,10 @@ void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 654843b..c977bae 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1500,6 +1500,49 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -2264,6 +2307,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, + [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, + [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 4029c2c..eea588f 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -260,8 +260,14 @@ #define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5) /*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/ #define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6) +/*UOP_PMULLW - (packed word) dest_reg = (src_reg_a * src_reg_b) & 0xffff*/ +#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7) +/*UOP_PMULHW - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ +#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8) +/*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ +#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9) -#define UOP_MAX 0xb7 +#define UOP_MAX 0xba #define UOP_MASK 0xffff @@ -620,6 +626,10 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b) + #define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) #define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) #define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 71a2e86..00e4018 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -89,9 +89,9 @@ RecompOpFn recomp_opcodes_0f[512] = /*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, +/*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -111,9 +111,9 @@ RecompOpFn recomp_opcodes_0f[512] = /*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, +/*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, }; RecompOpFn recomp_opcodes_d8[512] = diff --git a/src/codegen_ops_mmx_arith.c b/src/codegen_ops_mmx_arith.c index 848c046..cd23e3c 100644 --- a/src/codegen_ops_mmx_arith.c +++ b/src/codegen_ops_mmx_arith.c @@ -50,3 +50,7 @@ ropParith(PSUBSB) ropParith(PSUBSW) ropParith(PSUBUSB) ropParith(PSUBUSW) + +ropParith(PMADDWD) +ropParith(PMULHW) +ropParith(PMULLW) diff --git a/src/codegen_ops_mmx_arith.h b/src/codegen_ops_mmx_arith.h index e848c8d..5f67f0a 100644 --- a/src/codegen_ops_mmx_arith.h +++ b/src/codegen_ops_mmx_arith.h @@ -13,3 +13,7 @@ uint32_t ropPSUBSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uint32_t ropPSUBSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPSUBUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPSUBUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPMADDWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPMULHW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPMULLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 2a19183d836bfa415733cfeca2e25e8abb3db9a4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 24 Nov 2018 20:16:52 +0000 Subject: [PATCH 060/181] Added debug code to log execution rate of non-recompiled instructions. --- src/codegen.c | 40 +++++++++++++++++++++++++++++++++- src/codegen.h | 7 ++++++ src/codegen_backend.c | 35 +++++++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 6 +++++ src/codegen_backend_x86_ops.h | 2 ++ src/codegen_backend_x86_uops.c | 16 +++++++++++++- src/codegen_ir_defs.h | 10 +++++++++ src/pc.c | 1 + 8 files changed, 115 insertions(+), 2 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index d06438c..dfa9ea4 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -310,7 +310,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t int over = 0; int test_modrm = 1; int pc_off = 0; - +#ifdef DEBUG_EXTRA + uint8_t last_prefix = 0; +#endif op_ea_seg = &cpu_state.seg_ds; op_ssegs = 0; @@ -321,6 +323,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t switch (opcode) { case 0x0f: +#ifdef DEBUG_EXTRA + last_prefix = 0x0f; +#endif op_table = x86_dynarec_opcodes_0f; recomp_op_table = recomp_opcodes_0f; over = 1; @@ -359,6 +364,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xd8: +#ifdef DEBUG_EXTRA + last_prefix = 0xd8; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; recomp_op_table = recomp_opcodes_d8; opcode_shift = 3; @@ -369,6 +377,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xd9: +#ifdef DEBUG_EXTRA + last_prefix = 0xd9; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; recomp_op_table = recomp_opcodes_d9; opcode_mask = 0xff; @@ -378,6 +389,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xda: +#ifdef DEBUG_EXTRA + last_prefix = 0xda; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; recomp_op_table = recomp_opcodes_da; opcode_mask = 0xff; @@ -387,6 +401,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdb: +#ifdef DEBUG_EXTRA + last_prefix = 0xdb; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; recomp_op_table = recomp_opcodes_db; opcode_mask = 0xff; @@ -396,6 +413,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdc: +#ifdef DEBUG_EXTRA + last_prefix = 0xdc; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; recomp_op_table = recomp_opcodes_dc; opcode_shift = 3; @@ -406,6 +426,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdd: +#ifdef DEBUG_EXTRA + last_prefix = 0xdd; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; recomp_op_table = recomp_opcodes_dd; opcode_mask = 0xff; @@ -415,6 +438,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xde: +#ifdef DEBUG_EXTRA + last_prefix = 0xde; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; recomp_op_table = recomp_opcodes_de; opcode_mask = 0xff; @@ -424,6 +450,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdf: +#ifdef DEBUG_EXTRA + last_prefix = 0xdf; +#endif op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; recomp_op_table = recomp_opcodes_df; opcode_mask = 0xff; @@ -437,10 +466,16 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t break; case 0xf2: /*REPNE*/ +#ifdef DEBUG_EXTRA + last_prefix = 0xf2; +#endif op_table = x86_dynarec_opcodes_REPNE; recomp_op_table = NULL;//recomp_opcodes_REPNE; break; case 0xf3: /*REPE*/ +#ifdef DEBUG_EXTRA + last_prefix = 0xf3; +#endif op_table = x86_dynarec_opcodes_REPE; recomp_op_table = NULL;//recomp_opcodes_REPE; break; @@ -525,6 +560,9 @@ generate_call: op_pc -= pc_off; } +#ifdef DEBUG_EXTRA + uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); +#endif uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off); uop_MOV_IMM(ir, IREG_oldpc, old_pc); diff --git a/src/codegen.h b/src/codegen.h index 7136330..dcca68b 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -252,6 +252,7 @@ extern codeblock_t *codeblock; extern codeblock_t **codeblock_hash; void codegen_init(); +void codegen_close(); void codegen_reset(); void codegen_block_init(uint32_t phys_addr); void codegen_block_remove(); @@ -330,4 +331,10 @@ extern int codegen_reg_loaded[8]; extern int codegen_in_recompile; void codegen_generate_reset(); + + +#ifdef DEBUG_EXTRA +extern uint32_t instr_counts[256*256]; +#endif + #endif diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 7d96ec3..fa01aa8 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -46,10 +46,45 @@ static uint32_t last_op32; static x86seg *last_ea_seg; static int last_ssegs; +#ifdef DEBUG_EXTRA +uint32_t instr_counts[256*256]; +#endif void codegen_init() { codegen_backend_init(); +#ifdef DEBUG_EXTRA + memset(instr_counts, 0, sizeof(instr_counts)); +#endif +} + +void codegen_close() +{ +#ifdef DEBUG_EXTRA + pclog("Instruction counts :\n"); + while (1) + { + int c; + uint32_t highest_num = 0, highest_idx = 0; + + for (c = 0; c < 256*256; c++) + { + if (instr_counts[c] > highest_num) + { + highest_num = instr_counts[c]; + highest_idx = c; + } + } + if (!highest_num) + break; + + instr_counts[highest_idx] = 0; + if (highest_idx > 256) + pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num); + else + pclog(" %02x = %u\n", highest_idx & 0xff, highest_num); + } +#endif } void codegen_reset() diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index e477122..33dc124 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -343,6 +343,12 @@ void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); } +void host_x86_INC32_ABS(codeblock_t *block, void *p) +{ + codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ + codegen_addlong(block, (uint32_t)p); +} + void host_x86_JMP(codeblock_t *block, void *p) { codegen_addbyte(block, 0xe9); /*JMP*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index cd9eb4e..5084c5e 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -39,6 +39,8 @@ void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_INC32_ABS(codeblock_t *block, void *p); + void host_x86_JMP(codeblock_t *block, void *p); uint32_t *host_x86_JMP_short(codeblock_t *block); uint32_t *host_x86_JMP_long(codeblock_t *block); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index c977bae..a5ff9d9 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -2192,6 +2192,16 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) return 0; } +#ifdef DEBUG_EXTRA +static int codegen_LOG_INSTR(codeblock_t *block, uop_t *uop) +{ + if (uop->imm_data > 256*256) + fatal("LOG_INSTR %08x\n", uop->imm_data); + host_x86_INC32_ABS(block, &instr_counts[uop->imm_data]); + return 0; +} +#endif + const uOpFn uop_handlers[UOP_MAX] = { [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, @@ -2334,7 +2344,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + +#ifdef DEBUG_EXTRA + [UOP_LOG_INSTR & UOP_MASK] = codegen_LOG_INSTR +#endif }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index eea588f..4a32aa7 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -54,6 +54,12 @@ #define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) /*UOP_JMP_DEST - jump to ptr*/ #define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) + +#ifdef DEBUG_EXTRA +/*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/ +#define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f) +#endif + /*UOP_MOV_PTR - dest_reg = p*/ #define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) /*UOP_MOV_IMM - dest_reg = imm_data*/ @@ -661,6 +667,10 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) #define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) +#ifdef DEBUG_EXTRA +#define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm) +#endif + void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); diff --git a/src/pc.c b/src/pc.c index faeaa1a..ea77535 100644 --- a/src/pc.c +++ b/src/pc.c @@ -624,6 +624,7 @@ void speedchanged() void closepc() { + codegen_close(); atapi->exit(); // ioctl_close(); dumppic(); From 6341caf318289e7753360c04081dc988ed417616 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 24 Nov 2018 20:35:33 +0000 Subject: [PATCH 061/181] ARM MMX fixes --- src/codegen_backend_arm_defs.h | 2 + src/codegen_backend_arm_ops.c | 68 +++++++++++++++------ src/codegen_backend_arm_ops.h | 8 +++ src/codegen_backend_arm_uops.c | 106 +++++++++++++++++++++------------ 4 files changed, 129 insertions(+), 55 deletions(-) diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 7deb72f..def8970 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -43,6 +43,8 @@ #define REG_D15 15 #define REG_D_TEMP REG_D0 +#define REG_Q_TEMP REG_D0 +#define REG_Q_TEMP_2 REG_D2 #define REG_MASK_R0 (1 << REG_R0) #define REG_MASK_R1 (1 << REG_R1) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index c0a5a6a..b6692a7 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -113,13 +113,17 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMOV_D_64 0xec400b10 #define OPCODE_VMOV_S_32 0xee000a10 #define OPCODE_VMOV_D_D 0xeeb00b40 +#define OPCODE_VMOVN_I32 0xf3b60200 +#define OPCODE_VMOVN_I64 0xf3ba0200 #define OPCODE_VMRS_APSR 0xeef1fa10 #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 -#define OPCODE_VMUL_S16 0xf2100510 +#define OPCODE_VMUL_S16 0xf2100910 #define OPCODE_VMULL_S16 0xf2900c00 #define OPCODE_VORR_D 0xf2200110 #define OPCODE_VPADDL_S16 0xf3b40200 +#define OPCODE_VPADDL_S32 0xf3b80200 +#define OPCODE_VPADDL_Q_S32 0xf3b80240 #define OPCODE_VQADD_S8 0xf2000010 #define OPCODE_VQADD_S16 0xf2100010 #define OPCODE_VQADD_U8 0xf3000010 @@ -140,14 +144,16 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VSHR_D_U16 0xf3900010 #define OPCODE_VSHR_D_U32 0xf3a00010 #define OPCODE_VSHR_D_U64 0xf3800090 +#define OPCODE_VSHRN 0xf2800810 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 #define OPCODE_VSUB_I8 0xf3000800 #define OPCODE_VSUB_I16 0xf3100800 #define OPCODE_VSUB_I32 0xf3200800 +#define OPCODE_VZIP_D8 0xf3b20180 #define OPCODE_VZIP_D16 0xf3b60180 -#define OPCODE_VZIP_D32 0xf3ba0180 +#define OPCODE_VZIP_D32 0xf3ba0080 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -182,6 +188,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define VSHIFT_IMM(shift) ((shift) << 16) +#define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) + static inline uint32_t arm_data_offset(int offset) { if (offset < -0xffc || offset > 0xffc) @@ -902,6 +910,14 @@ void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VMOVN_I32 | Vd(dest_reg) | Vm(src_reg)); +} +void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); @@ -933,6 +949,14 @@ void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); } +void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VPADDL_S32 | Vd(dst_reg) | Vm(src_reg)); +} +void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VPADDL_Q_S32 | Vd(dst_reg) | Vm(src_reg)); +} void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { @@ -980,59 +1004,65 @@ void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 15) fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 31) fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 63) fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHR_SD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_S16(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 15) fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHR_SD_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + codegen_addlong(block, OPCODE_VSHR_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); } -void host_arm_VSHR_SD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_S32(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 31) fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHR_SD_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + codegen_addlong(block, OPCODE_VSHR_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); } -void host_arm_VSHR_SD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_S64(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 63) fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHR_SD_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + codegen_addlong(block, OPCODE_VSHR_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); } -void host_arm_VSHR_UD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_U16(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 15) fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHR_UD_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + codegen_addlong(block, OPCODE_VSHR_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); } -void host_arm_VSHR_UD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_U32(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 31) fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHR_UD_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + codegen_addlong(block, OPCODE_VSHR_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); } -void host_arm_VSHR_UD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_U64(codeblock_t *block, int dst_reg, int src_reg, int shift) { if (shift > 63) fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHR_UD_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + codegen_addlong(block, OPCODE_VSHR_D_U64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); +} +void host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + if (shift > 16) + fatal("host_arm_VSHRN_32 : shift > 16\n"); + codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16-shift)); } void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) @@ -1064,6 +1094,10 @@ void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg) +{ + codegen_addlong(block, OPCODE_VZIP_D8 | Vd(d_reg) | Vm(m_reg)); +} void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) { codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 946d7d5..edfbbc1 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -163,11 +163,15 @@ void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); + void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg); void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high); void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg); + void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); @@ -178,6 +182,8 @@ void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg); +void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg); +void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg); void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); @@ -201,6 +207,7 @@ void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shif void host_arm_VSHR_D_U16(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); @@ -209,5 +216,6 @@ void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_re void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg); void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg); void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 11e9f8f..c63a370 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1290,7 +1290,7 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { - host_arm_VMOV_32_S(block, dest_reg, src_reg, REG_TEMP); + host_arm_VMOV_32_S(block, dest_reg, src_reg); } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { @@ -1511,8 +1511,10 @@ static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VQMOVN_S16(block, dest_reg, dest_reg); - host_arm_VQMOVN_S16(block, REG_D_TEMP, src_reg_b); + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S16(block, REG_D_TEMP, REG_Q_TEMP_2); host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); } else @@ -1522,13 +1524,15 @@ static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) } static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VQMOVN_S32(block, dest_reg, dest_reg); - host_arm_VQMOVN_S32(block, REG_D_TEMP, src_reg_b); + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S32(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S32(block, REG_D_TEMP, REG_Q_TEMP_2); host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); } else @@ -1538,13 +1542,15 @@ static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) } static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VQMOVN_U16(block, dest_reg, dest_reg); - host_arm_VQMOVN_U16(block, REG_D_TEMP, src_reg_b); + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_U16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_U16(block, REG_D_TEMP, REG_Q_TEMP_2); host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); } else @@ -1739,13 +1745,14 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); - host_arm_VPADDL_S16(block, dest_reg, dest_reg); + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VPADDL_Q_S32(block, REG_Q_TEMP, REG_Q_TEMP); + host_arm_VMOVN_I64(block, dest_reg, REG_Q_TEMP); } else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1754,13 +1761,13 @@ static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) } static int codegen_PMULHW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VMULL_S16(block, dest_reg, src_reg_a, src_reg_b); - host_arm_VSHRN_16(block, dest_reg, dest_reg, 16); + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VSHRN_32(block, dest_reg, REG_Q_TEMP, 16); } else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1769,10 +1776,10 @@ static int codegen_PMULHW(codeblock_t *block, uop_t *uop) } static int codegen_PMULLW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); } @@ -1789,7 +1796,9 @@ static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); @@ -1806,7 +1815,9 @@ static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); @@ -1823,7 +1834,9 @@ static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); @@ -1840,7 +1853,9 @@ static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); else host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); @@ -1857,7 +1872,9 @@ static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); else host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); @@ -1874,7 +1891,9 @@ static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); else host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); @@ -1891,7 +1910,9 @@ static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); @@ -1908,7 +1929,9 @@ static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); @@ -1925,7 +1948,9 @@ static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); @@ -1966,9 +1991,6 @@ static int codegen_PSUBW(codeblock_t *block, uop_t *uop) } static int codegen_PSUBD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); @@ -2851,6 +2873,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); @@ -2863,6 +2889,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); From 856f0b447196a3dc1c419341724ec84b862a92b4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 25 Nov 2018 17:59:38 +0000 Subject: [PATCH 062/181] ARM64 MMX fixes --- src/codegen_backend_arm64_ops.c | 81 +++++++++++++++----- src/codegen_backend_arm64_ops.h | 16 ++-- src/codegen_backend_arm64_uops.c | 125 ++++++++++++++++++------------- 3 files changed, 146 insertions(+), 76 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 1ae57d9..9dabfe4 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -107,6 +107,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_ADD_V8B (0x0e208400) #define OPCODE_ADD_V4H (0x0e608400) #define OPCODE_ADD_V2S (0x0ea08400) +#define OPCODE_ADDP_V4S (0x4ea0bc00) #define OPCODE_AND_V (0x0e201c00) #define OPCODE_ASR (0x1ac02800) #define OPCODE_BIC_V (0x0e601c00) @@ -164,12 +165,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SQSUB_V4H (0x0e602c00) #define OPCODE_SQXTN_V8B_8H (0x0e214800) #define OPCODE_SQXTN_V4H_4S (0x0e614800) -#define OPCODE_SHL_VD (0x0e005400) -#define OPCODE_SHL_VQ (0x4e005400) +#define OPCODE_SHL_VD (0x0f005400) +#define OPCODE_SHL_VQ (0x4f005400) #define OPCODE_SHRN (0x0f008400) #define OPCODE_SMULL_V4S_4H (0x0e60c000) -#define OPCODE_SSHR_VD (0x0e004400) -#define OPCODE_SSHR_VQ (0x4e004400) +#define OPCODE_SSHR_VD (0x0f000400) +#define OPCODE_SSHR_VQ (0x4f000400) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) #define OPCODE_STRH_REG (0x78206800) @@ -184,8 +185,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UQSUB_V8B (0x2e202c00) #define OPCODE_UQSUB_V4H (0x2e602c00) #define OPCODE_UQXTN_V8B_8H (0x2e214800) -#define OPCODE_USHR_VD (0x2e004400) -#define OPCODE_USHR_VQ (0x6e004400) +#define OPCODE_UQXTN_V4H_4S (0x2e614800) +#define OPCODE_USHR_VD (0x2f000400) +#define OPCODE_USHR_VQ (0x6f000400) #define OPCODE_ZIP1_V8B (0x0e003800) #define OPCODE_ZIP1_V4H (0x0e403800) #define OPCODE_ZIP1_V2S (0x0e803800) @@ -220,6 +222,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) #define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) +#define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16) + static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) { @@ -312,6 +316,22 @@ void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); } } +void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data) +{ + if (!(imm_data & ~0xffffffull)) + { + if (imm_data & 0xfff) + { + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } + else + fatal("ADD_IMM_X %016llx\n", imm_data); +} void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); @@ -333,6 +353,11 @@ void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_ codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ADDP_V4S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) { codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset)); @@ -971,9 +996,11 @@ void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SHRN_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | SHIFT_IMM_V2S(shift)); + if (shift > 16) + fatal("host_arm64_SHRN_V4H_4S : shift > 16\n"); + codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | SHRN_SHIFT_IMM_V4S(16-shift)); } void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) @@ -1002,9 +1029,9 @@ void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SQXTN_V4B_4H(codeblock_t *block, int dst_reg, int src_reg) +void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SQXTN_V4B_4H | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); } void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) @@ -1022,15 +1049,21 @@ void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shif void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); + if (shift > 16) + fatal("host_arm_USHR_V4H : shift > 16\n"); + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16-shift)); } void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); + if (shift > 32) + fatal("host_arm_SSHR_V2S : shift > 32\n"); + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32-shift)); } void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); + if (shift > 64) + fatal("host_arm_SSHR_V2D : shift > 64\n"); + codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64-shift)); } void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) @@ -1175,18 +1208,28 @@ void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_UQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_UQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); +} -void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); + if (shift > 16) + fatal("host_arm_USHR_V4H : shift > 16\n"); + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16-shift)); } -void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); + if (shift > 32) + fatal("host_arm_USHR_V4S : shift > 32\n"); + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32-shift)); } -void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); + if (shift > 64) + fatal("host_arm_USHR_V2D : shift > 64\n"); + codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64-shift)); } void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 01dd50c..179c5af 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -4,6 +4,9 @@ void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data); + +void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset); @@ -157,13 +160,13 @@ void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg); -void host_arm64_SQXTN_V4H_4D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); -void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift); void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); @@ -201,12 +204,13 @@ uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit); void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); -void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 18b1d48..4f34ea3 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1386,14 +1386,14 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_VZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); } else fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1407,9 +1407,9 @@ static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_UQXTN_V4H_4D(block, dest_reg, dest_reg); - host_arm64_UQXTN_V4H_4D(block, REG_V_TEMP, src_reg_b); - host_arm64_VZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_SQXTN_V4H_4S(block, REG_V_TEMP, src_reg_b); + host_arm64_SQXTN_V4H_4S(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); } else fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1423,9 +1423,9 @@ static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_VZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); } else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1510,7 +1510,7 @@ static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_UQADD_V8H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_UQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1553,7 +1553,7 @@ static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1567,7 +1567,7 @@ static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1581,7 +1581,7 @@ static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1595,7 +1595,7 @@ static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1609,7 +1609,7 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1619,13 +1619,13 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); - host_arm64_SADDLP_V2S_4H(block, dest_reg, dest_reg); + host_arm64_SMULL_V4S_4H(block, REG_V_TEMP, src_reg_a, src_reg_b); + host_arm64_ADDP_V4S(block, dest_reg, REG_V_TEMP, REG_V_TEMP); } else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1634,10 +1634,10 @@ static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) } static int codegen_PMULHW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { host_arm64_SMULL_V4S_4H(block, dest_reg, src_reg_a, src_reg_b); host_arm64_SHRN_V4H_4S(block, dest_reg, dest_reg, 16); @@ -1649,10 +1649,10 @@ static int codegen_PMULHW(codeblock_t *block, uop_t *uop) } static int codegen_PMULLW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); } @@ -1669,7 +1669,9 @@ static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); @@ -1686,7 +1688,9 @@ static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); @@ -1703,7 +1707,9 @@ static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); @@ -1720,7 +1726,9 @@ static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); else host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); @@ -1737,7 +1745,9 @@ static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); else host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); @@ -1754,7 +1764,9 @@ static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); else host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); @@ -1771,7 +1783,9 @@ static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); @@ -1788,7 +1802,9 @@ static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); @@ -1805,7 +1821,9 @@ static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); @@ -1846,9 +1864,6 @@ static int codegen_PSUBW(codeblock_t *block, uop_t *uop) } static int codegen_PSUBD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); @@ -1925,7 +1940,7 @@ static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_VZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_ZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1939,7 +1954,7 @@ static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_VZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_ZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1953,7 +1968,7 @@ static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_VZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_ZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1967,7 +1982,7 @@ static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_VZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_ZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1981,7 +1996,7 @@ static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_VZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_ZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1995,7 +2010,7 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm64_VZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_ZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -2613,7 +2628,7 @@ void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_LDRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } @@ -2621,7 +2636,7 @@ void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } @@ -2629,7 +2644,7 @@ void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } @@ -2673,7 +2688,7 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } @@ -2681,7 +2696,7 @@ void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } @@ -2689,7 +2704,7 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } @@ -2716,6 +2731,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32_stack - not in range\n"); } +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_arm64_LDR_IMM_F64(block, host_reg, REG_SP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_arm64_LDR_IMM_F64(block, host_reg, REG_SP, stack_offset); @@ -2728,6 +2747,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos else fatal("codegen_direct_write_32_stack - not in range\n"); } +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_arm64_STR_IMM_F64(block, host_reg, REG_SP, stack_offset); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_arm64_STR_IMM_F64(block, host_reg, REG_SP, stack_offset); From 07035c97c850cce90e8e75cee7e929b25fa2498b Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 26 Nov 2018 17:00:00 +0000 Subject: [PATCH 063/181] Added recompiled versions of FABS, FCHS, FSQRT and FTST. --- src/codegen_backend_arm64_ops.c | 18 ++++++++ src/codegen_backend_arm64_ops.h | 4 ++ src/codegen_backend_arm64_uops.c | 70 ++++++++++++++++++++++++++++ src/codegen_backend_arm_ops.c | 18 ++++++++ src/codegen_backend_arm_ops.h | 6 +++ src/codegen_backend_arm_uops.c | 68 +++++++++++++++++++++++++++ src/codegen_backend_x86-64_ops.c | 10 ++++ src/codegen_backend_x86-64_ops.h | 4 ++ src/codegen_backend_x86-64_uops.c | 77 +++++++++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 10 ++++ src/codegen_backend_x86_ops.h | 4 ++ src/codegen_backend_x86_uops.c | 77 +++++++++++++++++++++++++++++++ src/codegen_ir_defs.h | 13 ++++++ src/codegen_ops.c | 8 ++-- src/codegen_ops_fpu_arith.c | 36 +++++++++++++++ src/codegen_ops_fpu_arith.h | 5 ++ 16 files changed, 424 insertions(+), 4 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 9dabfe4..ee2c0b6 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -120,6 +120,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_CMGT_V4H (0x0e603400) #define OPCODE_CMGT_V2S (0x0ea03400) #define OPCODE_EOR_V (0x2e201c00) +#define OPCODE_FABS_D (0x1e60c000) #define OPCODE_FADD_D (0x1e602800) #define OPCODE_FCMP_D (0x1e602000) #define OPCODE_FCVT_D_S (0x1e22c000) @@ -139,7 +140,9 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_FMOV_S_W (0x1e270000) #define OPCODE_FMOV_W_S (0x1e260000) #define OPCODE_FMUL_D (0x1e600800) +#define OPCODE_FNEG_D (0x1e614000) #define OPCODE_FRINTX_D (0x1e674000) +#define OPCODE_FSQRT_D (0x1e61c000) #define OPCODE_FSUB_D (0x1e603800) #define OPCODE_LDR_REG (0xb8606800) #define OPCODE_LDRX_REG (0xf8606800) @@ -680,6 +683,11 @@ void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr codegen_addlong(block, OPCODE_EOR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FABS_D | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); @@ -768,11 +776,21 @@ void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FNEG_D | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { if (!in_range7_x(offset)) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 179c5af..048c354 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -75,6 +75,8 @@ void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg); void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); @@ -101,6 +103,8 @@ void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 4f34ea3..0ee74dc 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -619,6 +619,71 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_arm64_FABS_D(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_arm64_FNEG_D(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_arm64_FSQRT_D(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) + { + host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); + host_arm64_MOVZ_IMM(block, dest_reg, 0); + host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0|C2|C3); + host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); + host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); + } + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_FADD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2540,6 +2605,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FABS & UOP_MASK] = codegen_FABS, + [UOP_FCHS & UOP_MASK] = codegen_FCHS, + [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, + [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index b6692a7..12e9c68 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -86,6 +86,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_USUB16 0xe6500f70 #define OPCODE_UXTB 0xe6ef0070 #define OPCODE_UXTH 0xe6ff0070 +#define OPCODE_VABS_D 0xeeb00bc0 #define OPCODE_VADD 0xee300b00 #define OPCODE_VADD_I8 0xf2000800 #define OPCODE_VADD_I16 0xf2100800 @@ -120,6 +121,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMUL 0xee200b00 #define OPCODE_VMUL_S16 0xf2100910 #define OPCODE_VMULL_S16 0xf2900c00 +#define OPCODE_VNEG_D 0xeeb10b40 #define OPCODE_VORR_D 0xf2200110 #define OPCODE_VPADDL_S16 0xf3b40200 #define OPCODE_VPADDL_S32 0xf3b80200 @@ -145,6 +147,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VSHR_D_U32 0xf3a00010 #define OPCODE_VSHR_D_U64 0xf3800090 #define OPCODE_VSHRN 0xf2800810 +#define OPCODE_VSQRT_D 0xeeb10bc0 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 @@ -796,6 +799,11 @@ void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } +void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VABS_D | Vd(dest_reg) | Vm(src_reg)); +} + void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -940,6 +948,11 @@ void host_arm_VMULL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_ codegen_addlong(block, OPCODE_VMULL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VNEG_D | Vd(dest_reg) | Vm(src_reg)); +} + void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -1065,6 +1078,11 @@ void host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16-shift)); } +void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg)); +} + void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index edfbbc1..542dc2a 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -139,6 +139,8 @@ void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate); void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate); +void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg); + void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); @@ -154,6 +156,8 @@ void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_re void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg); + void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); @@ -179,6 +183,8 @@ void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m); void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m); +void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg); + void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index c63a370..a9ce03e 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -693,6 +693,69 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_arm_VABS_D(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_arm_VNEG_D(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_arm_VSQRT_D(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) + { + host_arm_VSUB_D(block, REG_D_TEMP, REG_D_TEMP, REG_D_TEMP); + host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); + host_arm_MOV_IMM(block, dest_reg, 0); + host_arm_VMRS_APSR(block); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0|C2|C3); + } + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_FADD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2688,6 +2751,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FABS & UOP_MASK] = codegen_FABS, + [UOP_FCHS & UOP_MASK] = codegen_FCHS, + [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, + [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index ed57f2a..4ec3fd4 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -548,6 +548,11 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ +} + void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -1571,6 +1576,11 @@ void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} + void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 35510d0..10fe26a 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -71,6 +71,8 @@ void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); @@ -236,6 +238,8 @@ void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index faf5c33..dc87d53 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -548,6 +548,78 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) + { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); + host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); + host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) + { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + if (dest_reg != REG_EAX) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); + } + } + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_FADD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2288,6 +2360,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FABS & UOP_MASK] = codegen_FABS, + [UOP_FCHS & UOP_MASK] = codegen_FCHS, + [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, + [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 33dc124..a861d14 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -513,6 +513,11 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ } +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ +} + void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -1397,6 +1402,11 @@ void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} + void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg) diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 5084c5e..d07b0d9 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -75,6 +75,8 @@ void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32 void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); @@ -239,6 +241,8 @@ void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index a5ff9d9..20f39a7 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -559,6 +559,78 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_FABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) + { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); + host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); + host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) + { + host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); + } + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) + { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + if (dest_reg != REG_EAX) + { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); + } + } + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_FADD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2297,6 +2369,11 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_FMUL & UOP_MASK] = codegen_FMUL, [UOP_FSUB & UOP_MASK] = codegen_FSUB, [UOP_FCOM & UOP_MASK] = codegen_FCOM, + + [UOP_FABS & UOP_MASK] = codegen_FABS, + [UOP_FCHS & UOP_MASK] = codegen_FCHS, + [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, + [UOP_FTST & UOP_MASK] = codegen_FTST, [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 4a32aa7..15b3014 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -187,6 +187,14 @@ #define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) /*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/ #define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) +/*UOP_FABS - dest_reg = fabs(src_reg_a)*/ +#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86) +/*UOP_FCHS - dest_reg = fabs(src_reg_a)*/ +#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87) +/*UOP_FTST - dest_reg = flags from compare(src_reg_a, 0)*/ +#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88) +/*UOP_FSQRT - dest_reg = fsqrt(src_reg_a)*/ +#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89) /*UOP_MMX_ENTER - must be called before any MMX registers accessed*/ #define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) @@ -582,6 +590,11 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) #define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg) +#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg) +#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg) +#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg) + #define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0) #define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 00e4018..8dc433a 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -184,8 +184,8 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -206,8 +206,8 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL, }; RecompOpFn recomp_opcodes_da[512] = diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c index d903959..9d4259c 100644 --- a/src/codegen_ops_fpu_arith.c +++ b/src/codegen_ops_fpu_arith.c @@ -534,3 +534,39 @@ uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, ui ropFI_arith_mem(l, IREG_temp0) ropFI_arith_mem(w, IREG_temp0_W) + + +uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_FABS(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} + +uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_FCHS(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_FSQRT(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; +} +uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_FP_ENTER(ir); + uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + + return op_pc; +} diff --git a/src/codegen_ops_fpu_arith.h b/src/codegen_ops_fpu_arith.h index e61d4ae..60ae273 100644 --- a/src/codegen_ops_fpu_arith.h +++ b/src/codegen_ops_fpu_arith.h @@ -56,3 +56,8 @@ uint32_t ropFISUBl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uint32_t ropFISUBw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFISUBRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropFISUBRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 92ab0ee8ef020a299e885835c76fbea204ee99fa Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 27 Nov 2018 10:15:18 +0000 Subject: [PATCH 064/181] Fix flags on 8-bit memory INC/DEC. --- src/codegen_ops_arith.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index f4e4152..4c7c43d 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -1416,6 +1416,8 @@ uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + rebuild_c(ir); + if ((fetchdat & 0xc0) == 0xc0) { uop_MOVZX(ir, IREG_flags_op1, IREG_8(fetchdat & 7)); From c1565eb42fdc00593a354b7d1a916b1558899593 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 27 Nov 2018 19:43:01 +0000 Subject: [PATCH 065/181] Fix partial register handling - removes pointless loads when writing to non-32-bit registers (eg FPU or MMX). --- src/codegen_reg.c | 33 ++++++++++++++++++++++++++++++--- src/codegen_reg.h | 6 ++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 3e801a9..9c19d10 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -73,7 +73,7 @@ struct [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER}, [IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER}, - [IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER}, + [IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER}, [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER}, @@ -147,6 +147,33 @@ struct [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP}, }; +static int reg_is_native_size(ir_reg_t ir_reg) +{ + int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; + int requested_size = IREG_GET_SIZE(ir_reg.reg); + + switch (native_size) + { + case REG_BYTE: case REG_FPU_ST_BYTE: + return (requested_size == IREG_SIZE_B); + case REG_WORD: + return (requested_size == IREG_SIZE_W); + case REG_DWORD: + return (requested_size == IREG_SIZE_L); + case REG_QWORD: case REG_FPU_ST_QWORD: case REG_DOUBLE: case REG_FPU_ST_DOUBLE: + return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q)); + case REG_POINTER: + if (sizeof(void *) == 4) + return (requested_size == IREG_SIZE_L); + return (requested_size == IREG_SIZE_Q); + + default: + fatal("get_reg_is_native_size: unknown native size %i\n", native_size); + } + + return 0; +} + void codegen_reg_reset() { int c; @@ -260,7 +287,7 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, break; default: - fatal("codegen_reg_load - native_size=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size); + fatal("codegen_reg_load - native_size=%i reg=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size, IREG_GET_REG(ir_reg.reg)); } reg_set->regs[c] = ir_reg; @@ -469,7 +496,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) host_reg_set_t *reg_set = get_reg_set(ir_reg); int c; - if (IREG_GET_SIZE(ir_reg.reg) != IREG_SIZE_L) + if (!reg_is_native_size(ir_reg)) { /*Read in parent register so we can do partial accesses to it*/ ir_reg_t parent_reg; diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 8474ef9..63a0b6d 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -37,7 +37,7 @@ enum IREG_eaaddr = 14, IREG_ea_seg = 15, IREG_op32 = 16, - IREG_ssegs = 17, + IREG_ssegsx = 17, IREG_rm_mod_reg = 18, @@ -179,7 +179,9 @@ enum IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, - IREG_NPXS = IREG_NPXSx + IREG_SIZE_W + IREG_NPXS = IREG_NPXSx + IREG_SIZE_W, + + IREG_ssegs = IREG_ssegsx + IREG_SIZE_B }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) From a4d3aa1912a9ccf43727cc5bc0ef167c8e496f2e Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 09:42:04 +0000 Subject: [PATCH 066/181] Move flags and eflags variables into cpu_struct. --- src/386.c | 18 +- src/386_common.h | 10 +- src/386_dynarec.c | 44 +-- src/808x.c | 877 +++++++++++++++++++++-------------------- src/codegen.c | 4 +- src/codegen_ops_jump.c | 8 +- src/ibm.h | 5 +- src/x86.h | 2 +- src/x86_flags.h | 114 +++--- src/x86_ops_atomic.h | 8 +- src/x86_ops_bcd.h | 40 +- src/x86_ops_bit.h | 64 +-- src/x86_ops_bitscan.h | 4 +- src/x86_ops_flag.h | 94 ++--- src/x86_ops_int.h | 8 +- src/x86_ops_misc.h | 76 ++-- src/x86_ops_mov_ctrl.h | 24 +- src/x86_ops_mul.h | 48 +-- src/x86_ops_pmode.h | 38 +- src/x86_ops_rep.h | 84 ++-- src/x86_ops_ret.h | 34 +- src/x86_ops_shift.h | 90 ++--- src/x86_ops_string.h | 168 ++++---- src/x86seg.c | 85 ++-- src/x87_ops_arith.h | 24 +- 25 files changed, 1013 insertions(+), 958 deletions(-) diff --git a/src/386.c b/src/386.c index 25bb653..e7032d1 100644 --- a/src/386.c +++ b/src/386.c @@ -250,13 +250,13 @@ dontprint=0; if (!cpu_state.abrt) { - trap = flags & T_FLAG; + trap = cpu_state.flags & T_FLAG; opcode = fetchdat & 0xFF; fetchdat >>= 8; if (output == 3) { - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask); + pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,cpu_state.flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask); } cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -312,13 +312,13 @@ dontprint=0; } else { - writememw(ss,(SP-2)&0xFFFF,flags); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr = (1 << 2) + idt.base; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); } @@ -336,7 +336,7 @@ dontprint=0; nmi = 0; } } - else if ((flags&I_FLAG) && pic_intpending) + else if ((cpu_state.flags & I_FLAG) && pic_intpending) { temp=picinterrupt(); if (temp!=0xFF) @@ -352,13 +352,13 @@ dontprint=0; } else { - writememw(ss,(SP-2)&0xFFFF,flags); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr = (temp << 2) + idt.base; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); diff --git a/src/386_common.h b/src/386_common.h index 906c09a..91bf3c1 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -15,7 +15,7 @@ extern uint16_t ea_rseg; int checkio(int port); -#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \ +#define check_io_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \ { \ int tempi = checkio(port); \ if (cpu_state.abrt) return 1; \ @@ -26,7 +26,7 @@ int checkio(int port); } \ } -#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \ +#define checkio_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \ { \ int tempi = checkio(port); \ if (cpu_state.abrt) break; \ @@ -58,14 +58,14 @@ int checkio(int port); } while (0) #define CHECK_READ(seg, low, high) \ - if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \ + if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \ { \ x86gpf("Limit check", 0); \ return 1; \ } #define CHECK_WRITE(seg, low, high) \ - if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(eflags & VM_FLAG) && ((seg)->access & 8))) \ + if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((seg)->access & 8))) \ { \ x86gpf("Limit check", 0); \ return 1; \ @@ -79,7 +79,7 @@ int checkio(int port); } -#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ +#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\ { \ x86_int(6); \ return 1; \ diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 91a2b55..bdb1aa7 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -217,21 +217,21 @@ void x86_int(int num) { if (stack32) { - writememw(ss,ESP-2,flags); + writememw(ss,ESP-2,cpu_state.flags); writememw(ss,ESP-4,CS); writememw(ss,ESP-6,cpu_state.pc); ESP-=6; } else { - writememw(ss,((SP-2)&0xFFFF),flags); + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); writememw(ss,((SP-4)&0xFFFF),CS); writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); SP-=6; } - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); @@ -264,21 +264,21 @@ void x86_int_sw(int num) { if (stack32) { - writememw(ss,ESP-2,flags); + writememw(ss,ESP-2,cpu_state.flags); writememw(ss,ESP-4,CS); writememw(ss,ESP-6,cpu_state.pc); ESP-=6; } else { - writememw(ss,((SP-2)&0xFFFF),flags); + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); writememw(ss,((SP-4)&0xFFFF),CS); writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); SP-=6; } - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); @@ -303,13 +303,13 @@ int x86_int_sw_rm(int num) if (cpu_state.abrt) return 1; - writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; } + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; } writememw(ss,((SP-4)&0xFFFF),CS); writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; } SP-=6; - eflags &= ~VIF_FLAG; - flags &= ~T_FLAG; + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc = new_pc; loadcs(new_cs); oxpc=cpu_state.pc; @@ -507,7 +507,7 @@ int dontprint=0; #include "386_ops.h" -#define CACHE_ON() (!(cr0 & (1 << 30)) /*&& (cr0 & 1)*/ && !(flags & T_FLAG)) +#define CACHE_ON() (!(cr0 & (1 << 30)) /*&& (cr0 & 1)*/ && !(cpu_state.flags & T_FLAG)) //#define CACHE_ON() 0 static int cycles_main = 0; @@ -560,7 +560,7 @@ void exec386_dynarec(int cycs) // fatal("Dead with cache off\n"); if (!cpu_state.abrt) { - trap = flags & T_FLAG; + trap = cpu_state.flags & T_FLAG; opcode = fetchdat & 0xFF; fetchdat >>= 8; @@ -720,7 +720,7 @@ inrecomp=0; // fatal("Dead\n"); if (!cpu_state.abrt) { - trap = flags & T_FLAG; + trap = cpu_state.flags & T_FLAG; opcode = fetchdat & 0xFF; fetchdat >>= 8; @@ -800,7 +800,7 @@ inrecomp=0; if (!cpu_state.abrt) { - trap = flags & T_FLAG; + trap = cpu_state.flags & T_FLAG; opcode = fetchdat & 0xFF; fetchdat >>= 8; @@ -892,13 +892,13 @@ inrecomp=0; } else { - writememw(ss,(SP-2)&0xFFFF,flags); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr = (1 << 2) + idt.base; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); } @@ -916,7 +916,7 @@ inrecomp=0; nmi = 0; } } - else if ((flags&I_FLAG) && pic_intpending) + else if ((cpu_state.flags & I_FLAG) && pic_intpending) { temp=picinterrupt(); if (temp!=0xFF) @@ -930,13 +930,13 @@ inrecomp=0; } else { - writememw(ss,(SP-2)&0xFFFF,flags); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr=temp<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); diff --git a/src/808x.c b/src/808x.c index eaeffa6..7368a4e 100644 --- a/src/808x.c +++ b/src/808x.c @@ -570,11 +570,11 @@ void dumpregs() printf("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); else printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); - printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); + printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,cpu_state.flags); printf("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); printf("%i ins\n",ins); if (is386) - printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); + printf("In %s mode\n",(msw&1)?((cpu_state.eflags&VM_FLAG)?"V86":"protected"):"real"); else printf("In %s mode\n",(msw&1)?"protected":"real"); printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,cpu_state.seg_cs.limit,cpu_state.seg_cs.access, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high); @@ -627,7 +627,7 @@ void resetx86() cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; - eflags=0; + cpu_state.eflags=0; cgate32=0; if (AT) { @@ -643,7 +643,7 @@ void resetx86() } idt.base = 0; idt.limit = is386 ? 0x03FF : 0xFFFF; - flags=2; + cpu_state.flags=2; makeznptable(); resetreadlookup(); makemod1table(); @@ -676,7 +676,7 @@ void softresetx86() cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; - eflags=0; + cpu_state.eflags=0; cgate32=0; cpu_hasCX8 = 0; if (AT) @@ -692,7 +692,7 @@ void softresetx86() rammask = 0xfffff; } //rammask=0xFFFFFFFF; - flags=2; + cpu_state.flags=2; idt.base = 0; idt.limit = is386 ? 0x03FF : 0xFFFF; x86seg_reset(); @@ -701,123 +701,154 @@ void softresetx86() static void setznp8(uint8_t val) { - flags&=~0xC4; - flags|=znptable8[val]; + cpu_state.flags &= ~0xC4; + cpu_state.flags |= znptable8[val]; } static void setznp16(uint16_t val) { - flags&=~0xC4; - flags|=znptable16[val]; + cpu_state.flags &= ~0xC4; + cpu_state.flags |= znptable16[val]; } static void setadd8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a+(uint16_t)b; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + uint16_t c = (uint16_t)a + (uint16_t)b; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c&0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setadd8nc(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a+(uint16_t)b; - flags&=~0x8D4; - flags|=znptable8[c&0xFF]; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + uint16_t c = (uint16_t)a + (uint16_t)b; + cpu_state.flags &= ~0x8D4; + cpu_state.flags |= znptable8[c&0xFF]; + if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setadc8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a+(uint16_t)b+tempc; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + uint16_t c = (uint16_t)a + (uint16_t)b+tempc; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c&0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setadd16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + uint32_t c = (uint32_t)a + (uint32_t)b; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable16[c&0xFFFF]; + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setadd16nc(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D4; - flags|=znptable16[c&0xFFFF]; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + uint32_t c = (uint32_t)a + (uint32_t)b; + cpu_state.flags &= ~0x8D4; + cpu_state.flags |= znptable16[c&0xFFFF]; + if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setadc16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + uint32_t c = (uint32_t)a + (uint32_t)b+tempc; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable16[c&0xFFFF]; + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setsub8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a-(uint16_t)b; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + uint16_t c = (uint16_t)a - (uint16_t)b; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c&0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x80) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setsub8nc(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a-(uint16_t)b; - flags&=~0x8D4; - flags|=znptable8[c&0xFF]; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + uint16_t c = (uint16_t)a - (uint16_t)b; + cpu_state.flags &= ~0x8D4; + cpu_state.flags |= znptable8[c&0xFF]; + if ((a ^ b) & (a ^ c) & 0x80) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setsbc8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc); + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c&0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x80) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setsub16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; -// if (output) printf("%04X %04X %i\n",a^b,a^c,flags&V_FLAG); - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + uint32_t c = (uint32_t)a - (uint32_t)b; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable16[c&0xFFFF]; + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x8000) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setsub16nc(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D4; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + uint32_t c = (uint32_t)a - (uint32_t)b; + cpu_state.flags &= ~0x8D4; + cpu_state.flags |= (znptable16[c&0xFFFF]&~4); + cpu_state.flags |= (znptable8[c&0xFF]&4); + if ((a ^ b) & (a ^ c) & 0x8000) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static void setsbc16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); - flags&=~0x8D5; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc); + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= (znptable16[c&0xFFFF]&~4); + cpu_state.flags |= (znptable8[c&0xFF]&4); + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x8000) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } int current_diff = 0; @@ -893,8 +924,8 @@ void rep(int fv) { temp2=readmemb(ds+SI); outb(DX,temp2); - if (flags&D_FLAG) SI--; - else SI++; + if (cpu_state.flags & D_FLAG) SI--; + else SI++; c--; cycles-=5; } @@ -907,8 +938,8 @@ void rep(int fv) temp2=readmemb(ds+SI); writememb(es+DI,temp2); // if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } + if (cpu_state.flags & D_FLAG) { DI--; SI--; } + else { DI++; SI++; } c--; cycles-=17; clockhardware(); @@ -925,8 +956,8 @@ void rep(int fv) memcycs=0; tempw=readmemw(ds,SI); writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } + if (cpu_state.flags & D_FLAG) { DI-=2; SI-=2; } + else { DI+=2; SI+=2; } c--; cycles-=17; clockhardware(); @@ -938,43 +969,43 @@ void rep(int fv) // } break; case 0xA6: /*REP CMPSB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) + if (fv) cpu_state.flags |= Z_FLAG; + else cpu_state.flags &= ~Z_FLAG; + while ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)) && !IRQTEST) { memcycs=0; temp=readmemb(ds+SI); temp2=readmemb(es+DI); // printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } + if (cpu_state.flags & D_FLAG) { DI--; SI--; } + else { DI++; SI++; } c--; cycles -= 30; setsub8(temp,temp2); clockhardware(); FETCHADD(30 - memcycs); } - if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; + if (IRQTEST && c>0 && (fv==((cpu_state.flags & Z_FLAG)?1:0))) cpu_state.pc=ipc; // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; break; case 0xA7: /*REP CMPSW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) + if (fv) cpu_state.flags |= Z_FLAG; + else cpu_state.flags &= ~Z_FLAG; + while ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)) && !IRQTEST) { memcycs=0; tempw=readmemw(ds,SI); tempw2=readmemw(es,DI); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } + if (cpu_state.flags & D_FLAG) { DI-=2; SI-=2; } + else { DI+=2; SI+=2; } c--; cycles -= 30; setsub16(tempw,tempw2); clockhardware(); FETCHADD(30 - memcycs); } - if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; + if (IRQTEST && c>0 && (fv==((cpu_state.flags & Z_FLAG)?1:0))) cpu_state.pc=ipc; // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; // if (firstrepcycle) printf("REP CMPSW %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2); @@ -984,8 +1015,8 @@ void rep(int fv) { memcycs=0; writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; c--; cycles -= 10; clockhardware(); @@ -1000,8 +1031,8 @@ void rep(int fv) { memcycs=0; writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; c--; cycles -= 10; clockhardware(); @@ -1015,8 +1046,8 @@ void rep(int fv) if (c>0) { temp2=readmemb(ds+SI); - if (flags&D_FLAG) SI--; - else SI++; + if (cpu_state.flags & D_FLAG) SI--; + else SI++; c--; cycles-=4; } @@ -1027,8 +1058,8 @@ void rep(int fv) if (c>0) { tempw2=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; + if (cpu_state.flags & D_FLAG) SI -= 2; + else SI += 2; c--; cycles-=4; } @@ -1036,37 +1067,37 @@ void rep(int fv) else firstrepcycle=1; break; case 0xAE: /*REP SCASB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + if (fv) cpu_state.flags |= Z_FLAG; + else cpu_state.flags &= ~Z_FLAG; + if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { temp2=readmemb(es+DI); // if (output) printf("SCASB %02X %c %02X %05X ",temp2,temp2,AL,es+DI); setsub8(AL,temp2); // if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2); - if (flags&D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; c--; cycles -= 15; } //if (output) printf("%i %i %i %i\n",c,(c>0),(fv==((flags&Z_FLAG)?1:0)),((c>0) && (fv==((flags&Z_FLAG)?1:0)))); - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } + if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } else firstrepcycle=1; // cycles-=120; break; case 0xAF: /*REP SCASW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) + if (fv) cpu_state.flags |= Z_FLAG; + else cpu_state.flags &= ~Z_FLAG; + if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { tempw=readmemw(es,DI); setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; c--; cycles -= 15; } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } + if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } else firstrepcycle=1; break; default: @@ -1125,8 +1156,8 @@ void execx86(int cycs) cpu_state.oldpc = cpu_state.pc; opcodestart: opcode=FETCH(); - tempc=flags&C_FLAG; - trap=flags&T_FLAG; + tempc = cpu_state.flags & C_FLAG; + trap = cpu_state.flags & T_FLAG; cpu_state.pc--; // output=1; // if (output) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X\n",cs>>4,pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags&~0x200,rmdat); @@ -1135,7 +1166,7 @@ void execx86(int cycs) { // if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle) // { - if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); + if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,cpu_state.flags, ins, ram, ram[0x1a925]); skipnextprint=0; // ins++; // } @@ -1215,7 +1246,7 @@ void execx86(int cycs) temp=geteab(); temp|=getr8(cpu_reg); setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; @@ -1224,7 +1255,7 @@ void execx86(int cycs) tempw=geteaw(); tempw|=cpu_state.regs[cpu_reg].w; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; @@ -1233,7 +1264,7 @@ void execx86(int cycs) temp=geteab(); temp|=getr8(cpu_reg); setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?3:13); break; @@ -1242,20 +1273,20 @@ void execx86(int cycs) tempw=geteaw(); tempw|=cpu_state.regs[cpu_reg].w; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x0C: /*OR AL,#8*/ AL|=FETCH(); setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x0D: /*OR AX,#16*/ AX|=getword(); setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; @@ -1403,7 +1434,7 @@ void execx86(int cycs) temp=geteab(); temp&=getr8(cpu_reg); setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; @@ -1412,7 +1443,7 @@ void execx86(int cycs) tempw=geteaw(); tempw&=cpu_state.regs[cpu_reg].w; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; @@ -1421,7 +1452,7 @@ void execx86(int cycs) temp=geteab(); temp&=getr8(cpu_reg); setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?3:13); break; @@ -1430,20 +1461,20 @@ void execx86(int cycs) tempw=geteaw(); tempw&=cpu_state.regs[cpu_reg].w; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x24: /*AND AL,#8*/ AL&=FETCH(); setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x25: /*AND AX,#16*/ AX&=getword(); setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; @@ -1457,19 +1488,20 @@ void execx86(int cycs) // break; case 0x27: /*DAA*/ - if ((flags&A_FLAG) || ((AL&0xF)>9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { - tempi=((uint16_t)AL)+6; - AL+=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; + tempi = ((uint16_t)AL) + 6; + AL += 6; + cpu_state.flags |= A_FLAG; + if (tempi & 0x100) + cpu_state.flags |= C_FLAG; } // else // flags&=~A_FLAG; - if ((flags&C_FLAG) || (AL>0x9F)) + if ((cpu_state.flags & C_FLAG) || (AL > 0x9F)) { - AL+=0x60; - flags|=C_FLAG; + AL += 0x60; + cpu_state.flags |= C_FLAG; } // else // flags&=~C_FLAG; @@ -1531,19 +1563,20 @@ void execx86(int cycs) cycles-=4; goto opcodestart; case 0x2F: /*DAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { - tempi=((uint16_t)AL)-6; - AL-=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; + tempi = ((uint16_t)AL) - 6; + AL -= 6; + cpu_state.flags |= A_FLAG; + if (tempi & 0x100) + cpu_state.flags |= C_FLAG; } // else // flags&=~A_FLAG; - if ((flags&C_FLAG)||(AL>0x9F)) + if ((cpu_state.flags & C_FLAG) || (AL > 0x9F)) { - AL-=0x60; - flags|=C_FLAG; + AL -= 0x60; + cpu_state.flags |= C_FLAG; } // else // flags&=~C_FLAG; @@ -1555,7 +1588,7 @@ void execx86(int cycs) temp=geteab(); temp^=getr8(cpu_reg); setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; @@ -1564,7 +1597,7 @@ void execx86(int cycs) tempw=geteaw(); tempw^=cpu_state.regs[cpu_reg].w; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; @@ -1573,7 +1606,7 @@ void execx86(int cycs) temp=geteab(); temp^=getr8(cpu_reg); setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?3:13); break; @@ -1582,20 +1615,20 @@ void execx86(int cycs) tempw=geteaw(); tempw^=cpu_state.regs[cpu_reg].w; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x34: /*XOR AL,#8*/ AL^=FETCH(); setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x35: /*XOR AX,#16*/ AX^=getword(); setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; @@ -1609,16 +1642,16 @@ void execx86(int cycs) // break; case 0x37: /*AAA*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) + if ((cpu_state.flags & A_FLAG)||((AL & 0xF) > 9)) { - AL+=6; + AL += 6; AH++; - flags|=(A_FLAG|C_FLAG); + cpu_state.flags |= (A_FLAG|C_FLAG); } else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; + cpu_state.flags &= ~(A_FLAG|C_FLAG); + AL &= 0xF; + cycles -= 8; break; case 0x38: /*CMP 8,reg*/ @@ -1670,16 +1703,16 @@ void execx86(int cycs) // break; case 0x3F: /*AAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { - AL-=6; + AL -= 6; AH--; - flags|=(A_FLAG|C_FLAG); + cpu_state.flags |= (A_FLAG|C_FLAG); } else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; + cpu_state.flags &= ~(A_FLAG|C_FLAG); + AL &= 0xF; + cycles -= 8; break; case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ @@ -1714,105 +1747,105 @@ void execx86(int cycs) case 0x60: /*JO alias*/ case 0x70: /*JO*/ offset=(int8_t)FETCH(); - if (flags&V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (cpu_state.flags & V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x61: /*JNO alias*/ case 0x71: /*JNO*/ offset=(int8_t)FETCH(); - if (!(flags&V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (!(cpu_state.flags & V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x62: /*JB alias*/ case 0x72: /*JB*/ offset=(int8_t)FETCH(); - if (flags&C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (cpu_state.flags & C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x63: /*JNB alias*/ case 0x73: /*JNB*/ offset=(int8_t)FETCH(); - if (!(flags&C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (!(cpu_state.flags & C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x64: /*JE alias*/ case 0x74: /*JE*/ offset=(int8_t)FETCH(); - if (flags&Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (cpu_state.flags & Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x65: /*JNE alias*/ case 0x75: /*JNE*/ offset=(int8_t)FETCH(); cycles-=4; - if (!(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (!(cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } break; case 0x66: /*JBE alias*/ case 0x76: /*JBE*/ offset=(int8_t)FETCH(); - if (flags&(C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (cpu_state.flags & (C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x67: /*JNBE alias*/ case 0x77: /*JNBE*/ offset=(int8_t)FETCH(); - if (!(flags&(C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (!(cpu_state.flags & (C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x68: /*JS alias*/ case 0x78: /*JS*/ offset=(int8_t)FETCH(); - if (flags&N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (cpu_state.flags & N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x69: /*JNS alias*/ case 0x79: /*JNS*/ offset=(int8_t)FETCH(); - if (!(flags&N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (!(cpu_state.flags & N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6A: /*JP alias*/ case 0x7A: /*JP*/ offset=(int8_t)FETCH(); - if (flags&P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (cpu_state.flags & P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6B: /*JNP alias*/ case 0x7B: /*JNP*/ offset=(int8_t)FETCH(); - if (!(flags&P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (!(cpu_state.flags & P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6C: /*JL alias*/ case 0x7C: /*JL*/ offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; + temp=(cpu_state.flags & N_FLAG)?1:0; + temp2=(cpu_state.flags & V_FLAG)?1:0; if (temp!=temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6D: /*JNL alias*/ case 0x7D: /*JNL*/ offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; + temp=(cpu_state.flags & N_FLAG)?1:0; + temp2=(cpu_state.flags & V_FLAG)?1:0; if (temp==temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6E: /*JLE alias*/ case 0x7E: /*JLE*/ offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + temp=(cpu_state.flags & N_FLAG)?1:0; + temp2=(cpu_state.flags & V_FLAG)?1:0; + if ((cpu_state.flags & Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6F: /*JNLE alias*/ case 0x7F: /*JNLE*/ offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + temp=(cpu_state.flags & N_FLAG)?1:0; + temp2=(cpu_state.flags & V_FLAG)?1:0; + if (!((cpu_state.flags & Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; @@ -1830,7 +1863,7 @@ void execx86(int cycs) case 0x08: /*OR b,#8*/ temp|=temp2; setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?4:23); break; @@ -1849,7 +1882,7 @@ void execx86(int cycs) case 0x20: /*AND b,#8*/ temp&=temp2; setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?4:23); break; @@ -1861,7 +1894,7 @@ void execx86(int cycs) case 0x30: /*XOR b,#8*/ temp^=temp2; setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?4:23); break; @@ -1892,7 +1925,7 @@ void execx86(int cycs) case 0x08: /*OR w,#16*/ tempw|=tempw2; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; @@ -1906,7 +1939,7 @@ void execx86(int cycs) case 0x20: /*AND w,#16*/ tempw&=tempw2; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; @@ -1925,7 +1958,7 @@ void execx86(int cycs) case 0x30: /*XOR w,#16*/ tempw^=tempw2; setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; @@ -1959,7 +1992,7 @@ void execx86(int cycs) tempw|=tempw2; setznp16(tempw); seteaw(tempw); - flags&=~(C_FLAG|A_FLAG|V_FLAG); + cpu_state.flags &= ~(C_FLAG|A_FLAG|V_FLAG); cycles-=((cpu_mod==3)?4:23); break; case 0x10: /*ADC w,#8*/ @@ -1981,7 +2014,7 @@ void execx86(int cycs) setznp16(tempw); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); + cpu_state.flags &= ~(C_FLAG|A_FLAG|V_FLAG); break; case 0x28: /*SUB w,#8*/ setsub16(tempw,tempw2); @@ -1994,7 +2027,7 @@ void execx86(int cycs) setznp16(tempw); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); + cpu_state.flags &= ~(C_FLAG|A_FLAG|V_FLAG); break; case 0x38: /*CMP w,#8*/ setsub16(tempw,tempw2); @@ -2013,7 +2046,7 @@ void execx86(int cycs) temp=geteab(); temp2=getr8(cpu_reg); setznp8(temp&temp2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?3:13); break; case 0x85: /*TEST w,reg*/ @@ -2021,7 +2054,7 @@ void execx86(int cycs) tempw=geteaw(); tempw2=cpu_state.regs[cpu_reg].w; setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?3:13); break; case 0x86: /*XCHG b,reg*/ @@ -2171,22 +2204,22 @@ void execx86(int cycs) break; case 0x9C: /*PUSHF*/ if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); + writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000); SP-=2; cycles-=14; break; case 0x9D: /*POPF*/ if (cpu_state.ssegs) ss=oldss; - flags=readmemw(ss,SP)&0xFFF; + cpu_state.flags = readmemw(ss,SP) & 0xFFF; SP+=2; cycles-=12; break; case 0x9E: /*SAHF*/ - flags=(flags&0xFF00)|AH; + cpu_state.flags = (cpu_state.flags & 0xFF00) | AH; cycles-=4; break; case 0x9F: /*LAHF*/ - AH=flags&0xFF; + AH = cpu_state.flags & 0xFF; cycles-=4; break; @@ -2216,23 +2249,23 @@ void execx86(int cycs) case 0xA4: /*MOVSB*/ temp=readmemb(ds+SI); writememb(es+DI,temp); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } + if (cpu_state.flags & D_FLAG) { DI--; SI--; } + else { DI++; SI++; } cycles-=18; break; case 0xA5: /*MOVSW*/ tempw=readmemw(ds,SI); writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } + if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } + else { DI += 2; SI += 2; } cycles-=18; break; case 0xA6: /*CMPSB*/ temp =readmemb(ds+SI); temp2=readmemb(es+DI); setsub8(temp,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } + if (cpu_state.flags & D_FLAG) { DI--; SI--; } + else { DI++; SI++; } cycles-=30; break; case 0xA7: /*CMPSW*/ @@ -2240,60 +2273,60 @@ void execx86(int cycs) tempw2=readmemw(es,DI); // printf("CMPSW %04X %04X\n",tempw,tempw2); setsub16(tempw,tempw2); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } + if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } + else { DI += 2; SI += 2; } cycles-=30; break; case 0xA8: /*TEST AL,#8*/ temp=FETCH(); setznp8(AL&temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=5; break; case 0xA9: /*TEST AX,#16*/ tempw=getword(); setznp16(AX&tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=5; break; case 0xAA: /*STOSB*/ writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; cycles-=11; break; case 0xAB: /*STOSW*/ writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; cycles-=11; break; case 0xAC: /*LODSB*/ AL=readmemb(ds+SI); // printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI); - if (flags&D_FLAG) SI--; - else SI++; + if (cpu_state.flags & D_FLAG) SI--; + else SI++; cycles-=16; break; case 0xAD: /*LODSW*/ // if (times) printf("LODSW %04X:%04X\n",cs>>4,pc); AX=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; + if (cpu_state.flags & D_FLAG) SI -= 2; + else SI += 2; cycles-=16; break; case 0xAE: /*SCASB*/ temp=readmemb(es+DI); setsub8(AL,temp); - if (flags&D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; cycles-=19; break; case 0xAF: /*SCASW*/ tempw=readmemw(es,DI); setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; cycles-=19; break; @@ -2408,13 +2441,13 @@ void execx86(int cycs) break; case 0xCC: /*INT 3*/ if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); + writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000); + writememw(ss, ((SP-4)&0xFFFF), CS); + writememw(ss, ((SP-6)&0xFFFF), cpu_state.pc); SP-=6; addr=3<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; // printf("CC %04X:%04X ",CS,pc); cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); @@ -2428,10 +2461,10 @@ void execx86(int cycs) temp=FETCH(); if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - flags&=~T_FLAG; + writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000); + writememw(ss, ((SP-4)&0xFFFF), CS); + writememw(ss, ((SP-6)&0xFFFF), cpu_state.pc); + cpu_state.flags &= ~T_FLAG; SP-=6; addr=temp<<2; cpu_state.pc=readmemw(0,addr); @@ -2448,7 +2481,7 @@ void execx86(int cycs) cpu_state.pc=readmemw(ss,SP); // printf("CF\n"); loadcs(readmemw(ss,((SP+2)&0xFFFF))); - flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF; + cpu_state.flags = readmemw(ss,((SP+4)&0xFFFF))&0xFFF; SP+=6; cycles-=44; FETCHCLEAR(); @@ -2460,83 +2493,85 @@ void execx86(int cycs) switch (rmdat&0x38) { case 0x00: /*ROL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp&0x80) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp<<=1; - if (flags&C_FLAG) temp|=1; + if (cpu_state.flags & C_FLAG) + temp |= 1; seteab(temp); // setznp8(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags&C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x08: /*ROR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp>>=1; - if (flags&C_FLAG) temp|=0x80; + if (cpu_state.flags & C_FLAG) + temp |= 0x80; seteab(temp); // setznp8(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x10: /*RCL b,1*/ - temp2=flags&C_FLAG; - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; + temp2 = cpu_state.flags & C_FLAG; + if (temp&0x80) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp<<=1; if (temp2) temp|=1; seteab(temp); // setznp8(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x18: /*RCR b,1*/ - temp2=flags&C_FLAG; - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; + temp2 = cpu_state.flags & C_FLAG; + if (temp&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp>>=1; if (temp2) temp|=0x80; seteab(temp); // setznp8(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x20: case 0x30: /*SHL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((temp^(temp<<1))&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; + if (temp&0x80) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; + if ((temp^(temp<<1))&0x80) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; temp<<=1; seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x28: /*SHR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (temp&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; + if (temp&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; + if (temp&0x80) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; temp>>=1; seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x38: /*SAR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp>>=1; if (temp&0x40) temp|=0x80; seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; + cpu_state.flags |= A_FLAG; + cpu_state.flags &= ~V_FLAG; break; // default: @@ -2552,83 +2587,83 @@ void execx86(int cycs) switch (rmdat&0x38) { case 0x00: /*ROL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; + if (tempw&0x8000) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw<<=1; - if (flags&C_FLAG) tempw|=1; + if (cpu_state.flags & C_FLAG) tempw|=1; seteaw(tempw); // setznp16(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x08: /*ROR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if (tempw&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw>>=1; - if (flags&C_FLAG) tempw|=0x8000; + if (cpu_state.flags & C_FLAG) tempw|=0x8000; seteaw(tempw); // setznp16(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x10: /*RCL w,1*/ - temp2=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; + temp2 = cpu_state.flags & C_FLAG; + if (tempw&0x8000) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw<<=1; if (temp2) tempw|=1; seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x18: /*RCR w,1*/ - temp2=flags&C_FLAG; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; + temp2 = cpu_state.flags & C_FLAG; + if (tempw&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw>>=1; if (temp2) tempw|=0x8000; seteaw(tempw); // setznp16(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x20: case 0x30: /*SHL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; + if (tempw&0x8000) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; + if ((tempw^(tempw<<1))&0x8000) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; tempw<<=1; seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x28: /*SHR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (tempw&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; + if (tempw&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; + if (tempw&0x8000) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; tempw>>=1; seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x38: /*SAR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if (tempw&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw>>=1; if (tempw&0x4000) tempw|=0x8000; seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; + cpu_state.flags |= A_FLAG; + cpu_state.flags &= ~V_FLAG; break; // default: @@ -2655,12 +2690,12 @@ void execx86(int cycs) c--; cycles-=4; } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp2) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; seteab(temp); // setznp8(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x08: /*ROR b,CL*/ @@ -2672,40 +2707,40 @@ void execx86(int cycs) c--; cycles-=4; } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp2) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x10: /*RCL b,CL*/ // printf("RCL %i %02X %02X\n",c,CL,temp); while (c>0) { - templ=flags&C_FLAG; + templ=cpu_state.flags & C_FLAG; temp2=temp&0x80; temp<<=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp2) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; if (templ) temp|=1; c--; cycles-=4; } // printf("Now %02X\n",temp); seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x18: /*RCR b,CL*/ while (c>0) { - templ=flags&C_FLAG; + templ=cpu_state.flags & C_FLAG; temp2=temp&1; temp>>=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp2) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; if (templ) temp|=0x80; c--; cycles-=4; @@ -2713,49 +2748,49 @@ void execx86(int cycs) // if (temp2) flags|=C_FLAG; // else flags&=~C_FLAG; seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x20: case 0x30: /*SHL b,CL*/ if (c > 8) { temp = 0; - flags &= ~C_FLAG; + cpu_state.flags &= ~C_FLAG; } else { - if ((temp<<(c-1))&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; + if ((temp<<(c-1))&0x80) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp<<=c; } seteab(temp); setznp8(temp); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x28: /*SHR b,CL*/ if (c > 8) { temp = 0; - flags &= ~C_FLAG; + cpu_state.flags &= ~C_FLAG; } else { - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if ((temp>>(c-1))&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; temp>>=c; } seteab(temp); setznp8(temp); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x38: /*SAR b,CL*/ - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if ((temp>>(c-1))&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; while (c>0) { temp>>=1; @@ -2766,7 +2801,7 @@ void execx86(int cycs) seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; // default: @@ -2793,11 +2828,11 @@ void execx86(int cycs) c--; cycles-=4; } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; + if (temp) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x08: /*ROR w,CL*/ @@ -2808,46 +2843,46 @@ void execx86(int cycs) c--; cycles-=4; } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; + if (tempw2) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x10: /*RCL w,CL*/ while (c>0) { - templ=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; + templ = cpu_state.flags & C_FLAG; + if (tempw&0x8000) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw=(tempw<<1)|templ; c--; cycles-=4; } - if (templ) flags|=C_FLAG; - else flags&=~C_FLAG; + if (templ) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x18: /*RCR w,CL*/ while (c>0) { - templ=flags&C_FLAG; + templ = cpu_state.flags & C_FLAG; tempw2=(templ&1)?0x8000:0; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if (tempw&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw=(tempw>>1)|tempw2; c--; cycles-=4; } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; + if (tempw2) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; + if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG; + else cpu_state.flags &= ~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; @@ -2855,44 +2890,44 @@ void execx86(int cycs) if (c>16) { tempw=0; - flags&=~C_FLAG; + cpu_state.flags &= ~C_FLAG; } else { - if ((tempw<<(c-1))&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; + if ((tempw<<(c-1))&0x8000) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw<<=c; } seteaw(tempw); setznp16(tempw); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x28: /*SHR w,CL*/ if (c > 16) { tempw = 0; - flags &= ~C_FLAG; + cpu_state.flags &= ~C_FLAG; } else { - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if ((tempw>>(c-1))&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; tempw>>=c; } seteaw(tempw); setznp16(tempw); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; case 0x38: /*SAR w,CL*/ tempw2=tempw&0x8000; - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; + if ((tempw>>(c-1))&1) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; while (c>0) { tempw=(tempw>>1)|tempw2; @@ -2902,7 +2937,7 @@ void execx86(int cycs) seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; + cpu_state.flags |= A_FLAG; break; // default: @@ -2927,7 +2962,7 @@ void execx86(int cycs) cycles-=60; break; case 0xD6: /*SETALC*/ - AL = (flags & C_FLAG) ? 0xff : 0; + AL = (cpu_state.flags & C_FLAG) ? 0xff : 0; cycles -= 4; break; case 0xD7: /*XLAT*/ @@ -2944,13 +2979,13 @@ void execx86(int cycs) case 0xE0: /*LOOPNE*/ offset=(int8_t)FETCH(); CX--; - if (CX && !(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (CX && !(cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=6; break; case 0xE1: /*LOOPE*/ offset=(int8_t)FETCH(); CX--; - if (CX && (flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } + if (CX && (cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=6; break; case 0xE2: /*LOOP*/ @@ -3070,7 +3105,7 @@ void execx86(int cycs) cycles-=2; break; case 0xF5: /*CMC*/ - flags^=C_FLAG; + cpu_state.flags ^= C_FLAG; cycles-=2; break; @@ -3084,7 +3119,7 @@ void execx86(int cycs) temp2=FETCH(); temp&=temp2; setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?5:11); break; case 0x10: /*NOT b*/ @@ -3101,20 +3136,20 @@ void execx86(int cycs) case 0x20: /*MUL AL,b*/ setznp8(AL); AX=AL*temp; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); + if (AX) cpu_state.flags &= ~Z_FLAG; + else cpu_state.flags |= Z_FLAG; + if (AH) cpu_state.flags |= (C_FLAG|V_FLAG); + else cpu_state.flags &= ~(C_FLAG|V_FLAG); cycles-=70; break; case 0x28: /*IMUL AL,b*/ setznp8(AL); tempws=(int)((int8_t)AL)*(int)((int8_t)temp); AX=tempws&0xFFFF; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); + if (AX) cpu_state.flags &= ~Z_FLAG; + else cpu_state.flags |= Z_FLAG; + if (AH) cpu_state.flags |= (C_FLAG|V_FLAG); + else cpu_state.flags &= ~(C_FLAG|V_FLAG); cycles-=80; break; case 0x30: /*DIV AL,b*/ @@ -3145,12 +3180,12 @@ void execx86(int cycs) else { printf("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F6 30\n"); loadcs(readmemw(0,2)); @@ -3189,12 +3224,12 @@ void execx86(int cycs) else { printf("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F6 38\n"); loadcs(readmemw(0,2)); @@ -3222,7 +3257,7 @@ void execx86(int cycs) case 0x08: tempw2=getword(); setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?5:11); break; case 0x10: /*NOT w*/ @@ -3241,18 +3276,18 @@ void execx86(int cycs) // if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ); AX=templ&0xFFFF; DX=templ>>16; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (DX) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); + if (AX|DX) cpu_state.flags &= ~Z_FLAG; + else cpu_state.flags |= Z_FLAG; + if (DX) cpu_state.flags |= (C_FLAG|V_FLAG); + else cpu_state.flags &= ~(C_FLAG|V_FLAG); cycles-=118; break; case 0x28: /*IMUL AX,w*/ setznp16(AX); // printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw)); tempws=(int)((int16_t)AX)*(int)((int16_t)tempw); - if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); + if ((tempws>>15) && ((tempws>>15)!=-1)) cpu_state.flags |= (C_FLAG|V_FLAG); + else cpu_state.flags &= ~(C_FLAG|V_FLAG); // printf("%i ",tempws); AX=tempws&0xFFFF; tempws=(uint16_t)(tempws>>16); @@ -3260,8 +3295,8 @@ void execx86(int cycs) // printf("%04X %04X\n",AX,DX); // dumpregs(); // exit(-1); - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; + if (AX|DX) cpu_state.flags &= ~Z_FLAG; + else cpu_state.flags |= Z_FLAG; cycles-=128; break; case 0x30: /*DIV AX,w*/ @@ -3277,12 +3312,12 @@ void execx86(int cycs) else { printf("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F7 30\n"); loadcs(readmemw(0,2)); @@ -3304,12 +3339,12 @@ void execx86(int cycs) else { printf("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F7 38\n"); loadcs(readmemw(0,2)); @@ -3326,48 +3361,48 @@ void execx86(int cycs) break; case 0xF8: /*CLC*/ - flags&=~C_FLAG; + cpu_state.flags &= ~C_FLAG; cycles-=2; break; case 0xF9: /*STC*/ // printf("STC %04X\n",pc); - flags|=C_FLAG; + cpu_state.flags |= C_FLAG; cycles-=2; break; case 0xFA: /*CLI*/ - flags&=~I_FLAG; + cpu_state.flags &= ~I_FLAG; // printf("CLI at %04X:%04X\n",cs>>4,pc); cycles-=3; break; case 0xFB: /*STI*/ - flags|=I_FLAG; + cpu_state.flags |= I_FLAG; // printf("STI at %04X:%04X\n",cs>>4,pc); cycles-=2; break; case 0xFC: /*CLD*/ - flags&=~D_FLAG; + cpu_state.flags &= ~D_FLAG; cycles-=2; break; case 0xFD: /*STD*/ - flags|=D_FLAG; + cpu_state.flags |= D_FLAG; cycles-=2; break; case 0xFE: /*INC/DEC b*/ fetchea(); temp=geteab(); - flags&=~V_FLAG; + cpu_state.flags &= ~V_FLAG; if (rmdat&0x38) { setsub8nc(temp,1); temp2=temp-1; - if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG; + if ((temp&0x80) && !(temp2&0x80)) cpu_state.flags |= V_FLAG; } else { setadd8nc(temp,1); temp2=temp+1; - if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG; + if ((temp2&0x80) && !(temp&0x80)) cpu_state.flags |= V_FLAG; } // setznp8(temp2); seteab(temp2); @@ -3499,16 +3534,16 @@ void execx86(int cycs) clockhardware(); - if (trap && (flags&T_FLAG) && !noint) + if (trap && (cpu_state.flags & T_FLAG) && !noint) { // printf("TRAP!!! %04X:%04X\n",CS,pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr=1<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); FETCHCLEAR(); @@ -3516,13 +3551,13 @@ void execx86(int cycs) else if (nmi && nmi_enable && nmi_mask) { // output = 3; - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr=2<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); FETCHCLEAR(); @@ -3534,13 +3569,13 @@ void execx86(int cycs) if (temp!=0xFF) { if (inhlt) cpu_state.pc++; - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; addr=temp<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); // printf("INT INT INT\n"); loadcs(readmemw(0,addr+2)); @@ -3548,7 +3583,7 @@ void execx86(int cycs) // printf("INTERRUPT\n"); } } - takeint = (flags&I_FLAG) && (pic.pend&~pic.mask); + takeint = (cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask); if (noint) noint=0; ins++; diff --git a/src/codegen.c b/src/codegen.c index dfa9ea4..ba9c06a 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -48,7 +48,7 @@ void codegen_generate_reset() void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg) { /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (eflags & VM_FLAG)) + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) return; /*CS and SS must always be valid*/ if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) @@ -65,7 +65,7 @@ void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg) void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) { /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (eflags & VM_FLAG)) + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) return; /*CS and SS must always be valid*/ if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index 1d677d2..c5209c1 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -159,7 +159,7 @@ uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((msw&1) && !(eflags&VM_FLAG)) + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) return 0; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -184,7 +184,7 @@ uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((msw&1) && !(eflags&VM_FLAG)) + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) return 0; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -212,7 +212,7 @@ uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 { uint16_t offset; - if ((msw&1) && !(eflags&VM_FLAG)) + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) return 0; offset = fastreadw(cs + op_pc); @@ -240,7 +240,7 @@ uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 { uint16_t offset; - if ((msw&1) && !(eflags&VM_FLAG)) + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) return 0; offset = fastreadw(cs + op_pc); diff --git a/src/ibm.h b/src/ibm.h index c829b51..e6488e4 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -188,6 +188,8 @@ struct uint32_t l; uint16_t w; } CR0; + + uint16_t flags, eflags; } cpu_state; #define cycles cpu_state._cycles @@ -214,7 +216,6 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128); #define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128) -uint16_t flags,eflags; uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; extern int ins,output; @@ -273,7 +274,7 @@ uint32_t dr[8]; #define CR4_PVI (1 << 1) #define CR4_PSE (1 << 4) -#define IOPL ((flags>>12)&3) +#define IOPL ((cpu_state.flags >> 12) & 3) #define IOPLp ((!(msw&1)) || (CPL<=IOPL)) //#define IOPLp 1 diff --git a/src/x86.h b/src/x86.h index 1c15e1f..195f52a 100644 --- a/src/x86.h +++ b/src/x86.h @@ -55,7 +55,7 @@ extern uint16_t *mod1add[2][8]; extern uint32_t *mod1seg[8]; -#define IRQTEST ((flags&I_FLAG) && (pic.pend&~pic.mask) && !noint) +#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) extern int cgate32; diff --git a/src/x86_flags.h b/src/x86_flags.h index 3fa9cc5..e7c2cc2 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -66,7 +66,7 @@ static inline int ZF_SET() return !cpu_state.flags_res; case FLAGS_UNKNOWN: - return flags & Z_FLAG; + return cpu_state.flags & Z_FLAG; } return 0; } @@ -106,7 +106,7 @@ static inline int NF_SET() return cpu_state.flags_res & 0x80000000; case FLAGS_UNKNOWN: - return flags & N_FLAG; + return cpu_state.flags & N_FLAG; } return 0; } @@ -142,7 +142,7 @@ static inline int PF_SET() return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; case FLAGS_UNKNOWN: - return flags & P_FLAG; + return cpu_state.flags & P_FLAG; } return 0; } @@ -194,7 +194,7 @@ static inline int VF_SET() return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000)); case FLAGS_UNKNOWN: - return flags & V_FLAG; + return cpu_state.flags & V_FLAG; } return 0; } @@ -234,7 +234,7 @@ static inline int AF_SET() return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10; case FLAGS_UNKNOWN: - return flags & A_FLAG; + return cpu_state.flags & A_FLAG; } return 0; } @@ -286,7 +286,7 @@ static inline int CF_SET() case FLAGS_INC16: case FLAGS_INC32: case FLAGS_UNKNOWN: - return flags & C_FLAG; + return cpu_state.flags & C_FLAG; } return 0; } @@ -309,7 +309,7 @@ static inline void flags_rebuild() if (ZF_SET()) tempf |= Z_FLAG; if (NF_SET()) tempf |= N_FLAG; if (VF_SET()) tempf |= V_FLAG; - flags = (flags & ~0x8d5) | tempf; + cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf; cpu_state.flags_op = FLAGS_UNKNOWN; } } @@ -324,9 +324,9 @@ static inline void flags_rebuild_c() if (cpu_state.flags_op != FLAGS_UNKNOWN) { if (CF_SET()) - flags |= C_FLAG; + cpu_state.flags |= C_FLAG; else - flags &= ~C_FLAG; + cpu_state.flags &= ~C_FLAG; } } @@ -447,67 +447,85 @@ static inline void setsub32nc(uint32_t a, uint32_t b) static inline void setadc8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a+(uint16_t)b+tempc; + uint16_t c = (uint16_t)a + (uint16_t)b + tempc; cpu_state.flags_op = FLAGS_UNKNOWN; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c&0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static inline void setadc16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; + uint32_t c = (uint32_t)a + (uint32_t)b + tempc; cpu_state.flags_op = FLAGS_UNKNOWN; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable16[c&0xFFFF]; + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static inline void setsbc8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); + uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc); cpu_state.flags_op = FLAGS_UNKNOWN; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c&0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x80) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static inline void setsbc16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); + uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc); cpu_state.flags_op = FLAGS_UNKNOWN; - flags&=~0x8D5; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= (znptable16[c&0xFFFF] & ~4); + cpu_state.flags |= (znptable8[c&0xFF] & 4); + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x8000) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } static inline void setadc32(uint32_t a, uint32_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; + uint32_t c = (uint32_t)a + (uint32_t)b + tempc; cpu_state.flags_op = FLAGS_UNKNOWN; - flags&=~0x8D5; - flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); - flags|=(znptable8[c&0xFF]&P_FLAG); - if ((ca) || (c==a && tempc)) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG; - if (((a&0xF)-((b&0xF)+tempc))&0x10) flags|=A_FLAG; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= ((c & 0x80000000) ? N_FLAG : ((!c) ? Z_FLAG : 0)); + cpu_state.flags |= (znptable8[c&0xFF] & P_FLAG); + if ((c > a) || (c == a && tempc)) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x80000000) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - ((b & 0xF) + tempc)) & 0x10) + cpu_state.flags |= A_FLAG; } diff --git a/src/x86_ops_atomic.h b/src/x86_ops_atomic.h index d74c30e..06a33e2 100644 --- a/src/x86_ops_atomic.h +++ b/src/x86_ops_atomic.h @@ -141,9 +141,9 @@ static int opCMPXCHG8B_a16(uint32_t fetchdat) if (cpu_state.abrt) return 0; flags_rebuild(); if (temp == temp2 && temp_hi == temp2_hi) - flags |= Z_FLAG; + cpu_state.flags |= Z_FLAG; else - flags &= ~Z_FLAG; + cpu_state.flags &= ~Z_FLAG; cycles -= (cpu_mod == 3) ? 6 : 10; return 0; } @@ -173,9 +173,9 @@ static int opCMPXCHG8B_a32(uint32_t fetchdat) if (cpu_state.abrt) return 0; flags_rebuild(); if (temp == temp2 && temp_hi == temp2_hi) - flags |= Z_FLAG; + cpu_state.flags |= Z_FLAG; else - flags &= ~Z_FLAG; + cpu_state.flags &= ~Z_FLAG; cycles -= (cpu_mod == 3) ? 6 : 10; return 0; } diff --git a/src/x86_ops_bcd.h b/src/x86_ops_bcd.h index a7eaf03..2b41394 100644 --- a/src/x86_ops_bcd.h +++ b/src/x86_ops_bcd.h @@ -1,14 +1,14 @@ static int opAAA(uint32_t fetchdat) { flags_rebuild(); - if ((flags & A_FLAG) || ((AL & 0xF) > 9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { AL += 6; AH++; - flags |= (A_FLAG | C_FLAG); + cpu_state.flags |= (A_FLAG | C_FLAG); } else - flags &= ~(A_FLAG | C_FLAG); + cpu_state.flags &= ~(A_FLAG | C_FLAG); AL &= 0xF; CLOCK_CYCLES(is486 ? 3 : 4); PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); @@ -42,14 +42,14 @@ static int opAAM(uint32_t fetchdat) static int opAAS(uint32_t fetchdat) { flags_rebuild(); - if ((flags & A_FLAG) || ((AL & 0xF) > 9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { AL -= 6; AH--; - flags |= (A_FLAG | C_FLAG); + cpu_state.flags |= (A_FLAG | C_FLAG); } else - flags &= ~(A_FLAG | C_FLAG); + cpu_state.flags &= ~(A_FLAG | C_FLAG); AL &= 0xF; CLOCK_CYCLES(is486 ? 3 : 4); PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); @@ -61,23 +61,23 @@ static int opDAA(uint32_t fetchdat) uint16_t tempw; flags_rebuild(); - if ((flags & A_FLAG) || ((AL & 0xf) > 9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { int tempi = ((uint16_t)AL) + 6; AL += 6; - flags |= A_FLAG; - if (tempi & 0x100) flags |= C_FLAG; + cpu_state.flags |= A_FLAG; + if (tempi & 0x100) cpu_state.flags |= C_FLAG; } - if ((flags & C_FLAG) || (AL > 0x9f)) + if ((cpu_state.flags & C_FLAG) || (AL > 0x9f)) { AL += 0x60; - flags |= C_FLAG; + cpu_state.flags |= C_FLAG; } - tempw = flags & (C_FLAG | A_FLAG); + tempw = cpu_state.flags & (C_FLAG | A_FLAG); setznp8(AL); flags_rebuild(); - flags |= tempw; + cpu_state.flags |= tempw; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); @@ -89,23 +89,23 @@ static int opDAS(uint32_t fetchdat) uint16_t tempw; flags_rebuild(); - if ((flags & A_FLAG) || ((AL & 0xf) > 9)) + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { int tempi = ((uint16_t)AL) - 6; AL -= 6; - flags |= A_FLAG; - if (tempi & 0x100) flags |= C_FLAG; + cpu_state.flags |= A_FLAG; + if (tempi & 0x100) cpu_state.flags |= C_FLAG; } - if ((flags & C_FLAG) || (AL > 0x9f)) + if ((cpu_state.flags & C_FLAG) || (AL > 0x9f)) { AL -= 0x60; - flags |= C_FLAG; + cpu_state.flags |= C_FLAG; } - tempw = flags & (C_FLAG | A_FLAG); + tempw = cpu_state.flags & (C_FLAG | A_FLAG); setznp8(AL); flags_rebuild(); - flags |= tempw; + cpu_state.flags |= tempw; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); diff --git a/src/x86_ops_bit.h b/src/x86_ops_bit.h index 74194f5..7261fef 100644 --- a/src/x86_ops_bit.h +++ b/src/x86_ops_bit.h @@ -7,8 +7,8 @@ static int opBT_w_r_a16(uint32_t fetchdat) cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0; temp = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 0); @@ -23,8 +23,8 @@ static int opBT_w_r_a32(uint32_t fetchdat) cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0; temp = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 1); @@ -39,8 +39,8 @@ static int opBT_l_r_a16(uint32_t fetchdat) cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0; temp = geteal(); if (cpu_state.abrt) return 1; flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 0); @@ -55,8 +55,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0; temp = geteal(); if (cpu_state.abrt) return 1; flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 1); @@ -78,8 +78,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \ seteaw(temp); if (cpu_state.abrt) return 1; \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ - else flags &= ~C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ + else cpu_state.flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 0); \ @@ -99,8 +99,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \ seteaw(temp); if (cpu_state.abrt) return 1; \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ - else flags &= ~C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ + else cpu_state.flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 1); \ @@ -120,8 +120,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \ seteal(temp); if (cpu_state.abrt) return 1; \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ - else flags &= ~C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ + else cpu_state.flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 0); \ @@ -141,8 +141,8 @@ static int opBT_l_r_a32(uint32_t fetchdat) temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \ seteal(temp); if (cpu_state.abrt) return 1; \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ - else flags &= ~C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ + else cpu_state.flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 1); \ @@ -169,8 +169,8 @@ static int opBA_w_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x20: /*BT w,imm*/ - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; @@ -191,8 +191,8 @@ static int opBA_w_a16(uint32_t fetchdat) break; } seteaw(temp); if (cpu_state.abrt) return 1; - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(6); PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; @@ -213,8 +213,8 @@ static int opBA_w_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x20: /*BT w,imm*/ - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; @@ -235,8 +235,8 @@ static int opBA_w_a32(uint32_t fetchdat) break; } seteaw(temp); if (cpu_state.abrt) return 1; - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(6); PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; @@ -258,8 +258,8 @@ static int opBA_l_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x20: /*BT w,imm*/ - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return 0; @@ -280,8 +280,8 @@ static int opBA_l_a16(uint32_t fetchdat) break; } seteal(temp); if (cpu_state.abrt) return 1; - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(6); PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); return 0; @@ -302,8 +302,8 @@ static int opBA_l_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x20: /*BT w,imm*/ - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return 0; @@ -324,8 +324,8 @@ static int opBA_l_a32(uint32_t fetchdat) break; } seteal(temp); if (cpu_state.abrt) return 1; - if (tempc) flags |= C_FLAG; - else flags &= ~C_FLAG; + if (tempc) cpu_state.flags |= C_FLAG; + else cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(6); PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); return 0; diff --git a/src/x86_ops_bitscan.h b/src/x86_ops_bitscan.h index 4fcc79c..98349da 100644 --- a/src/x86_ops_bitscan.h +++ b/src/x86_ops_bitscan.h @@ -4,7 +4,7 @@ if (temp) \ { \ int c; \ - flags &= ~Z_FLAG; \ + cpu_state.flags &= ~Z_FLAG; \ for (c = start; c != end; c += dir) \ { \ CLOCK_CYCLES(time); \ @@ -17,7 +17,7 @@ } \ } \ else \ - flags |= Z_FLAG; + cpu_state.flags |= Z_FLAG; static int opBSF_w_a16(uint32_t fetchdat) { diff --git a/src/x86_ops_flag.h b/src/x86_ops_flag.h index 9d3c0d7..db1dc20 100644 --- a/src/x86_ops_flag.h +++ b/src/x86_ops_flag.h @@ -1,7 +1,7 @@ static int opCMC(uint32_t fetchdat) { flags_rebuild(); - flags ^= C_FLAG; + cpu_state.flags ^= C_FLAG; CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; @@ -11,14 +11,14 @@ static int opCMC(uint32_t fetchdat) static int opCLC(uint32_t fetchdat) { flags_rebuild(); - flags &= ~C_FLAG; + cpu_state.flags &= ~C_FLAG; CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opCLD(uint32_t fetchdat) { - flags &= ~D_FLAG; + cpu_state.flags &= ~D_FLAG; CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; @@ -27,10 +27,10 @@ static int opCLI(uint32_t fetchdat) { if (!IOPLp) { - if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) || - ((eflags & VM_FLAG) && (cr4 & CR4_VME))) + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || + ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { - eflags &= ~VIF_FLAG; + cpu_state.eflags &= ~VIF_FLAG; } else { @@ -39,7 +39,7 @@ static int opCLI(uint32_t fetchdat) } } else - flags &= ~I_FLAG; + cpu_state.flags &= ~I_FLAG; CLOCK_CYCLES(3); PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); @@ -49,14 +49,14 @@ static int opCLI(uint32_t fetchdat) static int opSTC(uint32_t fetchdat) { flags_rebuild(); - flags |= C_FLAG; + cpu_state.flags |= C_FLAG; CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opSTD(uint32_t fetchdat) { - flags |= D_FLAG; + cpu_state.flags |= D_FLAG; CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; @@ -65,16 +65,16 @@ static int opSTI(uint32_t fetchdat) { if (!IOPLp) { - if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) || - ((eflags & VM_FLAG) && (cr4 & CR4_VME))) + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || + ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { - if (eflags & VIP_FLAG) + if (cpu_state.eflags & VIP_FLAG) { x86gpf(NULL,0); return 1; } else - eflags |= VIF_FLAG; + cpu_state.eflags |= VIF_FLAG; } else { @@ -83,7 +83,7 @@ static int opSTI(uint32_t fetchdat) } } else - flags |= I_FLAG; + cpu_state.flags |= I_FLAG; CPU_BLOCK_END(); @@ -95,7 +95,7 @@ static int opSTI(uint32_t fetchdat) static int opSAHF(uint32_t fetchdat) { flags_rebuild(); - flags = (flags & 0xff00) | (AH & 0xd5) | 2; + cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; CLOCK_CYCLES(3); PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); @@ -106,7 +106,7 @@ static int opSAHF(uint32_t fetchdat) static int opLAHF(uint32_t fetchdat) { flags_rebuild(); - AH = flags & 0xff; + AH = cpu_state.flags & 0xff; CLOCK_CYCLES(3); PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; @@ -114,15 +114,15 @@ static int opLAHF(uint32_t fetchdat) static int opPUSHF(uint32_t fetchdat) { - if ((eflags & VM_FLAG) && (IOPL < 3)) + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { if (cr4 & CR4_VME) { uint16_t temp; flags_rebuild(); - temp = (flags & ~I_FLAG) | 0x3000; - if (eflags & VIF_FLAG) + temp = (cpu_state.flags & ~I_FLAG) | 0x3000; + if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; PUSH_W(temp); } @@ -135,7 +135,7 @@ static int opPUSHF(uint32_t fetchdat) else { flags_rebuild(); - PUSH_W(flags); + PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); @@ -144,16 +144,16 @@ static int opPUSHF(uint32_t fetchdat) static int opPUSHFD(uint32_t fetchdat) { uint16_t tempw; - if ((eflags & VM_FLAG) && (IOPL < 3)) + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { x86gpf(NULL, 0); return 1; } - if (cpu_CR4_mask & CR4_VME) tempw = eflags & 0x3c; - else if (CPUID) tempw = eflags & 0x24; - else tempw = eflags & 4; + if (cpu_CR4_mask & CR4_VME) tempw = cpu_state.eflags & 0x3c; + else if (CPUID) tempw = cpu_state.eflags & 0x24; + else tempw = cpu_state.eflags & 4; flags_rebuild(); - PUSH_L(flags | (tempw << 16)); + PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); return cpu_state.abrt; @@ -163,7 +163,7 @@ static int opPOPF_286(uint32_t fetchdat) { uint16_t tempw; - if ((eflags & VM_FLAG) && (IOPL < 3)) + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { x86gpf(NULL, 0); return 1; @@ -171,10 +171,10 @@ static int opPOPF_286(uint32_t fetchdat) tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) flags = (flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2; - else flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2; + if (!(msw & 1)) cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); CLOCK_CYCLES(5); @@ -188,7 +188,7 @@ static int opPOPF(uint32_t fetchdat) { uint16_t tempw; - if ((eflags & VM_FLAG) && (IOPL < 3)) + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { if (cr4 & CR4_VME) { @@ -201,17 +201,17 @@ static int opPOPF(uint32_t fetchdat) return 1; } - if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (eflags & VIP_FLAG))) + if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { ESP = old_esp; x86gpf(NULL, 0); return 1; } if (tempw & I_FLAG) - eflags |= VIF_FLAG; + cpu_state.eflags |= VIF_FLAG; else - eflags &= ~VIF_FLAG; - flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; } else { @@ -226,11 +226,11 @@ static int opPOPF(uint32_t fetchdat) return 1; if (!(CPL) || !(msw & 1)) - flags = (tempw & 0x7fd5) | 2; + cpu_state.flags = (tempw & 0x7fd5) | 2; else if (IOPLp) - flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; else - flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; } flags_extract(); @@ -245,7 +245,7 @@ static int opPOPFD(uint32_t fetchdat) { uint32_t templ; - if ((eflags & VM_FLAG) && (IOPL < 3)) + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { x86gpf(NULL, 0); return 1; @@ -253,16 +253,16 @@ static int opPOPFD(uint32_t fetchdat) templ = POP_L(); if (cpu_state.abrt) return 1; - if (!(CPL) || !(msw & 1)) flags = (templ & 0x7fd5) | 2; - else if (IOPLp) flags = (flags & 0x3000) | (templ & 0x4fd5) | 2; - else flags = (flags & 0x3200) | (templ & 0x4dd5) | 2; + if (!(CPL) || !(msw & 1)) cpu_state.flags = (templ & 0x7fd5) | 2; + else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2; + else cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2; templ &= is486 ? 0x3c0000 : 0; - templ |= ((eflags&3) << 16); - if (cpu_CR4_mask & CR4_VME) eflags = (templ >> 16) & 0x3f; - else if (CPUID) eflags = (templ >> 16) & 0x27; - else if (is486) eflags = (templ >> 16) & 7; - else eflags = (templ >> 16) & 3; + templ |= ((cpu_state.eflags&3) << 16); + if (cpu_CR4_mask & CR4_VME) cpu_state.eflags = (templ >> 16) & 0x3f; + else if (CPUID) cpu_state.eflags = (templ >> 16) & 0x27; + else if (is486) cpu_state.eflags = (templ >> 16) & 7; + else cpu_state.eflags = (templ >> 16) & 3; flags_extract(); diff --git a/src/x86_ops_int.h b/src/x86_ops_int.h index ce85225..efb2a5d 100644 --- a/src/x86_ops_int.h +++ b/src/x86_ops_int.h @@ -1,7 +1,7 @@ static int opINT3(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); return 1; @@ -15,7 +15,7 @@ static int opINT3(uint32_t fetchdat) static int opINT1(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); return 1; @@ -31,7 +31,7 @@ static int opINT(uint32_t fetchdat) int cycles_old = cycles; UNUSED(cycles_old); uint8_t temp = getbytef(); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { if (cr4 & CR4_VME) { @@ -104,7 +104,7 @@ static int opINTO(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); return 1; diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index 7c220a0..ee6c632 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -86,8 +86,8 @@ static int opF6_a16(uint32_t fetchdat) case 0x20: /*MUL AL,b*/ AX = AL * dst; flags_rebuild(); - if (AH) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (AH) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(13); PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; @@ -95,8 +95,8 @@ static int opF6_a16(uint32_t fetchdat) tempws = (int)((int8_t)AL) * (int)((int8_t)dst); AX = tempws & 0xffff; flags_rebuild(); - if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(14); PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; @@ -110,8 +110,8 @@ static int opF6_a16(uint32_t fetchdat) if (!cpu_iscyrix) { flags_rebuild(); - flags |= 0x8D5; /*Not a Cyrix*/ - flags &= ~1; + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; } } else @@ -133,8 +133,8 @@ static int opF6_a16(uint32_t fetchdat) if (!cpu_iscyrix) { flags_rebuild(); - flags|=0x8D5; /*Not a Cyrix*/ - flags &= ~1; + cpu_state.flags|=0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; } } else @@ -192,8 +192,8 @@ static int opF6_a32(uint32_t fetchdat) case 0x20: /*MUL AL,b*/ AX = AL * dst; flags_rebuild(); - if (AH) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (AH) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(13); PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; @@ -201,8 +201,8 @@ static int opF6_a32(uint32_t fetchdat) tempws = (int)((int8_t)AL) * (int)((int8_t)dst); AX = tempws & 0xffff; flags_rebuild(); - if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(14); PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; @@ -216,8 +216,8 @@ static int opF6_a32(uint32_t fetchdat) if (!cpu_iscyrix) { flags_rebuild(); - flags |= 0x8D5; /*Not a Cyrix*/ - flags &= ~1; + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; } } else @@ -239,8 +239,8 @@ static int opF6_a32(uint32_t fetchdat) if (!cpu_iscyrix) { flags_rebuild(); - flags|=0x8D5; /*Not a Cyrix*/ - flags &= ~1; + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; } } else @@ -303,8 +303,8 @@ static int opF7_w_a16(uint32_t fetchdat) AX = templ & 0xFFFF; DX = templ >> 16; flags_rebuild(); - if (DX) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (DX) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(21); PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; @@ -313,8 +313,8 @@ static int opF7_w_a16(uint32_t fetchdat) AX = templ & 0xFFFF; DX = templ >> 16; flags_rebuild(); - if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(22); PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; @@ -403,8 +403,8 @@ static int opF7_w_a32(uint32_t fetchdat) AX = templ & 0xFFFF; DX = templ >> 16; flags_rebuild(); - if (DX) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (DX) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(21); PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; @@ -413,8 +413,8 @@ static int opF7_w_a32(uint32_t fetchdat) AX = templ & 0xFFFF; DX = templ >> 16; flags_rebuild(); - if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(22); PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; @@ -503,8 +503,8 @@ static int opF7_l_a16(uint32_t fetchdat) EAX = temp64 & 0xffffffff; EDX = temp64 >> 32; flags_rebuild(); - if (EDX) flags |= (C_FLAG|V_FLAG); - else flags &= ~(C_FLAG|V_FLAG); + if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG); + else cpu_state.flags &= ~(C_FLAG|V_FLAG); CLOCK_CYCLES(21); PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; @@ -513,8 +513,8 @@ static int opF7_l_a16(uint32_t fetchdat) EAX = temp64 & 0xffffffff; EDX = temp64 >> 32; flags_rebuild(); - if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(38); PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; @@ -579,8 +579,8 @@ static int opF7_l_a32(uint32_t fetchdat) EAX = temp64 & 0xffffffff; EDX = temp64 >> 32; flags_rebuild(); - if (EDX) flags |= (C_FLAG|V_FLAG); - else flags &= ~(C_FLAG|V_FLAG); + if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG); + else cpu_state.flags &= ~(C_FLAG|V_FLAG); CLOCK_CYCLES(21); PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; @@ -589,8 +589,8 @@ static int opF7_l_a32(uint32_t fetchdat) EAX = temp64 & 0xffffffff; EDX = temp64 >> 32; flags_rebuild(); - if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) flags |= (C_FLAG | V_FLAG); - else flags &= ~(C_FLAG | V_FLAG); + if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(38); PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; @@ -619,12 +619,12 @@ static int opF7_l_a32(uint32_t fetchdat) static int opHLT(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { x86gpf(NULL,0); return 1; } - if (!((flags&I_FLAG) && pic_intpending)) + if (!((cpu_state.flags & I_FLAG) && pic_intpending)) { CLOCK_CYCLES_ALWAYS(100); cpu_state.pc--; @@ -739,7 +739,7 @@ static int opBOUND_l_a32(uint32_t fetchdat) static int opCLTS(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't CLTS\n"); x86gpf(NULL,0); @@ -782,7 +782,7 @@ static int opLOADALL(uint32_t fetchdat) return 1; } msw = (msw & 1) | readmemw(0, 0x806); - flags = (readmemw(0, 0x818) & 0xffd5) | 2; + cpu_state.flags = (readmemw(0, 0x818) & 0xffd5) | 2; flags_extract(); tr.seg = readmemw(0, 0x816); cpu_state.pc = readmemw(0, 0x81A); @@ -890,8 +890,8 @@ static int opLOADALL386(uint32_t fetchdat) uint32_t la_addr = es + EDI; cr0 = readmeml(0, la_addr); - flags = readmemw(0, la_addr + 4); - eflags = readmemw(0, la_addr + 6); + cpu_state.flags = readmemw(0, la_addr + 4); + cpu_state.eflags = readmemw(0, la_addr + 6); flags_extract(); cpu_state.pc = readmeml(0, la_addr + 8); EDI = readmeml(0, la_addr + 0xC); diff --git a/src/x86_ops_mov_ctrl.h b/src/x86_ops_mov_ctrl.h index 7b21bf7..190dfdc 100644 --- a/src/x86_ops_mov_ctrl.h +++ b/src/x86_ops_mov_ctrl.h @@ -1,6 +1,6 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load from CRx\n"); x86gpf(NULL, 0); @@ -38,7 +38,7 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) } static int opMOV_r_CRx_a32(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load from CRx\n"); x86gpf(NULL, 0); @@ -77,7 +77,7 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat) static int opMOV_r_DRx_a16(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load from DRx\n"); x86gpf(NULL, 0); @@ -91,7 +91,7 @@ static int opMOV_r_DRx_a16(uint32_t fetchdat) } static int opMOV_r_DRx_a32(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load from DRx\n"); x86gpf(NULL, 0); @@ -108,7 +108,7 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) { uint32_t old_cr0 = cr0; - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load CRx\n"); x86gpf(NULL,0); @@ -164,7 +164,7 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) { uint32_t old_cr0 = cr0; - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load CRx\n"); x86gpf(NULL,0); @@ -219,7 +219,7 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) static int opMOV_DRx_r_a16(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load DRx\n"); x86gpf(NULL, 0); @@ -233,7 +233,7 @@ static int opMOV_DRx_r_a16(uint32_t fetchdat) } static int opMOV_DRx_r_a32(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load DRx\n"); x86gpf(NULL, 0); @@ -248,7 +248,7 @@ static int opMOV_DRx_r_a32(uint32_t fetchdat) static int opMOV_r_TRx_a16(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load from TRx\n"); x86gpf(NULL, 0); @@ -262,7 +262,7 @@ static int opMOV_r_TRx_a16(uint32_t fetchdat) } static int opMOV_r_TRx_a32(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load from TRx\n"); x86gpf(NULL, 0); @@ -277,7 +277,7 @@ static int opMOV_r_TRx_a32(uint32_t fetchdat) static int opMOV_TRx_r_a16(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load TRx\n"); x86gpf(NULL, 0); @@ -290,7 +290,7 @@ static int opMOV_TRx_r_a16(uint32_t fetchdat) } static int opMOV_TRx_r_a32(uint32_t fetchdat) { - if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load TRx\n"); x86gpf(NULL, 0); diff --git a/src/x86_ops_mul.h b/src/x86_ops_mul.h index 27778b0..5971140 100644 --- a/src/x86_ops_mul.h +++ b/src/x86_ops_mul.h @@ -12,8 +12,8 @@ static int opIMUL_w_iw_a16(uint32_t fetchdat) templ = ((int)tempw) * ((int)tempw2); flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); @@ -34,8 +34,8 @@ static int opIMUL_w_iw_a32(uint32_t fetchdat) templ = ((int)tempw) * ((int)tempw2); flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); @@ -57,8 +57,8 @@ static int opIMUL_l_il_a16(uint32_t fetchdat) temp64 = ((int64_t)templ) * ((int64_t)templ2); flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(25); @@ -79,8 +79,8 @@ static int opIMUL_l_il_a32(uint32_t fetchdat) temp64 = ((int64_t)templ) * ((int64_t)templ2); flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(25); @@ -103,8 +103,8 @@ static int opIMUL_w_ib_a16(uint32_t fetchdat) templ = ((int)tempw) * ((int)tempw2); flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); @@ -126,8 +126,8 @@ static int opIMUL_w_ib_a32(uint32_t fetchdat) templ = ((int)tempw) * ((int)tempw2); flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); @@ -150,8 +150,8 @@ static int opIMUL_l_ib_a16(uint32_t fetchdat) temp64 = ((int64_t)templ)*((int64_t)templ2); flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(20); @@ -173,8 +173,8 @@ static int opIMUL_l_ib_a32(uint32_t fetchdat) temp64 = ((int64_t)templ)*((int64_t)templ2); flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(20); @@ -196,8 +196,8 @@ static int opIMUL_w_w_a16(uint32_t fetchdat) if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = templ & 0xFFFF; flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(18); PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 0); @@ -215,8 +215,8 @@ static int opIMUL_w_w_a32(uint32_t fetchdat) if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = templ & 0xFFFF; flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(18); PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 1); @@ -235,8 +235,8 @@ static int opIMUL_l_l_a16(uint32_t fetchdat) if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(30); PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 0); @@ -254,8 +254,8 @@ static int opIMUL_l_l_a32(uint32_t fetchdat) if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG; - else flags &= ~(C_FLAG | V_FLAG); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; + else cpu_state.flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(30); PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 1); diff --git a/src/x86_ops_pmode.h b/src/x86_ops_pmode.h index a59340b..5301ef3 100644 --- a/src/x86_ops_pmode.h +++ b/src/x86_ops_pmode.h @@ -14,10 +14,10 @@ static int opARPL_a16(uint32_t fetchdat) { temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3); seteaw(temp_seg); if (cpu_state.abrt) return 1; - flags |= Z_FLAG; + cpu_state.flags |= Z_FLAG; } else - flags &= ~Z_FLAG; + cpu_state.flags &= ~Z_FLAG; CLOCK_CYCLES(is486 ? 9 : 20); PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 0); @@ -39,10 +39,10 @@ static int opARPL_a32(uint32_t fetchdat) { temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3); seteaw(temp_seg); if (cpu_state.abrt) return 1; - flags |= Z_FLAG; + cpu_state.flags |= Z_FLAG; } else - flags &= ~Z_FLAG; + cpu_state.flags &= ~Z_FLAG; CLOCK_CYCLES(is486 ? 9 : 20); PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 1); @@ -63,7 +63,7 @@ static int opARPL_a32(uint32_t fetchdat) sel = geteaw(); if (cpu_state.abrt) return 1; \ \ flags_rebuild(); \ - if (!(sel & 0xfffc)) { flags &= ~Z_FLAG; return 0; } /*Null selector*/ \ + if (!(sel & 0xfffc)) { cpu_state.flags &= ~Z_FLAG; return 0; } /*Null selector*/ \ valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \ if (valid) \ { \ @@ -71,7 +71,7 @@ static int opARPL_a32(uint32_t fetchdat) desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \ cpl_override = 0; if (cpu_state.abrt) return 1; \ } \ - flags &= ~Z_FLAG; \ + cpu_state.flags &= ~Z_FLAG; \ if ((desc & 0x1f00) == 0x000) valid = 0; \ if ((desc & 0x1f00) == 0x800) valid = 0; \ if ((desc & 0x1f00) == 0xa00) valid = 0; \ @@ -83,7 +83,7 @@ static int opARPL_a32(uint32_t fetchdat) } \ if (valid) \ { \ - flags |= Z_FLAG; \ + cpu_state.flags |= Z_FLAG; \ cpl_override = 1; \ if (is32) \ cpu_state.regs[cpu_reg].l = readmeml(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xffff00; \ @@ -114,7 +114,7 @@ opLAR(l_a32, fetch_ea_32, 1, 1) \ sel = geteaw(); if (cpu_state.abrt) return 1; \ flags_rebuild(); \ - flags &= ~Z_FLAG; \ + cpu_state.flags &= ~Z_FLAG; \ if (!(sel & 0xfffc)) return 0; /*Null selector*/ \ valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \ if (valid) \ @@ -133,7 +133,7 @@ opLAR(l_a32, fetch_ea_32, 1, 1) } \ if (valid) \ { \ - flags |= Z_FLAG; \ + cpu_state.flags |= Z_FLAG; \ cpl_override = 1; \ if (is32) \ { \ @@ -185,7 +185,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x10: /*LLDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) + if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) { pclog("Invalid LLDT!\n"); x86gpf(NULL,0); @@ -213,7 +213,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32); break; case 0x18: /*LTR*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) + if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) { pclog("Invalid LTR!\n"); x86gpf(NULL,0); @@ -248,7 +248,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) SEG_CHECK_READ(cpu_state.ea_seg); sel = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); - flags &= ~Z_FLAG; + cpu_state.flags &= ~Z_FLAG; if (!(sel & 0xfffc)) return 0; /*Null selector*/ cpl_override = 1; valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); @@ -261,7 +261,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) if (dpl < CPL || dpl < (sel & 3)) valid = 0; } if ((desc & 0x0800) && !(desc & 0x0200)) valid = 0; /*Non-readable code*/ - if (valid) flags |= Z_FLAG; + if (valid) cpu_state.flags |= Z_FLAG; CLOCK_CYCLES(20); PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); break; @@ -270,7 +270,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) SEG_CHECK_READ(cpu_state.ea_seg); sel = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); - flags &= ~Z_FLAG; + cpu_state.flags &= ~Z_FLAG; if (!(sel & 0xfffc)) return 0; /*Null selector*/ cpl_override = 1; valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); @@ -281,7 +281,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) if (dpl < CPL || dpl < (sel & 3)) valid = 0; if (desc & 0x0800) valid = 0; /*Code*/ if (!(desc & 0x0200)) valid = 0; /*Read-only data*/ - if (valid) flags |= Z_FLAG; + if (valid) cpu_state.flags |= Z_FLAG; CLOCK_CYCLES(20); PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); break; @@ -342,7 +342,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32); break; case 0x10: /*LGDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) + if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) { pclog("Invalid LGDT!\n"); x86gpf(NULL,0); @@ -361,7 +361,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32); break; case 0x18: /*LIDT*/ - if ((CPL || eflags&VM_FLAG) && (cr0&1)) + if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) { pclog("Invalid LIDT!\n"); x86gpf(NULL,0); @@ -390,7 +390,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x30: /*LMSW*/ - if ((CPL || eflags&VM_FLAG) && (msw&1)) + if ((CPL || cpu_state.eflags&VM_FLAG) && (msw&1)) { pclog("LMSW - ring not zero!\n"); x86gpf(NULL, 0); @@ -417,7 +417,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) case 0x38: /*INVLPG*/ if (is486) { - if ((CPL || eflags&VM_FLAG) && (cr0&1)) + if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) { pclog("Invalid INVLPG!\n"); x86gpf(NULL, 0); diff --git a/src/x86_ops_rep.h b/src/x86_ops_rep.h index bd95991..4adfcb1 100644 --- a/src/x86_ops_rep.h +++ b/src/x86_ops_rep.h @@ -14,8 +14,8 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) temp = inb(DX); \ writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ + if (cpu_state.flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ CNT_REG--; \ cycles -= 15; \ reads++; writes++; total_cycles += 15; \ @@ -43,8 +43,8 @@ static int opREP_INSW_ ## size(uint32_t fetchdat) temp = inw(DX); \ writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ + if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ + else DEST_REG += 2; \ CNT_REG--; \ cycles -= 15; \ reads++; writes++; total_cycles += 15; \ @@ -74,8 +74,8 @@ static int opREP_INSL_ ## size(uint32_t fetchdat) temp = inl(DX); \ writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ + if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ + else DEST_REG += 4; \ CNT_REG--; \ cycles -= 15; \ reads++; writes++; total_cycles += 15; \ @@ -101,8 +101,8 @@ static int opREP_OUTSB_ ## size(uint32_t fetchdat) temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ check_io_perm(DX); \ outb(DX, temp); \ - if (flags & D_FLAG) SRC_REG--; \ - else SRC_REG++; \ + if (cpu_state.flags & D_FLAG) SRC_REG--; \ + else SRC_REG++; \ CNT_REG--; \ cycles -= 14; \ reads++; writes++; total_cycles += 14; \ @@ -128,8 +128,8 @@ static int opREP_OUTSW_ ## size(uint32_t fetchdat) check_io_perm(DX); \ check_io_perm(DX+1); \ outw(DX, temp); \ - if (flags & D_FLAG) SRC_REG -= 2; \ - else SRC_REG += 2; \ + if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \ + else SRC_REG += 2; \ CNT_REG--; \ cycles -= 14; \ reads++; writes++; total_cycles += 14; \ @@ -157,8 +157,8 @@ static int opREP_OUTSL_ ## size(uint32_t fetchdat) check_io_perm(DX+2); \ check_io_perm(DX+3); \ outl(DX, temp); \ - if (flags & D_FLAG) SRC_REG -= 4; \ - else SRC_REG += 4; \ + if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \ + else SRC_REG += 4; \ CNT_REG--; \ cycles -= 14; \ reads++; writes++; total_cycles += 14; \ @@ -192,8 +192,8 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ - else { DEST_REG++; SRC_REG++; } \ + if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ + else { DEST_REG++; SRC_REG++; } \ CNT_REG--; \ cycles -= is486 ? 3 : 4; \ ins++; \ @@ -230,8 +230,8 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ - else { DEST_REG += 2; SRC_REG += 2; } \ + if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ + else { DEST_REG += 2; SRC_REG += 2; } \ CNT_REG--; \ cycles -= is486 ? 3 : 4; \ ins++; \ @@ -268,8 +268,8 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ - else { DEST_REG += 4; SRC_REG += 4; } \ + if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ + else { DEST_REG += 4; SRC_REG += 4; } \ CNT_REG--; \ cycles -= is486 ? 3 : 4; \ ins++; \ @@ -301,8 +301,8 @@ static int opREP_STOSB_ ## size(uint32_t fetchdat) { \ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \ - if (flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ + if (cpu_state.flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ writes++; total_cycles += is486 ? 4 : 5; \ @@ -331,8 +331,8 @@ static int opREP_STOSW_ ## size(uint32_t fetchdat) { \ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG+1); \ writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \ - if (flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ + if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ + else DEST_REG += 2; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ writes++; total_cycles += is486 ? 4 : 5; \ @@ -361,8 +361,8 @@ static int opREP_STOSL_ ## size(uint32_t fetchdat) { \ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG+3); \ writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \ - if (flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ + if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ + else DEST_REG += 4; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ writes++; total_cycles += is486 ? 4 : 5; \ @@ -391,8 +391,8 @@ static int opREP_LODSB_ ## size(uint32_t fetchdat) while (CNT_REG > 0) \ { \ AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (flags & D_FLAG) SRC_REG--; \ - else SRC_REG++; \ + if (cpu_state.flags & D_FLAG) SRC_REG--; \ + else SRC_REG++; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ reads++; total_cycles += is486 ? 4 : 5; \ @@ -420,8 +420,8 @@ static int opREP_LODSW_ ## size(uint32_t fetchdat) while (CNT_REG > 0) \ { \ AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (flags & D_FLAG) SRC_REG -= 2; \ - else SRC_REG += 2; \ + if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \ + else SRC_REG += 2; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ reads++; total_cycles += is486 ? 4 : 5; \ @@ -449,8 +449,8 @@ static int opREP_LODSL_ ## size(uint32_t fetchdat) while (CNT_REG > 0) \ { \ EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (flags & D_FLAG) SRC_REG -= 4; \ - else SRC_REG += 4; \ + if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \ + else SRC_REG += 4; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ reads++; total_cycles += is486 ? 4 : 5; \ @@ -483,8 +483,8 @@ static int opREP_CMPSB_ ## size(uint32_t fetchdat) temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ - else { DEST_REG++; SRC_REG++; } \ + if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ + else { DEST_REG++; SRC_REG++; } \ CNT_REG--; \ cycles -= is486 ? 7 : 9; \ reads += 2; total_cycles += is486 ? 7 : 9; \ @@ -513,8 +513,8 @@ static int opREP_CMPSW_ ## size(uint32_t fetchdat) temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ - else { DEST_REG += 2; SRC_REG += 2; } \ + if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ + else { DEST_REG += 2; SRC_REG += 2; } \ CNT_REG--; \ cycles -= is486 ? 7 : 9; \ reads += 2; total_cycles += is486 ? 7 : 9; \ @@ -543,8 +543,8 @@ static int opREP_CMPSL_ ## size(uint32_t fetchdat) temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ \ - if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ - else { DEST_REG += 4; SRC_REG += 4; } \ + if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ + else { DEST_REG += 4; SRC_REG += 4; } \ CNT_REG--; \ cycles -= is486 ? 7 : 9; \ reads += 2; total_cycles += is486 ? 7 : 9; \ @@ -575,8 +575,8 @@ static int opREP_SCASB_ ## size(uint32_t fetchdat) uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\ setsub8(AL, temp); \ tempz = (ZF_SET()) ? 1 : 0; \ - if (flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ + if (cpu_state.flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ CNT_REG--; \ cycles -= is486 ? 5 : 8; \ reads++; total_cycles += is486 ? 5 : 8; \ @@ -608,8 +608,8 @@ static int opREP_SCASW_ ## size(uint32_t fetchdat) uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\ setsub16(AX, temp); \ tempz = (ZF_SET()) ? 1 : 0; \ - if (flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ + if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ + else DEST_REG += 2; \ CNT_REG--; \ cycles -= is486 ? 5 : 8; \ reads++; total_cycles += is486 ? 5 : 8; \ @@ -641,8 +641,8 @@ static int opREP_SCASL_ ## size(uint32_t fetchdat) uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\ setsub32(EAX, temp); \ tempz = (ZF_SET()) ? 1 : 0; \ - if (flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ + if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ + else DEST_REG += 4; \ CNT_REG--; \ cycles -= is486 ? 5 : 8; \ reads++; total_cycles += is486 ? 5 : 8; \ diff --git a/src/x86_ops_ret.h b/src/x86_ops_ret.h index d9db8ba..b69180c 100644 --- a/src/x86_ops_ret.h +++ b/src/x86_ops_ret.h @@ -1,5 +1,5 @@ #define RETF_a16(stack_offset) \ - if ((msw&1) && !(eflags&VM_FLAG)) \ + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ { \ pmoderetf(0, stack_offset); \ return 1; \ @@ -21,7 +21,7 @@ cycles -= timing_retf_rm; #define RETF_a32(stack_offset) \ - if ((msw&1) && !(eflags&VM_FLAG)) \ + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ { \ pmoderetf(1, stack_offset); \ return 1; \ @@ -94,7 +94,7 @@ static int opIRET_286(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); return 1; @@ -113,14 +113,14 @@ static int opIRET_286(uint32_t fetchdat) { cpu_state.pc = readmemw(ss, ESP); new_cs = readmemw(ss, ESP + 2); - flags = (flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; ESP += 6; } else { cpu_state.pc = readmemw(ss, SP); new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - flags = (flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; SP += 6; } loadcs(new_cs); @@ -139,7 +139,7 @@ static int opIRET(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { if (cr4 & CR4_VME) { @@ -151,17 +151,17 @@ static int opIRET(uint32_t fetchdat) if (cpu_state.abrt) return 1; - if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (eflags & VIP_FLAG))) + if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { x86gpf(NULL, 0); return 1; } SP += 6; if (new_flags & I_FLAG) - eflags |= VIF_FLAG; + cpu_state.eflags |= VIF_FLAG; else - eflags &= ~VIF_FLAG; - flags = (flags & 0x3300) | (new_flags & 0x4cd5) | 2; + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2; loadcs(new_cs); cpu_state.pc = new_pc; @@ -189,14 +189,14 @@ static int opIRET(uint32_t fetchdat) { cpu_state.pc = readmemw(ss, ESP); new_cs = readmemw(ss, ESP + 2); - flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; + cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; ESP += 6; } else { cpu_state.pc = readmemw(ss, SP); new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; + cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; SP += 6; } loadcs(new_cs); @@ -216,7 +216,7 @@ static int opIRETD(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); - if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); return 1; @@ -235,16 +235,16 @@ static int opIRETD(uint32_t fetchdat) { cpu_state.pc = readmeml(ss, ESP); new_cs = readmemw(ss, ESP + 4); - flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; - eflags = readmemw(ss, ESP + 10); + cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, ESP + 10); ESP += 12; } else { cpu_state.pc = readmeml(ss, SP); new_cs = readmemw(ss, ((SP + 4) & 0xffff)); - flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2; - eflags = readmemw(ss, (SP + 10) & 0xffff); + cpu_state.flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff); SP += 12; } loadcs(new_cs); diff --git a/src/x86_ops_shift.h b/src/x86_ops_shift.h index 1fe2e89..1a31316 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -13,9 +13,9 @@ c--; \ } \ seteab(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -28,14 +28,14 @@ c--; \ } \ seteab(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x10: /*RCL b,CL*/ \ - temp2 = flags & C_FLAG; \ + temp2 = cpu_state.flags & C_FLAG; \ if (is486) CLOCK_CYCLES_ALWAYS(c); \ while (c > 0) \ { \ @@ -45,14 +45,14 @@ c--; \ } \ seteab(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x18: /*RCR b,CL*/ \ - temp2 = flags & C_FLAG; \ + temp2 = cpu_state.flags & C_FLAG; \ if (is486) CLOCK_CYCLES_ALWAYS(c); \ while (c > 0) \ { \ @@ -62,9 +62,9 @@ c--; \ } \ seteab(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -105,9 +105,9 @@ c--; \ } \ seteaw(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -120,14 +120,14 @@ c--; \ } \ seteaw(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x10: /*RCL w, c*/ \ - temp2 = flags & C_FLAG; \ + temp2 = cpu_state.flags & C_FLAG; \ if (is486) CLOCK_CYCLES_ALWAYS(c); \ while (c > 0) \ { \ @@ -137,14 +137,14 @@ c--; \ } \ seteaw(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x18: /*RCR w, c*/ \ - temp2 = flags & C_FLAG; \ + temp2 = cpu_state.flags & C_FLAG; \ if (is486) CLOCK_CYCLES_ALWAYS(c); \ while (c > 0) \ { \ @@ -154,9 +154,9 @@ c--; \ } \ seteaw(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -197,9 +197,9 @@ c--; \ } \ seteal(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ @@ -212,9 +212,9 @@ c--; \ } \ seteal(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ @@ -229,14 +229,14 @@ c--; \ } \ seteal(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x18: /*RCR l, c*/ \ - temp2 = flags & C_FLAG; \ + temp2 = cpu_state.flags & C_FLAG; \ if (is486) CLOCK_CYCLES_ALWAYS(c); \ while (c > 0) \ { \ @@ -246,9 +246,9 @@ c--; \ } \ seteal(temp); if (cpu_state.abrt) return 1; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ @@ -541,7 +541,7 @@ static int opD3_l_a32(uint32_t fetchdat) seteaw(tempw); if (cpu_state.abrt) return 1; \ setznp16(tempw); \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ } #define SHLD_l() \ @@ -553,7 +553,7 @@ static int opD3_l_a32(uint32_t fetchdat) seteal(templ); if (cpu_state.abrt) return 1; \ setznp32(templ); \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ } @@ -567,7 +567,7 @@ static int opD3_l_a32(uint32_t fetchdat) seteaw(tempw); if (cpu_state.abrt) return 1; \ setznp16(tempw); \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ } #define SHRD_l() \ @@ -579,7 +579,7 @@ static int opD3_l_a32(uint32_t fetchdat) seteal(templ); if (cpu_state.abrt) return 1; \ setznp32(templ); \ flags_rebuild(); \ - if (tempc) flags |= C_FLAG; \ + if (tempc) cpu_state.flags |= C_FLAG; \ } #define opSHxD(operation) \ diff --git a/src/x86_ops_string.h b/src/x86_ops_string.h index 3bdeace..433d683 100644 --- a/src/x86_ops_string.h +++ b/src/x86_ops_string.h @@ -6,8 +6,8 @@ static int opMOVSB_a16(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememb(es, DI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) { DI--; SI--; } - else { DI++; SI++; } + if (cpu_state.flags & D_FLAG) { DI--; SI--; } + else { DI++; SI++; } CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0); return 0; @@ -20,8 +20,8 @@ static int opMOVSB_a32(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememb(es, EDI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } + if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } + else { EDI++; ESI++; } CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1); return 0; @@ -35,8 +35,8 @@ static int opMOVSW_a16(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememw(es, DI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) { DI -= 2; SI -= 2; } - else { DI += 2; SI += 2; } + if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } + else { DI += 2; SI += 2; } CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0); return 0; @@ -49,8 +49,8 @@ static int opMOVSW_a32(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememw(es, EDI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } - else { EDI += 2; ESI += 2; } + if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } + else { EDI += 2; ESI += 2; } CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1); return 0; @@ -64,8 +64,8 @@ static int opMOVSL_a16(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; writememl(es, DI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) { DI -= 4; SI -= 4; } - else { DI += 4; SI += 4; } + if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } + else { DI += 4; SI += 4; } CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 0,1,0,1, 0); return 0; @@ -78,8 +78,8 @@ static int opMOVSL_a32(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; writememl(es, EDI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } - else { EDI += 4; ESI += 4; } + if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } + else { EDI += 4; ESI += 4; } CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 0,1,0,1, 1); return 0; @@ -95,8 +95,8 @@ static int opCMPSB_a16(uint32_t fetchdat) src = readmemb(cpu_state.ea_seg->base, SI); dst = readmemb(es, DI); if (cpu_state.abrt) return 1; setsub8(src, dst); - if (flags & D_FLAG) { DI--; SI--; } - else { DI++; SI++; } + if (cpu_state.flags & D_FLAG) { DI--; SI--; } + else { DI++; SI++; } CLOCK_CYCLES((is486) ? 8 : 10); PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0); return 0; @@ -110,8 +110,8 @@ static int opCMPSB_a32(uint32_t fetchdat) src = readmemb(cpu_state.ea_seg->base, ESI); dst = readmemb(es, EDI); if (cpu_state.abrt) return 1; setsub8(src, dst); - if (flags & D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } + if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } + else { EDI++; ESI++; } CLOCK_CYCLES((is486) ? 8 : 10); PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1); return 0; @@ -126,8 +126,8 @@ static int opCMPSW_a16(uint32_t fetchdat) src = readmemw(cpu_state.ea_seg->base, SI); dst = readmemw(es, DI); if (cpu_state.abrt) return 1; setsub16(src, dst); - if (flags & D_FLAG) { DI -= 2; SI -= 2; } - else { DI += 2; SI += 2; } + if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } + else { DI += 2; SI += 2; } CLOCK_CYCLES((is486) ? 8 : 10); PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0); return 0; @@ -141,8 +141,8 @@ static int opCMPSW_a32(uint32_t fetchdat) src = readmemw(cpu_state.ea_seg->base, ESI); dst = readmemw(es, EDI); if (cpu_state.abrt) return 1; setsub16(src, dst); - if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } - else { EDI += 2; ESI += 2; } + if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } + else { EDI += 2; ESI += 2; } CLOCK_CYCLES((is486) ? 8 : 10); PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1); return 0; @@ -157,8 +157,8 @@ static int opCMPSL_a16(uint32_t fetchdat) src = readmeml(cpu_state.ea_seg->base, SI); dst = readmeml(es, DI); if (cpu_state.abrt) return 1; setsub32(src, dst); - if (flags & D_FLAG) { DI -= 4; SI -= 4; } - else { DI += 4; SI += 4; } + if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } + else { DI += 4; SI += 4; } CLOCK_CYCLES((is486) ? 8 : 10); PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 0); return 0; @@ -172,8 +172,8 @@ static int opCMPSL_a32(uint32_t fetchdat) src = readmeml(cpu_state.ea_seg->base, ESI); dst = readmeml(es, EDI); if (cpu_state.abrt) return 1; setsub32(src, dst); - if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } - else { EDI += 4; ESI += 4; } + if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } + else { EDI += 4; ESI += 4; } CLOCK_CYCLES((is486) ? 8 : 10); PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 1); return 0; @@ -183,8 +183,8 @@ static int opSTOSB_a16(uint32_t fetchdat) { SEG_CHECK_WRITE(&cpu_state.seg_es); writememb(es, DI, AL); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); return 0; @@ -193,8 +193,8 @@ static int opSTOSB_a32(uint32_t fetchdat) { SEG_CHECK_WRITE(&cpu_state.seg_es); writememb(es, EDI, AL); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) EDI--; - else EDI++; + if (cpu_state.flags & D_FLAG) EDI--; + else EDI++; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1); return 0; @@ -204,8 +204,8 @@ static int opSTOSW_a16(uint32_t fetchdat) { SEG_CHECK_WRITE(&cpu_state.seg_es); writememw(es, DI, AX); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) DI -= 2; - else DI += 2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); return 0; @@ -214,8 +214,8 @@ static int opSTOSW_a32(uint32_t fetchdat) { SEG_CHECK_WRITE(&cpu_state.seg_es); writememw(es, EDI, AX); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) EDI -= 2; - else EDI += 2; + if (cpu_state.flags & D_FLAG) EDI -= 2; + else EDI += 2; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1); return 0; @@ -225,8 +225,8 @@ static int opSTOSL_a16(uint32_t fetchdat) { SEG_CHECK_WRITE(&cpu_state.seg_es); writememl(es, DI, EAX); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) DI -= 4; - else DI += 4; + if (cpu_state.flags & D_FLAG) DI -= 4; + else DI += 4; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); return 0; @@ -235,8 +235,8 @@ static int opSTOSL_a32(uint32_t fetchdat) { SEG_CHECK_WRITE(&cpu_state.seg_es); writememl(es, EDI, EAX); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) EDI -= 4; - else EDI += 4; + if (cpu_state.flags & D_FLAG) EDI -= 4; + else EDI += 4; CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0,0,0,1, 1); return 0; @@ -250,8 +250,8 @@ static int opLODSB_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; AL = temp; - if (flags & D_FLAG) SI--; - else SI++; + if (cpu_state.flags & D_FLAG) SI--; + else SI++; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); return 0; @@ -263,8 +263,8 @@ static int opLODSB_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; AL = temp; - if (flags & D_FLAG) ESI--; - else ESI++; + if (cpu_state.flags & D_FLAG) ESI--; + else ESI++; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); return 0; @@ -277,8 +277,8 @@ static int opLODSW_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; AX = temp; - if (flags & D_FLAG) SI -= 2; - else SI += 2; + if (cpu_state.flags & D_FLAG) SI -= 2; + else SI += 2; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); return 0; @@ -290,8 +290,8 @@ static int opLODSW_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; AX = temp; - if (flags & D_FLAG) ESI -= 2; - else ESI += 2; + if (cpu_state.flags & D_FLAG) ESI -= 2; + else ESI += 2; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); return 0; @@ -304,8 +304,8 @@ static int opLODSL_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; EAX = temp; - if (flags & D_FLAG) SI -= 4; - else SI += 4; + if (cpu_state.flags & D_FLAG) SI -= 4; + else SI += 4; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); return 0; @@ -317,8 +317,8 @@ static int opLODSL_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; EAX = temp; - if (flags & D_FLAG) ESI -= 4; - else ESI += 4; + if (cpu_state.flags & D_FLAG) ESI -= 4; + else ESI += 4; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0,1,0,0, 1); return 0; @@ -332,8 +332,8 @@ static int opSCASB_a16(uint32_t fetchdat) SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemb(es, DI); if (cpu_state.abrt) return 1; setsub8(AL, temp); - if (flags & D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0); return 0; @@ -345,8 +345,8 @@ static int opSCASB_a32(uint32_t fetchdat) SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemb(es, EDI); if (cpu_state.abrt) return 1; setsub8(AL, temp); - if (flags & D_FLAG) EDI--; - else EDI++; + if (cpu_state.flags & D_FLAG) EDI--; + else EDI++; CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1); return 0; @@ -359,8 +359,8 @@ static int opSCASW_a16(uint32_t fetchdat) SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemw(es, DI); if (cpu_state.abrt) return 1; setsub16(AX, temp); - if (flags & D_FLAG) DI -= 2; - else DI += 2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0); return 0; @@ -372,8 +372,8 @@ static int opSCASW_a32(uint32_t fetchdat) SEG_CHECK_READ(&cpu_state.seg_es); temp = readmemw(es, EDI); if (cpu_state.abrt) return 1; setsub16(AX, temp); - if (flags & D_FLAG) EDI -= 2; - else EDI += 2; + if (cpu_state.flags & D_FLAG) EDI -= 2; + else EDI += 2; CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1); return 0; @@ -386,8 +386,8 @@ static int opSCASL_a16(uint32_t fetchdat) SEG_CHECK_READ(&cpu_state.seg_es); temp = readmeml(es, DI); if (cpu_state.abrt) return 1; setsub32(EAX, temp); - if (flags & D_FLAG) DI -= 4; - else DI += 4; + if (cpu_state.flags & D_FLAG) DI -= 4; + else DI += 4; CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 0,1,0,0, 0); return 0; @@ -399,8 +399,8 @@ static int opSCASL_a32(uint32_t fetchdat) SEG_CHECK_READ(&cpu_state.seg_es); temp = readmeml(es, EDI); if (cpu_state.abrt) return 1; setsub32(EAX, temp); - if (flags & D_FLAG) EDI -= 4; - else EDI += 4; + if (cpu_state.flags & D_FLAG) EDI -= 4; + else EDI += 4; CLOCK_CYCLES(7); PREFETCH_RUN(7, 1, -1, 0,1,0,0, 1); return 0; @@ -414,8 +414,8 @@ static int opINSB_a16(uint32_t fetchdat) check_io_perm(DX); temp = inb(DX); writememb(es, DI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) DI--; - else DI++; + if (cpu_state.flags & D_FLAG) DI--; + else DI++; CLOCK_CYCLES(15); PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0); return 0; @@ -428,8 +428,8 @@ static int opINSB_a32(uint32_t fetchdat) check_io_perm(DX); temp = inb(DX); writememb(es, EDI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) EDI--; - else EDI++; + if (cpu_state.flags & D_FLAG) EDI--; + else EDI++; CLOCK_CYCLES(15); PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1); return 0; @@ -444,8 +444,8 @@ static int opINSW_a16(uint32_t fetchdat) check_io_perm(DX + 1); temp = inw(DX); writememw(es, DI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) DI -= 2; - else DI += 2; + if (cpu_state.flags & D_FLAG) DI -= 2; + else DI += 2; CLOCK_CYCLES(15); PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0); return 0; @@ -459,8 +459,8 @@ static int opINSW_a32(uint32_t fetchdat) check_io_perm(DX + 1); temp = inw(DX); writememw(es, EDI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) EDI -= 2; - else EDI += 2; + if (cpu_state.flags & D_FLAG) EDI -= 2; + else EDI += 2; CLOCK_CYCLES(15); PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1); return 0; @@ -477,8 +477,8 @@ static int opINSL_a16(uint32_t fetchdat) check_io_perm(DX + 3); temp = inl(DX); writememl(es, DI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) DI -= 4; - else DI += 4; + if (cpu_state.flags & D_FLAG) DI -= 4; + else DI += 4; CLOCK_CYCLES(15); PREFETCH_RUN(15, 1, -1, 0,1,0,1, 0); return 0; @@ -494,8 +494,8 @@ static int opINSL_a32(uint32_t fetchdat) check_io_perm(DX + 3); temp = inl(DX); writememl(es, EDI, temp); if (cpu_state.abrt) return 1; - if (flags & D_FLAG) EDI -= 4; - else EDI += 4; + if (cpu_state.flags & D_FLAG) EDI -= 4; + else EDI += 4; CLOCK_CYCLES(15); PREFETCH_RUN(15, 1, -1, 0,1,0,1, 1); return 0; @@ -508,8 +508,8 @@ static int opOUTSB_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; check_io_perm(DX); - if (flags & D_FLAG) SI--; - else SI++; + if (cpu_state.flags & D_FLAG) SI--; + else SI++; outb(DX, temp); CLOCK_CYCLES(14); PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0); @@ -522,8 +522,8 @@ static int opOUTSB_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; check_io_perm(DX); - if (flags & D_FLAG) ESI--; - else ESI++; + if (cpu_state.flags & D_FLAG) ESI--; + else ESI++; outb(DX, temp); CLOCK_CYCLES(14); PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1); @@ -538,8 +538,8 @@ static int opOUTSW_a16(uint32_t fetchdat) temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; check_io_perm(DX); check_io_perm(DX + 1); - if (flags & D_FLAG) SI -= 2; - else SI += 2; + if (cpu_state.flags & D_FLAG) SI -= 2; + else SI += 2; outw(DX, temp); CLOCK_CYCLES(14); PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0); @@ -553,8 +553,8 @@ static int opOUTSW_a32(uint32_t fetchdat) temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; check_io_perm(DX); check_io_perm(DX + 1); - if (flags & D_FLAG) ESI -= 2; - else ESI += 2; + if (cpu_state.flags & D_FLAG) ESI -= 2; + else ESI += 2; outw(DX, temp); CLOCK_CYCLES(14); PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1); @@ -571,8 +571,8 @@ static int opOUTSL_a16(uint32_t fetchdat) check_io_perm(DX + 1); check_io_perm(DX + 2); check_io_perm(DX + 3); - if (flags & D_FLAG) SI -= 4; - else SI += 4; + if (cpu_state.flags & D_FLAG) SI -= 4; + else SI += 4; outl(EDX, temp); CLOCK_CYCLES(14); PREFETCH_RUN(14, 1, -1, 0,1,0,1, 0); @@ -588,8 +588,8 @@ static int opOUTSL_a32(uint32_t fetchdat) check_io_perm(DX + 1); check_io_perm(DX + 2); check_io_perm(DX + 3); - if (flags & D_FLAG) ESI -= 4; - else ESI += 4; + if (cpu_state.flags & D_FLAG) ESI -= 4; + else ESI += 4; outl(EDX, temp); CLOCK_CYCLES(14); PREFETCH_RUN(14, 1, -1, 0,1,0,1, 1); diff --git a/src/x86seg.c b/src/x86seg.c index b508b87..547ed1b 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -115,21 +115,21 @@ void x86_doabrt(int x86_abrt) uint32_t addr = (x86_abrt << 2) + idt.base; if (stack32) { - writememw(ss,ESP-2,flags); + writememw(ss,ESP-2,cpu_state.flags); writememw(ss,ESP-4,CS); writememw(ss,ESP-6,cpu_state.pc); ESP-=6; } else { - writememw(ss,((SP-2)&0xFFFF),flags); + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); writememw(ss,((SP-4)&0xFFFF),CS); writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); SP-=6; } - flags&=~I_FLAG; - flags&=~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); @@ -315,7 +315,7 @@ int loadseg(uint16_t seg, x86seg *s) uint32_t addr; int dpl; - if (msw&1 && !(eflags&VM_FLAG)) + if (msw&1 && !(cpu_state.eflags&VM_FLAG)) { // intcount++; if (!(seg&~3)) @@ -499,7 +499,7 @@ void loadcs(uint16_t seg) uint16_t segdat[4]; uint32_t addr; if (output) pclog("Load CS %04X\n",seg); - if (msw&1 && !(eflags&VM_FLAG)) + if (msw&1 && !(cpu_state.eflags&VM_FLAG)) { // intcount++; // flushmmucache(); @@ -608,8 +608,8 @@ void loadcs(uint16_t seg) cpu_state.seg_cs.limit_low = 0; cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - if (eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; - else cpu_state.seg_cs.access=(0<<5) | 2; + if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; + else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); } } @@ -621,7 +621,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) uint16_t type,seg2; uint32_t newpc; // pclog("Load CS JMP %04X\n",seg); - if (msw&1 && !(eflags&VM_FLAG)) + if (msw&1 && !(cpu_state.eflags&VM_FLAG)) { if (!(seg&~3)) { @@ -827,7 +827,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) optype=JMP; cpl_override=1; taskswitch286(seg,segdat,segdat[2]&0x800); - flags &= ~NT_FLAG; + cpu_state.flags &= ~NT_FLAG; cpl_override=0; // case 0xB00: /*386 Busy task gate*/ // if (optype==JMP) pclog("Task switch!\n"); @@ -853,8 +853,8 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) cpu_state.seg_cs.limit_low = 0; cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - if (eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; - else cpu_state.seg_cs.access=(0<<5) | 2; + if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; + else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); cycles -= timing_jmp_rm; } @@ -941,7 +941,7 @@ void loadcscall(uint16_t seg) int csout = output; - if (msw&1 && !(eflags&VM_FLAG)) + if (msw&1 && !(cpu_state.eflags&VM_FLAG)) { //flushmmucache(); if (csout) pclog("Protected mode CS load! %04X\n",seg); @@ -1370,8 +1370,8 @@ void loadcscall(uint16_t seg) cpu_state.seg_cs.limit_low = 0; cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - if (eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; - else cpu_state.seg_cs.access=(0<<5) | 2; + if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; + else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); } } @@ -1383,7 +1383,7 @@ void pmoderetf(int is32, uint16_t off) uint32_t addr, oaddr; uint16_t segdat[4],segdat2[4],seg,newss; uint32_t oldsp=ESP; - if (output) pclog("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,eflags); + if (output) pclog("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,cpu_state.eflags); if (is32) { newpc=POPL(); @@ -1683,7 +1683,7 @@ void pmodeint(int num, int soft) // if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc); // pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt); - if (eflags&VM_FLAG && IOPL!=3 && soft) + if (cpu_state.eflags&VM_FLAG && IOPL!=3 && soft) { if (output) pclog("V86 banned int\n"); pclog("V86 banned int!\n"); @@ -1806,7 +1806,7 @@ void pmodeint(int num, int soft) x86np("Int gate CS not present\n", segdat[1] & 0xfffc); return; } - if ((eflags&VM_FLAG) && DPL2) + if ((cpu_state.eflags & VM_FLAG) && DPL2) { pclog("V86 calling int gate, DPL != 0\n"); x86gpf(NULL,segdat[1]&0xFFFC); @@ -1896,7 +1896,7 @@ void pmodeint(int num, int soft) if (type>=0x800) { // if (output) pclog("Push 32 %i\n",eflags&VM_FLAG); - if (eflags & VM_FLAG) + if (cpu_state.eflags & VM_FLAG) { PUSHL(GS); PUSHL(FS); @@ -1909,7 +1909,7 @@ void pmodeint(int num, int soft) } PUSHL(oldss); PUSHL(oldsp); - PUSHL(flags|(eflags<<16)); + PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); // if (soft) pclog("Pushl CS %08X\n", CS); PUSHL(CS); // if (soft) pclog("Pushl PC %08X\n", pc); @@ -1921,7 +1921,7 @@ void pmodeint(int num, int soft) // if (output) pclog("Push 16\n"); PUSHW(oldss); PUSHW(oldsp); - PUSHW(flags); + PUSHW(cpu_state.flags); // if (soft) pclog("Pushw CS %04X\n", CS); PUSHW(CS); // if (soft) pclog("Pushw pc %04X\n", pc); @@ -1947,7 +1947,7 @@ void pmodeint(int num, int soft) x86np("Int gate CS not present\n", segdat[1] & 0xfffc); return; } - if ((eflags & VM_FLAG) && DPL20x800) { - PUSHL(flags|(eflags<<16)); + PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); // if (soft) pclog("Pushlc CS %08X\n", CS); PUSHL(CS); // if (soft) pclog("Pushlc PC %08X\n", pc); @@ -1964,7 +1964,7 @@ void pmodeint(int num, int soft) } else { - PUSHW(flags); + PUSHW(cpu_state.flags); // if (soft) pclog("Pushwc CS %04X\n", CS); PUSHW(CS); // if (soft) pclog("Pushwc PC %04X\n", pc); @@ -1993,14 +1993,14 @@ void pmodeint(int num, int soft) cpl_override = 0; #endif - eflags&=~VM_FLAG; + cpu_state.eflags &= ~VM_FLAG; cpu_cur_status &= ~CPU_STATUS_V86; if (!(type&0x100)) { - flags&=~I_FLAG; + cpu_state.flags &= ~I_FLAG; // pclog("INT %02X disabling interrupts %i\n",num,soft); } - flags&=~(T_FLAG|NT_FLAG); + cpu_state.flags &= ~(T_FLAG|NT_FLAG); // if (output) pclog("Final Stack %04X:%08X\n",SS,ESP); cycles -= timing_int_pm; break; @@ -2065,7 +2065,7 @@ void pmodeiret(int is32) uint16_t seg = 0; uint32_t addr, oaddr; uint32_t oldsp=ESP; - if (is386 && (eflags&VM_FLAG)) + if (is386 && (cpu_state.eflags & VM_FLAG)) { // if (output) pclog("V86 IRET\n"); if (IOPL!=3) @@ -2093,7 +2093,7 @@ void pmodeiret(int is32) cpu_state.seg_cs.limit_low = 0; cpu_state.seg_cs.limit_high = 0xffff; CS=seg; - flags=(flags&0x3000)|(tempflags&0xCFD5)|2; + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempflags & 0xCFD5) | 2; cycles -= timing_iret_rm; return; } @@ -2102,7 +2102,7 @@ void pmodeiret(int is32) //flushmmucache(); // if (output) pclog("Pmode IRET %04X:%04X ",CS,pc); - if (flags&NT_FLAG) + if (cpu_state.flags & NT_FLAG) { // pclog("NT IRET\n"); seg=readmemw(tr.base,0); @@ -2155,7 +2155,7 @@ void pmodeiret(int is32) segs[2]=POPL(); segs[3]=POPL(); if (cpu_state.abrt) { ESP = oldsp; return; } // pclog("Pop stack %04X:%04X\n",newss,newsp); - eflags=tempflags>>16; + cpu_state.eflags = tempflags>>16; cpu_cur_status |= CPU_STATUS_V86; loadseg(segs[0],&cpu_state.seg_es); do_seg_v86_init(&cpu_state.seg_es); @@ -2185,7 +2185,7 @@ void pmodeiret(int is32) cpu_cur_status |= CPU_STATUS_NOTFLATSS; use32=0; cpu_cur_status &= ~CPU_STATUS_USE32; - flags=(tempflags&0xFFD5)|2; + cpu_state.flags = (tempflags&0xFFD5)|2; cycles -= timing_iret_v86; // pclog("V86 IRET to %04X:%04X %04X:%04X %04X %04X %04X %04X %i\n",CS,pc,SS,SP,DS,ES,FS,GS,abrt); // if (CS==0xFFFF && pc==0xFFFFFFFF) timetolive=12; @@ -2422,8 +2422,8 @@ void pmodeiret(int is32) cycles -= timing_iret_pm_outer; } cpu_state.pc=newpc; - flags=(flags&~flagmask)|(tempflags&flagmask&0xFFD5)|2; - if (is32) eflags=tempflags>>16; + cpu_state.flags = (cpu_state.flags&~flagmask) | (tempflags&flagmask&0xFFD5)|2; + if (is32) cpu_state.eflags = tempflags>>16; // pclog("done\n"); } @@ -2477,13 +2477,13 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) } if (cpu_state.abrt) return; - if (optype==IRET) flags&=~NT_FLAG; + if (optype==IRET) cpu_state.flags&=~NT_FLAG; // if (output) pclog("Write PC %08X %08X\n",tr.base,pc); cpu_386_flags_rebuild(); writememl(tr.base,0x1C,cr3); writememl(tr.base,0x20,cpu_state.pc); - writememl(tr.base,0x24,flags|(eflags<<16)); + writememl(tr.base,0x24,cpu_state.flags | (cpu_state.eflags<<16)); writememl(tr.base,0x28,EAX); writememl(tr.base,0x2C,ECX); @@ -2556,8 +2556,8 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) cpu_state.pc=new_pc; // if (output) pclog("New pc %08X\n",new_pc); - flags=new_flags; - eflags=new_flags>>16; + cpu_state.flags = new_flags; + cpu_state.eflags = new_flags>>16; cpu_386_flags_extract(); // if (output) pclog("Load LDT %04X\n",new_ldt); @@ -2574,7 +2574,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) // if (output) pclog("Limit %04X Base %08X\n",ldt.limit,ldt.base); - if (eflags & VM_FLAG) + if (cpu_state.eflags & VM_FLAG) { loadcs(new_cs); set_use32(0); @@ -2695,12 +2695,13 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) } if (cpu_state.abrt) return; - if (optype==IRET) flags&=~NT_FLAG; + if (optype == IRET) + cpu_state.flags &= ~NT_FLAG; // if (output) pclog("Write PC %08X %08X\n",tr.base,pc); cpu_386_flags_rebuild(); writememw(tr.base,0x0E,cpu_state.pc); - writememw(tr.base,0x10,flags); + writememw(tr.base,0x10,cpu_state.flags); writememw(tr.base,0x12,AX); writememw(tr.base,0x14,CX); @@ -2760,7 +2761,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) cpu_state.pc=new_pc; // if (output) pclog("New pc %08X\n",new_pc); - flags=new_flags; + cpu_state.flags = new_flags; cpu_386_flags_extract(); // if (output) pclog("Load LDT %04X\n",new_ldt); diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h index d5810c6..f52abe8 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -206,9 +206,9 @@ static int opFCOMI(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FICOM\n"); flags_rebuild(); - flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG; + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; CLOCK_CYCLES(4); return 0; } @@ -218,9 +218,9 @@ static int opFCOMIP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FICOMP\n"); flags_rebuild(); - flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG; + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; x87_pop(); CLOCK_CYCLES(4); return 0; @@ -415,9 +415,9 @@ static int opFUCOMI(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FUCOMI\n"); flags_rebuild(); - flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG; + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; CLOCK_CYCLES(4); return 0; } @@ -427,9 +427,9 @@ static int opFUCOMIP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FUCOMIP\n"); flags_rebuild(); - flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG; + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; x87_pop(); CLOCK_CYCLES(4); return 0; From e012420f90a563f752c6df5622c7ce623d9f1116 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 09:58:50 +0000 Subject: [PATCH 067/181] Added recompiled versions of CLC, CLD, CLI, CMC, STC, STD and STI. --- src/codegen_ops.c | 4 ++-- src/codegen_ops_misc.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/codegen_ops_misc.h | 10 +++++++++ src/codegen_reg.c | 2 ++ src/codegen_reg.h | 8 +++++-- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 8dc433a..3093ee5 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -43,7 +43,7 @@ RecompOpFn recomp_opcodes[512] = /*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES_16, ropLDS_16, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, ropRETF_imm_16, ropRETF_16, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, ropJMP_far_16, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_16, NULL, NULL, NULL, NULL, NULL, NULL, ropINCDEC, ropFF_16, +/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_16, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_16, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -65,7 +65,7 @@ RecompOpFn recomp_opcodes[512] = /*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES_32, ropLDS_32, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, ropRETF_imm_32, ropRETF_32, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, ropJMP_far_32, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_32, NULL, NULL, NULL, NULL, NULL, NULL, ropINCDEC, ropFF_32 +/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_32, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_32 }; diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index e3635e3..8afb20a 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -551,3 +551,50 @@ ropLxS(LES, &cpu_state.seg_es) ropLxS(LFS, &cpu_state.seg_fs) ropLxS(LGS, &cpu_state.seg_gs) ropLxS(LSS, &cpu_state.seg_ss) + +uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_CALL_FUNC(ir, flags_rebuild); + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG); + return op_pc; +} +uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_CALL_FUNC(ir, flags_rebuild); + uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); + return op_pc; +} +uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_CALL_FUNC(ir, flags_rebuild); + uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); + return op_pc; +} + +uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG); + return op_pc; +} +uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG); + return op_pc; +} + +uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; + + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG); + return op_pc; +} +uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; + + uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG); + return op_pc; +} diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h index 20f115d..8f2fd76 100644 --- a/src/codegen_ops_misc.h +++ b/src/codegen_ops_misc.h @@ -25,3 +25,13 @@ uint32_t ropLGS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uint32_t ropLGS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropLSS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropLSS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 9c19d10..7fa5ff2 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -134,6 +134,8 @@ struct [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER}, [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, + + [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER}, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 63a0b6d..aa35ab5 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -115,8 +115,10 @@ enum IREG_NPXCx = 72, IREG_NPXSx = 73, + + IREG_flagsx = 74, - IREG_COUNT = 74, + IREG_COUNT = 75, IREG_INVALID = 255, @@ -181,7 +183,9 @@ enum IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, IREG_NPXS = IREG_NPXSx + IREG_SIZE_W, - IREG_ssegs = IREG_ssegsx + IREG_SIZE_B + IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, + + IREG_flags = IREG_flagsx + IREG_SIZE_W }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) From 5df3f6caef29bc2da122203e3aace55b7939161c Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 11:50:24 +0000 Subject: [PATCH 068/181] Added recompiled versions of PUSHA and POPA. --- src/codegen_ops.c | 4 +-- src/codegen_ops_helpers.h | 4 +++ src/codegen_ops_stack.c | 73 +++++++++++++++++++++++++++++++++++++++ src/codegen_ops_stack.h | 6 ++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 3093ee5..29a9d39 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -32,7 +32,7 @@ RecompOpFn recomp_opcodes[512] = /*40*/ ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, /*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL, +/*60*/ ropPUSHA_16, ropPOPA_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL, /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W, @@ -54,7 +54,7 @@ RecompOpFn recomp_opcodes[512] = /*40*/ ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, /*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL, +/*60*/ ropPUSHA_32, ropPOPA_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL, /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L, diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index 8d9d911..1b4cf30 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -24,7 +24,11 @@ static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) return IREG_eaaddr; } } +} +static inline int LOAD_SP(ir_data_t *ir) +{ + return LOAD_SP_WITH_OFFSET(ir, 0); } static inline void ADD_SP(ir_data_t *ir, int offset) diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c index fb63e1d..09485b2 100644 --- a/src/codegen_ops_stack.c +++ b/src/codegen_ops_stack.c @@ -288,3 +288,76 @@ uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc; } + + +uint32_t ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -16); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI); + SUB_SP(ir, 16); + + return op_pc; +} +uint32_t ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -32); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI); + SUB_SP(ir, 32); + + return op_pc; +} + +uint32_t ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP(ir); + uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14); + ADD_SP(ir, 16); + + return op_pc; +} +uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP(ir); + uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28); + ADD_SP(ir, 32); + + return op_pc; +} diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 9af5d60..085c637 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -38,3 +38,9 @@ uint32_t ropPOP_GS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From 335cea3ee1a619f3826e198a5c8b1077ef6b27bd Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 15:19:21 +0000 Subject: [PATCH 069/181] Added recompiled versions of PUSHF and PUSHFD. --- src/codegen_ops.c | 4 ++-- src/codegen_ops_stack.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/codegen_ops_stack.h | 3 +++ src/codegen_reg.c | 3 ++- src/codegen_reg.h | 8 +++++--- 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 29a9d39..10b19d2 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -36,7 +36,7 @@ RecompOpFn recomp_opcodes[512] = /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W, -/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropCBW, ropCWD, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropCBW, ropCWD, NULL, NULL, ropPUSHF, NULL, NULL, NULL, /*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, @@ -58,7 +58,7 @@ RecompOpFn recomp_opcodes[512] = /*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8, /*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L, -/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropCWDE, ropCDQ, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropCWDE, ropCDQ, NULL, NULL, ropPUSHFD, NULL, NULL, NULL, /*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c index 09485b2..29d2bda 100644 --- a/src/codegen_ops_stack.c +++ b/src/codegen_ops_stack.c @@ -1,6 +1,7 @@ #include "ibm.h" #include "x86.h" +#include "x86_flags.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -361,3 +362,42 @@ uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t return op_pc; } + +uint32_t ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + return 0; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_CALL_FUNC(ir, flags_rebuild); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); + SUB_SP(ir, 2); + + return op_pc; +} +uint32_t ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int sp_reg; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + return 0; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_CALL_FUNC(ir, flags_rebuild); + + if (cpu_CR4_mask & CR4_VME) + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); + else if (CPUID) + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W); + SUB_SP(ir, 4); + + return op_pc; +} diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 085c637..6b9ac57 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -44,3 +44,6 @@ uint32_t ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 7fa5ff2..1e2fbb6 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -136,7 +136,8 @@ struct [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER}, - + [IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ diff --git a/src/codegen_reg.h b/src/codegen_reg.h index aa35ab5..2e76936 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -117,8 +117,9 @@ enum IREG_NPXSx = 73, IREG_flagsx = 74, - - IREG_COUNT = 75, + IREG_eflagsx = 75, + + IREG_COUNT = 76, IREG_INVALID = 255, @@ -185,7 +186,8 @@ enum IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, - IREG_flags = IREG_flagsx + IREG_SIZE_W + IREG_flags = IREG_flagsx + IREG_SIZE_W, + IREG_eflags = IREG_eflagsx + IREG_SIZE_W }; #define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) From 356f406b229fd1386fb6d1d4586bfc3c4e8a5df4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 18:41:53 +0000 Subject: [PATCH 070/181] Fix codegen pointer register reads. --- src/codegen_backend_arm64_uops.c | 14 ++++++++ src/codegen_backend_arm_ops.h | 2 ++ src/codegen_backend_arm_uops.c | 8 +++++ src/codegen_backend_x86-64_ops.c | 57 ++++++++++++++++++++++++++++++- src/codegen_backend_x86-64_ops.h | 1 + src/codegen_backend_x86-64_uops.c | 16 +++++++++ src/codegen_backend_x86_uops.c | 8 +++++ src/codegen_ir_defs.h | 4 +++ src/codegen_reg.c | 9 +++++ 9 files changed, 118 insertions(+), 1 deletion(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 0ee74dc..c7729af 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -2687,6 +2687,13 @@ void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_double - not in range\n"); } +void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +{ + if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) + host_arm64_LDR_IMM_X(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + else + fatal("codegen_direct_read_pointer - not in range\n"); +} void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) @@ -2801,6 +2808,13 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32_stack - not in range\n"); } +void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + if (in_range12_q(stack_offset)) + host_arm64_LDR_IMM_X(block, host_reg, REG_SP, stack_offset); + else + fatal("codegen_direct_read_pointer_stack - not in range\n"); +} void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { host_arm64_LDR_IMM_F64(block, host_reg, REG_SP, stack_offset); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 542dc2a..b7877df 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -215,6 +215,8 @@ void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shif void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg); + void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index a9ce03e..8ceebbc 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -2829,6 +2829,10 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +{ + codegen_direct_read_32(block, host_reg, p); +} void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); @@ -2941,6 +2945,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + codegen_direct_read_32_stack(block, host_reg, stack_offset); +} void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 4ec3fd4..04d0080 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -777,6 +777,25 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addlong(block, (uint32_t)(uintptr_t)p); } } +void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOV64_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } + else if (offset < (1ull << 32)) + { + codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } + else + fatal("host_x86_MOV64_REG_ABS - out of range\n"); +} void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) { @@ -845,11 +864,29 @@ void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); } +void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte(block, 0x48); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } + else + codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) { if ((src_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); + fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); if (offset >= -128 && offset < 127) { @@ -863,6 +900,24 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset else fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); } +void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_addbyte(block, 0x48); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } + else + codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + else + fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); +} void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 10fe26a..a86e3ed 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -92,6 +92,7 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index dc87d53..4955609 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -2430,6 +2430,10 @@ void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { host_x86_MOVQ_XREG_ABS(block, host_reg, p); } +void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +{ + host_x86_MOV64_REG_ABS(block, host_reg, p); +} void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { host_x86_MOVQ_XREG_ABS(block, host_reg, p); @@ -2478,6 +2482,10 @@ void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { host_x86_MOVQ_ABS_XREG(block, p, host_reg); } +void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg) +{ + host_x86_MOV64_ABS_REG(block, p, host_reg); +} void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { host_x86_MOVQ_ABS_XREG(block, p, host_reg); @@ -2527,6 +2535,10 @@ void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } +void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_x86_MOV64_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); @@ -2540,6 +2552,10 @@ void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int hos { host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); } +void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_x86_MOV64_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 20f39a7..67f28d4 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -2440,6 +2440,10 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { host_x86_MOV32_REG_ABS(block, host_reg, p); } +void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +{ + codegen_direct_read_32(block, host_reg, p); +} void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { host_x86_MOVQ_XREG_ABS(block, host_reg, p); @@ -2537,6 +2541,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of { host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } +void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + codegen_direct_read_32_stack(block, host_reg, stack_offset); +} void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 15b3014..2a2733e 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -688,6 +688,7 @@ void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p); +void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p); void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx); void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx); @@ -697,6 +698,7 @@ void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg); +void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg); void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg); @@ -706,10 +708,12 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset); +void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset); void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg); +void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg); void codegen_set_jump_dest(codeblock_t *block, void *p); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 1e2fbb6..7d993fd 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -253,6 +253,15 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, codegen_direct_read_64(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); break; + case REG_POINTER: + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n"); + if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_pointer_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_pointer(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; + case REG_DOUBLE: if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n"); From d63176e4726964cbb4e0874d8caab47bababf66d Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 18:43:40 +0000 Subject: [PATCH 071/181] Move dynarec code memory out of codeblock structure. --- src/codegen.h | 9 +++++++-- src/codegen_backend.c | 3 +++ src/codegen_backend_arm.c | 18 +++++++++++------- src/codegen_backend_arm64.c | 18 +++++++++++------- src/codegen_backend_x86-64.c | 10 +++++++--- src/codegen_backend_x86-64.h | 2 +- src/codegen_backend_x86.c | 16 ++++++++++------ src/codegen_backend_x86.h | 3 ++- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/codegen.h b/src/codegen.h index dcca68b..b212cbe 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -30,7 +30,10 @@ */ /*Hack until better memory management written*/ -#define BLOCK_DATA_SIZE 0x10000 +/*This is deliberately _not_ a power of two, to avoid cache aliasing problems. + Try changing this to a power of two, and watch the performance plummet :) + It's probably best for this to be a multiple of the cache line size though*/ +#define BLOCK_DATA_SIZE 0xff80 typedef struct codeblock_t { @@ -61,9 +64,11 @@ typedef struct codeblock_t uint32_t status; uint32_t flags; - uint8_t data[BLOCK_DATA_SIZE]; + uint8_t *data; } codeblock_t; +uint8_t *codeblock_data; + /*Code block uses FPU*/ #define CODEBLOCK_HAS_FPU 1 /*Code block is always entered with the same FPU top-of-stack*/ diff --git a/src/codegen_backend.c b/src/codegen_backend.c index fa01aa8..482e1e9 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -96,7 +96,10 @@ void codegen_reset() mem_reset_page_blocks(); for (c = 0; c < BLOCK_SIZE; c++) + { codeblock[c].pc = BLOCK_PC_INVALID; + codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; + } } void dump_block() diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 5852294..00c2a17 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -294,23 +294,27 @@ void codegen_backend_init() #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE); #endif - if (!codeblock) - fatal("codeblock failed to alloc - %i\n", (BLOCK_SIZE+1) * sizeof(codeblock_t)); + if (!codeblock_data) + fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) + for (c = 0; c < BLOCK_SIZE+1; c++) + { codeblock[c].pc = BLOCK_PC_INVALID; + codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; + } #if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock & pagemask); - len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + start = (void *)((long)codeblock_data & pagemask); + len = (((BLOCK_SIZE+1) * BLOCK_DATA_SIZE) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index f201c4b..839f37e 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -289,23 +289,27 @@ void codegen_backend_init() #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE); #endif - if (!codeblock) - fatal("codeblock failed to alloc - %i\n", (BLOCK_SIZE+1) * sizeof(codeblock_t)); + if (!codeblock_data) + fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) + for (c = 0; c < BLOCK_SIZE+1; c++) + { codeblock[c].pc = BLOCK_PC_INVALID; + codeblock[c].data = &codeblock_data[c * BLOCK_SIZE]; + } #if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock & pagemask); - len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + start = (void *)((long)codeblock_data & pagemask); + len = (((BLOCK_SIZE+1) * BLOCK_DATA_SIZE) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index bb92241..c509c04 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -276,17 +276,21 @@ void codegen_backend_init() #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE); #endif + codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) + for (c = 0; c < BLOCK_SIZE+1; c++) + { + codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; + } #if defined(__linux__) || defined(__APPLE__) start = (void *)((long)codeblock & pagemask); diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h index 50797ef..4e9ec51 100644 --- a/src/codegen_backend_x86-64.h +++ b/src/codegen_backend_x86-64.h @@ -10,7 +10,7 @@ #define HASH(l) ((l) & 0x1ffff) /*Hack until better memory management written*/ -#define BLOCK_EXIT_OFFSET 0xffe0 +#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 32) /*#define BLOCK_EXIT_OFFSET 0x7f0*/ #define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index daeff4d..675d9fe 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -261,22 +261,26 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); +#if defined WIN32 || defined _WIN32 || defined _WIN32 + codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE; #endif codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) + for (c = 0; c < BLOCK_SIZE + 1; c++) + { + codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; + } #if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock & pagemask); - len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + start = (void *)((long)codeblock_data & pagemask); + len = (((BLOCK_SIZE+1) * BLOCK_DATA_SIZE) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h index 5face4e..13ccfab 100644 --- a/src/codegen_backend_x86.h +++ b/src/codegen_backend_x86.h @@ -10,7 +10,8 @@ #define HASH(l) ((l) & 0x1ffff) /*Hack until better memory management written*/ -#define BLOCK_EXIT_OFFSET 0xfff0 +#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 16) +//#define BLOCK_EXIT_OFFSET 0xfff0 /*#define BLOCK_EXIT_OFFSET 0x7f0*/ #define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) From 2007c25177e0bbc5488f949caa4940da3a155206 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 28 Nov 2018 20:29:48 +0000 Subject: [PATCH 072/181] Start reducing size of codeblock_t structure. Re-arrange all variables needed to run a block to fit in a single cache line. --- src/386_dynarec.c | 9 ++++---- src/codegen.h | 45 +++++++++++++++++++-------------------- src/codegen_backend.c | 14 ++++++------ src/codegen_backend_x86.c | 24 ++++++++++++++++++++- src/ibm.h | 10 ++++----- 5 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index bdb1aa7..eb727b0 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -19,7 +19,7 @@ #define CPU_BLOCK_END() cpu_block_end = 1 -uint32_t cpu_cur_status = 0; +uint16_t cpu_cur_status = 0; int cpu_reps, cpu_reps_latched; int cpu_notreps, cpu_notreps_latched; @@ -663,16 +663,15 @@ void exec386_dynarec(int cycs) valid_block = 0; } } - if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) { /*FPU top-of-stack does not match the value this block was compiled with, re-compile using dynamic top-of-stack*/ - block->flags &= ~CODEBLOCK_STATIC_TOP; - block->was_recompiled = 0; + block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); } } - if (valid_block && block->was_recompiled) + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED)) { void (*code)() = (void *)&block->data[BLOCK_START]; diff --git a/src/codegen.h b/src/codegen.h index b212cbe..f9d357c 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -37,10 +37,19 @@ typedef struct codeblock_t { + uint32_t pc; + uint32_t _cs; + uint32_t phys, phys_2; + uint16_t status; + uint16_t flags; + uint16_t ins; + uint8_t TOP; + uint32_t endpc; + uint8_t *data; + uint64_t page_mask, page_mask2; uint64_t *dirty_mask, *dirty_mask2; - uint64_t cmp; - + /*Previous and next pointers, for the codeblock list associated with each physical page. Two sets of pointers, as a codeblock can be present in two pages.*/ @@ -50,21 +59,6 @@ typedef struct codeblock_t /*Pointers for codeblock tree, used to search for blocks when hash lookup fails.*/ struct codeblock_t *parent, *left, *right; - - int pnt; - int ins; - - int was_recompiled; - int TOP; - - uint32_t pc; - uint32_t _cs; - uint32_t endpc; - uint32_t phys, phys_2; - uint32_t status; - uint32_t flags; - - uint8_t *data; } codeblock_t; uint8_t *codeblock_data; @@ -73,6 +67,8 @@ uint8_t *codeblock_data; #define CODEBLOCK_HAS_FPU 1 /*Code block is always entered with the same FPU top-of-stack*/ #define CODEBLOCK_STATIC_TOP 2 +/*Code block has been compiled*/ +#define CODEBLOCK_WAS_RECOMPILED 4 #define BLOCK_PC_INVALID 0xffffffff @@ -83,13 +79,14 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) while (block) { - if (a == block->cmp) + uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32); + if (a == block_cmp) { if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) break; } - if (a < block->cmp) + if (a < block_cmp) block = block->left; else block = block->right; @@ -102,8 +99,7 @@ static inline void codeblock_tree_add(codeblock_t *new_block) { codeblock_t *block = pages[new_block->phys >> 12].head; uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); - new_block->cmp = a; - + if (!block) { pages[new_block->phys >> 12].head = new_block; @@ -112,17 +108,20 @@ static inline void codeblock_tree_add(codeblock_t *new_block) else { codeblock_t *old_block = NULL; + uint64_t old_block_cmp; while (block) { old_block = block; - if (a < old_block->cmp) + old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32); + + if (a < old_block_cmp) block = block->left; else block = block->right; } - if (a < old_block->cmp) + if (a < old_block_cmp) old_block->left = new_block; else old_block->right = new_block; diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 482e1e9..a24b7a5 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -277,7 +277,6 @@ void codegen_block_init(uint32_t phys_addr) block->ins = 0; block->pc = cs + cpu_state.pc; block->_cs = cs; - block->pnt = block_current; block->phys = phys_addr; block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; block->dirty_mask2 = NULL; @@ -287,8 +286,6 @@ void codegen_block_init(uint32_t phys_addr) block->flags = CODEBLOCK_STATIC_TOP; block->status = cpu_cur_status; - block->was_recompiled = 0; - recomp_page = block->phys & ~0xfff; codeblock_tree_add(block); @@ -301,6 +298,11 @@ ir_data_t *codegen_get_ir_data() return ir_data; } +static int get_block_nr(codeblock_t *block) +{ + return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t); +} + void codegen_block_start_recompile(codeblock_t *block) { page_t *page = &pages[block->phys >> 12]; @@ -309,9 +311,9 @@ void codegen_block_start_recompile(codeblock_t *block) mem_flush_write_page(block->phys, cs+cpu_state.pc); block_num = HASH(block->phys); - block_current = block->pnt; + block_current = get_block_nr(block);//block->pnt; - if (block->pc != cs + cpu_state.pc || block->was_recompiled) + if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) fatal("Recompile to used block!\n"); block->status = cpu_cur_status; @@ -342,7 +344,7 @@ void codegen_block_start_recompile(codeblock_t *block) cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; block->TOP = cpu_state.TOP & 7; - block->was_recompiled = 1; + block->flags |= CODEBLOCK_WAS_RECOMPILED; codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 675d9fe..0fd6104 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -1,5 +1,6 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 +#include #include "ibm.h" #include "codegen.h" #include "codegen_backend.h" @@ -260,7 +261,28 @@ void codegen_backend_init() long pagesize = sysconf(_SC_PAGESIZE); long pagemask = ~(pagesize - 1); #endif - +pclog("sizeof(codeblock_t)=%i\n", sizeof(codeblock_t)); +pclog(" offsetof(codeblock_t, pc)=%i\n", offsetof(codeblock_t, pc)); +pclog(" offsetof(codeblock_t, _cs)=%i\n", offsetof(codeblock_t, _cs)); +pclog(" offsetof(codeblock_t, phys)=%i\n", offsetof(codeblock_t, phys)); +pclog(" offsetof(codeblock_t, phys_2)=%i\n", offsetof(codeblock_t, phys_2)); +pclog(" offsetof(codeblock_t, status)=%i\n", offsetof(codeblock_t, status)); +pclog(" offsetof(codeblock_t, flags)=%i\n", offsetof(codeblock_t, flags)); +pclog(" offsetof(codeblock_t, ins)=%i\n", offsetof(codeblock_t, ins)); +pclog(" offsetof(codeblock_t, TOP)=%i\n", offsetof(codeblock_t, TOP)); +pclog(" offsetof(codeblock_t, endpc)=%i\n", offsetof(codeblock_t, endpc)); +pclog(" offsetof(codeblock_t, data)=%i\n", offsetof(codeblock_t, data)); +pclog(" offsetof(codeblock_t, page_mask=%i\n", offsetof(codeblock_t, page_mask)); +pclog(" offsetof(codeblock_t, page_mask2=%i\n", offsetof(codeblock_t, page_mask2)); +pclog(" offsetof(codeblock_t, dirty_mask=%i\n", offsetof(codeblock_t, dirty_mask)); +pclog(" offsetof(codeblock_t, dirty_mask2=%i\n", offsetof(codeblock_t, dirty_mask2)); +pclog(" offsetof(codeblock_t, prev=%i\n", offsetof(codeblock_t, prev)); +pclog(" offsetof(codeblock_t, next=%i\n", offsetof(codeblock_t, next)); +pclog(" offsetof(codeblock_t, prev_2=%i\n", offsetof(codeblock_t, prev_2)); +pclog(" offsetof(codeblock_t, next_2=%i\n", offsetof(codeblock_t, next_2)); +pclog(" offsetof(codeblock_t, parent=%i\n", offsetof(codeblock_t, parent)); +pclog(" offsetof(codeblock_t, left=%i\n", offsetof(codeblock_t, left)); +pclog(" offsetof(codeblock_t, right=%i\n", offsetof(codeblock_t, right)); codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); #if defined WIN32 || defined _WIN32 || defined _WIN32 codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); diff --git a/src/ibm.h b/src/ibm.h index e6488e4..2221e8c 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -194,7 +194,7 @@ struct #define cycles cpu_state._cycles -extern uint32_t cpu_cur_status; +extern uint16_t cpu_cur_status; /*The flags below must match in both cpu_cur_status and block->status for a block to be valid*/ @@ -202,13 +202,13 @@ extern uint32_t cpu_cur_status; #define CPU_STATUS_STACK32 (1 << 1) #define CPU_STATUS_PMODE (1 << 2) #define CPU_STATUS_V86 (1 << 3) -#define CPU_STATUS_FLAGS 0xffff +#define CPU_STATUS_FLAGS 0xff /*If the flags below are set in cpu_cur_status, they must be set in block->status. Otherwise they are ignored*/ -#define CPU_STATUS_NOTFLATDS (1 << 16) -#define CPU_STATUS_NOTFLATSS (1 << 17) -#define CPU_STATUS_MASK 0xffff0000 +#define CPU_STATUS_NOTFLATDS (1 << 8) +#define CPU_STATUS_NOTFLATSS (1 << 9) +#define CPU_STATUS_MASK 0xff00 #define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; From 9ff1c7f409facd27148d798ce1cb205558fc594c Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 29 Nov 2018 20:05:12 +0000 Subject: [PATCH 073/181] Further reductions to codeblock_t size - replace link pointers with uint16_t block indicies, shrink ins to uint8_t, remove endpc. codeblock_t now fits in a 64-byte cacheline on 32-bit platforms. --- src/386_dynarec.c | 2 +- src/codegen.h | 155 ++++++++++++++++++++--------------- src/codegen_backend.c | 102 +++++++++++------------ src/codegen_backend_arm.c | 14 ++-- src/codegen_backend_arm64.c | 14 ++-- src/codegen_backend_x86-64.c | 14 ++-- src/codegen_backend_x86.c | 37 ++++----- src/mem.c | 4 +- src/mem.h | 4 +- 9 files changed, 186 insertions(+), 160 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index eb727b0..8954538 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -651,7 +651,7 @@ void exec386_dynarec(int cycs) allow the first page to be interpreted and for the page fault to occur when the page boundary is actually crossed.*/ - uint32_t phys_addr_2 = get_phys_noabrt(block->endpc); + uint32_t phys_addr_2 = get_phys_noabrt(block->pc + 0x400); page_t *page_2 = &pages[phys_addr_2 >> 12]; if ((block->phys_2 ^ phys_addr_2) & ~0xfff) valid_block = 0; diff --git a/src/codegen.h b/src/codegen.h index f9d357c..72a3820 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -42,9 +42,13 @@ typedef struct codeblock_t uint32_t phys, phys_2; uint16_t status; uint16_t flags; - uint16_t ins; + uint8_t ins; uint8_t TOP; - uint32_t endpc; + + /*Pointers for codeblock tree, used to search for blocks when hash lookup + fails.*/ + uint16_t parent, left, right; + uint8_t *data; uint64_t page_mask, page_mask2; @@ -53,16 +57,16 @@ typedef struct codeblock_t /*Previous and next pointers, for the codeblock list associated with each physical page. Two sets of pointers, as a codeblock can be present in two pages.*/ - struct codeblock_t *prev, *next; - struct codeblock_t *prev_2, *next_2; - - /*Pointers for codeblock tree, used to search for blocks when hash lookup - fails.*/ - struct codeblock_t *parent, *left, *right; + uint16_t prev, next; + uint16_t prev_2, next_2; } codeblock_t; uint8_t *codeblock_data; +extern codeblock_t *codeblock; + +extern codeblock_t **codeblock_hash; + /*Code block uses FPU*/ #define CODEBLOCK_HAS_FPU 1 /*Code block is always entered with the same FPU top-of-stack*/ @@ -72,11 +76,22 @@ uint8_t *codeblock_data; #define BLOCK_PC_INVALID 0xffffffff +#define BLOCK_INVALID 0 + +static inline int get_block_nr(codeblock_t *block) +{ + return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t); +} + static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) { - codeblock_t *block = pages[phys >> 12].head; + codeblock_t *block; uint64_t a = _cs | ((uint64_t)phys << 32); + if (!pages[phys >> 12].head) + return NULL; + + block = &codeblock[pages[phys >> 12].head]; while (block) { uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32); @@ -87,9 +102,9 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) break; } if (a < block_cmp) - block = block->left; + block = block->left ? &codeblock[block->left] : NULL; else - block = block->right; + block = block->right ? &codeblock[block->right] : NULL; } return block; @@ -97,18 +112,18 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) static inline void codeblock_tree_add(codeblock_t *new_block) { - codeblock_t *block = pages[new_block->phys >> 12].head; + codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head]; uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); - if (!block) + if (!pages[new_block->phys >> 12].head) { - pages[new_block->phys >> 12].head = new_block; - new_block->parent = new_block->left = new_block->right = NULL; + pages[new_block->phys >> 12].head = get_block_nr(new_block); + new_block->parent = new_block->left = new_block->right = BLOCK_INVALID; } else { codeblock_t *old_block = NULL; - uint64_t old_block_cmp; + uint64_t old_block_cmp = 0; while (block) { @@ -116,58 +131,68 @@ static inline void codeblock_tree_add(codeblock_t *new_block) old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32); if (a < old_block_cmp) - block = block->left; + block = block->left ? &codeblock[block->left] : NULL; else - block = block->right; + block = block->right ? &codeblock[block->right] : NULL; } if (a < old_block_cmp) - old_block->left = new_block; + old_block->left = get_block_nr(new_block); else - old_block->right = new_block; + old_block->right = get_block_nr(new_block); - new_block->parent = old_block; - new_block->left = new_block->right = NULL; + new_block->parent = get_block_nr(old_block); + new_block->left = new_block->right = BLOCK_INVALID; } } static inline void codeblock_tree_delete(codeblock_t *block) { - codeblock_t *parent = block->parent; + uint16_t parent_nr = block->parent; + codeblock_t *parent; + + if (block->parent) + parent = &codeblock[block->parent]; + else + parent = NULL; if (!block->left && !block->right) { /*Easy case - remove from parent*/ if (!parent) - pages[block->phys >> 12].head = NULL; + pages[block->phys >> 12].head = BLOCK_INVALID; else { - if (parent->left == block) - parent->left = NULL; - if (parent->right == block) - parent->right = NULL; + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) + parent->left = BLOCK_INVALID; + if (parent->right == block_nr) + parent->right = BLOCK_INVALID; } return; } else if (!block->left) { /*Only right node*/ - if (!parent) + if (!parent_nr) { pages[block->phys >> 12].head = block->right; - pages[block->phys >> 12].head->parent = NULL; + codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; } else { - if (parent->left == block) + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) { parent->left = block->right; - parent->left->parent = parent; + codeblock[parent->left].parent = parent_nr; } - if (parent->right == block) + if (parent->right == block_nr) { parent->right = block->right; - parent->right->parent = parent; + codeblock[parent->right].parent = parent_nr; } } return; @@ -175,22 +200,24 @@ static inline void codeblock_tree_delete(codeblock_t *block) else if (!block->right) { /*Only left node*/ - if (!parent) + if (!parent_nr) { pages[block->phys >> 12].head = block->left; - pages[block->phys >> 12].head->parent = NULL; + codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; } else { - if (parent->left == block) + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) { parent->left = block->left; - parent->left->parent = parent; + codeblock[parent->left].parent = parent_nr; } - if (parent->right == block) + if (parent->right == block_nr) { parent->right = block->left; - parent->right->parent = parent; + codeblock[parent->right].parent = parent_nr; } } return; @@ -198,50 +225,54 @@ static inline void codeblock_tree_delete(codeblock_t *block) else { /*Difficult case - node has two children. Walk right child to find lowest node*/ - codeblock_t *lowest = block->right, *highest; + codeblock_t *lowest = &codeblock[block->right], *highest; codeblock_t *old_parent; + uint16_t lowest_nr; while (lowest->left) - lowest = lowest->left; - - old_parent = lowest->parent; + lowest = &codeblock[lowest->left]; + lowest_nr = get_block_nr(lowest); + + old_parent = &codeblock[lowest->parent]; /*Replace deleted node with lowest node*/ - if (!parent) - pages[block->phys >> 12].head = lowest; + if (!parent_nr) + pages[block->phys >> 12].head = lowest_nr; else { - if (parent->left == block) - parent->left = lowest; - if (parent->right == block) - parent->right = lowest; + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) + parent->left = lowest_nr; + if (parent->right == block_nr) + parent->right = lowest_nr; } - lowest->parent = parent; + lowest->parent = parent_nr; lowest->left = block->left; if (lowest->left) - lowest->left->parent = lowest; + codeblock[lowest->left].parent = lowest_nr; - old_parent->left = NULL; + old_parent->left = BLOCK_INVALID; - highest = lowest->right; - if (!highest) + highest = &codeblock[lowest->right]; + if (!lowest->right) { - if (lowest != block->right) + if (lowest_nr != block->right) { lowest->right = block->right; - block->right->parent = lowest; + codeblock[block->right].parent = lowest_nr; } return; } while (highest->right) - highest = highest->right; + highest = &codeblock[highest->right]; - if (block->right && block->right != lowest) + if (block->right && block->right != lowest_nr) { highest->right = block->right; - block->right->parent = highest; + codeblock[block->right].parent = get_block_nr(highest); } } } @@ -251,10 +282,6 @@ static inline void codeblock_tree_delete(codeblock_t *block) #define PAGE_MASK_MASK 63 #define PAGE_MASK_SHIFT 4 -extern codeblock_t *codeblock; - -extern codeblock_t **codeblock_hash; - void codegen_init(); void codegen_close(); void codegen_reset(); diff --git a/src/codegen_backend.c b/src/codegen_backend.c index a24b7a5..de292e3 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -122,43 +122,44 @@ void dump_block() static void add_to_block_list(codeblock_t *block) { - codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + uint16_t block_prev_nr = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + uint16_t block_nr = get_block_nr(block); if (!block->page_mask) fatal("add_to_block_list - mask = 0\n"); - if (block_prev) + if (block_prev_nr) { - block->next = block_prev; - block_prev->prev = block; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + block->next = block_prev_nr; + codeblock[block_prev_nr].prev = block_nr; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block_nr; } else { - block->next = NULL; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + block->next = BLOCK_INVALID; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block_nr; } if (block->next) { - if (block->next->pc == BLOCK_PC_INVALID) - fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); + if (codeblock[block->next].pc == BLOCK_PC_INVALID) + fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos); } if (block->page_mask2) { - block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + block_prev_nr = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; - if (block_prev) + if (block_prev_nr) { - block->next_2 = block_prev; - block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + block->next_2 = block_prev_nr; + codeblock[block_prev_nr].prev_2 = block_nr; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block_nr; } else { - block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + block->next_2 = BLOCK_INVALID; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block_nr; } } } @@ -170,15 +171,15 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) if (block->prev) { - block->prev->next = block->next; + codeblock[block->prev].next = block->next; if (block->next) - block->next->prev = block->prev; + codeblock[block->next].prev = block->prev; } else { pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; if (block->next) - block->next->prev = NULL; + codeblock[block->next].prev = BLOCK_INVALID; else mem_flush_write_page(block->phys, 0); } @@ -191,16 +192,16 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) if (block->prev_2) { - block->prev_2->next_2 = block->next_2; + codeblock[block->prev_2].next_2 = block->next_2; if (block->next_2) - block->next_2->prev_2 = block->prev_2; + codeblock[block->next_2].prev_2 = block->prev_2; } else { // pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; if (block->next_2) - block->next_2->prev_2 = NULL; + codeblock[block->next_2].prev_2 = BLOCK_INVALID; else mem_flush_write_page(block->phys_2, 0); } @@ -223,32 +224,36 @@ static void delete_block(codeblock_t *block) void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) { - struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; + uint16_t block_nr = page->block[(phys_addr >> 10) & 3]; - while (block) + while (block_nr) { + codeblock_t *block = &codeblock[block_nr]; + if (mask & block->page_mask) { delete_block(block); cpu_recomp_evicted++; } - if (block == block->next) + if (block == &codeblock[block->next]) fatal("Broken 1\n"); - block = block->next; + block_nr = block->next; } - block = page->block_2[(phys_addr >> 10) & 3]; + block_nr = page->block_2[(phys_addr >> 10) & 3]; - while (block) + while (block_nr) { + codeblock_t *block = &codeblock[block_nr]; + if (mask & block->page_mask2) { delete_block(block); cpu_recomp_evicted++; } - if (block == block->next_2) + if (block == &codeblock[block->next_2]) fatal("Broken 2\n"); - block = block->next_2; + block_nr = block->next_2; } } @@ -261,6 +266,8 @@ void codegen_block_init(uint32_t phys_addr) mem_flush_write_page(phys_addr, cs+cpu_state.pc); block_current = (block_current + 1) & BLOCK_MASK; + if (!block_current) + block_current++; block = &codeblock[block_current]; // if (block->pc == 0xb00b4ff5) @@ -280,8 +287,8 @@ void codegen_block_init(uint32_t phys_addr) block->phys = phys_addr; block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; block->dirty_mask2 = NULL; - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; + block->next = block->prev = BLOCK_INVALID; + block->next_2 = block->prev_2 = BLOCK_INVALID; block->page_mask = 0; block->flags = CODEBLOCK_STATIC_TOP; block->status = cpu_cur_status; @@ -298,11 +305,6 @@ ir_data_t *codegen_get_ir_data() return ir_data; } -static int get_block_nr(codeblock_t *block) -{ - return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t); -} - void codegen_block_start_recompile(codeblock_t *block) { page_t *page = &pages[block->phys >> 12]; @@ -372,14 +374,12 @@ void codegen_block_generate_end_mask() uint32_t start_pc; uint32_t end_pc; - block->endpc = codegen_endpc; - block->page_mask = 0; start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ block->endpc) & ~0x3ff) + if ((block->pc ^ codegen_endpc) & ~0x3ff) end_pc = 0x3ff & ~15; else - end_pc = (block->endpc & 0x3ff) & ~15; + end_pc = (codegen_endpc & 0x3ff) & ~15; if (end_pc < start_pc) end_pc = 0x3ff; start_pc >>= PAGE_MASK_SHIFT; @@ -396,37 +396,37 @@ void codegen_block_generate_end_mask() block->phys_2 = -1; block->page_mask2 = 0; - block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0x3ff) + block->next_2 = block->prev_2 = BLOCK_INVALID; + if ((block->pc ^ codegen_endpc) & ~0x3ff) { - block->phys_2 = get_phys_noabrt(block->endpc); + block->phys_2 = get_phys_noabrt(codegen_endpc); if (block->phys_2 != -1) { page_t *page_2 = &pages[block->phys_2 >> 12]; start_pc = 0; - end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; + end_pc = (codegen_endpc & 0x3ff) >> PAGE_MASK_SHIFT; for (; start_pc <= end_pc; start_pc++) block->page_mask2 |= ((uint64_t)1 << start_pc); page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) - mem_flush_write_page(block->phys_2, block->endpc); + mem_flush_write_page(block->phys_2, codegen_endpc); if (!block->page_mask2) fatal("!page_mask2\n"); if (block->next_2) { // pclog(" next_2->pc=%08x\n", block->next_2->pc); - if (block->next_2->pc == BLOCK_PC_INVALID) - fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)block->next_2); + if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); } block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; } } -// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); +// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask); recomp_page = -1; } @@ -443,8 +443,8 @@ void codegen_block_end_recompile(codeblock_t *block) codegen_timing_block_end(); remove_from_block_list(block, block->pc); - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; + block->next = block->prev = BLOCK_INVALID; + block->next_2 = block->prev_2 = BLOCK_INVALID; codegen_block_generate_end_mask(); add_to_block_list(block); // pclog("End block %i\n", block_num); diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index 00c2a17..d2b0fe4 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -294,19 +294,19 @@ void codegen_backend_init() #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE); + codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); #endif if (!codeblock_data) fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE+1; c++) + for (c = 0; c < BLOCK_SIZE; c++) { codeblock[c].pc = BLOCK_PC_INVALID; codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; @@ -314,7 +314,7 @@ void codegen_backend_init() #if defined(__linux__) || defined(__APPLE__) start = (void *)((long)codeblock_data & pagemask); - len = (((BLOCK_SIZE+1) * BLOCK_DATA_SIZE) + pagesize) & pagemask; + len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); @@ -323,7 +323,7 @@ void codegen_backend_init() #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); - block_current = BLOCK_SIZE; + block_current = 0; block_pos = 0; build_loadstore_routines(&codeblock[block_current]); diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 839f37e..534df5c 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -289,19 +289,19 @@ void codegen_backend_init() #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE); + codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); #endif if (!codeblock_data) fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE+1; c++) + for (c = 0; c < BLOCK_SIZE; c++) { codeblock[c].pc = BLOCK_PC_INVALID; codeblock[c].data = &codeblock_data[c * BLOCK_SIZE]; @@ -309,7 +309,7 @@ void codegen_backend_init() #if defined(__linux__) || defined(__APPLE__) start = (void *)((long)codeblock_data & pagemask); - len = (((BLOCK_SIZE+1) * BLOCK_DATA_SIZE) + pagesize) & pagemask; + len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); @@ -318,7 +318,7 @@ void codegen_backend_init() #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); - block_current = BLOCK_SIZE; + block_current = 0; block_pos = 0; codegen_reset_literal_pool(&codeblock[block_current]); build_loadstore_routines(&codeblock[block_current]); diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index c509c04..631402a 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -276,17 +276,17 @@ void codegen_backend_init() #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE); + codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); #endif - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE+1; c++) + for (c = 0; c < BLOCK_SIZE; c++) { codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; @@ -294,7 +294,7 @@ void codegen_backend_init() #if defined(__linux__) || defined(__APPLE__) start = (void *)((long)codeblock & pagemask); - len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask; + len = ((BLOCK_SIZE * sizeof(codeblock_t)) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); @@ -303,7 +303,7 @@ void codegen_backend_init() #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); - block_current = BLOCK_SIZE; + block_current = 0; block_pos = 0; build_loadstore_routines(&codeblock[block_current]); // fatal("Here\n"); diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 0fd6104..4a43ff0 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -270,31 +270,30 @@ pclog(" offsetof(codeblock_t, status)=%i\n", offsetof(codeblock_t, status)); pclog(" offsetof(codeblock_t, flags)=%i\n", offsetof(codeblock_t, flags)); pclog(" offsetof(codeblock_t, ins)=%i\n", offsetof(codeblock_t, ins)); pclog(" offsetof(codeblock_t, TOP)=%i\n", offsetof(codeblock_t, TOP)); -pclog(" offsetof(codeblock_t, endpc)=%i\n", offsetof(codeblock_t, endpc)); +pclog(" offsetof(codeblock_t, parent)=%i\n", offsetof(codeblock_t, parent)); +pclog(" offsetof(codeblock_t, left)=%i\n", offsetof(codeblock_t, left)); +pclog(" offsetof(codeblock_t, right)=%i\n", offsetof(codeblock_t, right)); pclog(" offsetof(codeblock_t, data)=%i\n", offsetof(codeblock_t, data)); -pclog(" offsetof(codeblock_t, page_mask=%i\n", offsetof(codeblock_t, page_mask)); -pclog(" offsetof(codeblock_t, page_mask2=%i\n", offsetof(codeblock_t, page_mask2)); -pclog(" offsetof(codeblock_t, dirty_mask=%i\n", offsetof(codeblock_t, dirty_mask)); -pclog(" offsetof(codeblock_t, dirty_mask2=%i\n", offsetof(codeblock_t, dirty_mask2)); -pclog(" offsetof(codeblock_t, prev=%i\n", offsetof(codeblock_t, prev)); -pclog(" offsetof(codeblock_t, next=%i\n", offsetof(codeblock_t, next)); -pclog(" offsetof(codeblock_t, prev_2=%i\n", offsetof(codeblock_t, prev_2)); -pclog(" offsetof(codeblock_t, next_2=%i\n", offsetof(codeblock_t, next_2)); -pclog(" offsetof(codeblock_t, parent=%i\n", offsetof(codeblock_t, parent)); -pclog(" offsetof(codeblock_t, left=%i\n", offsetof(codeblock_t, left)); -pclog(" offsetof(codeblock_t, right=%i\n", offsetof(codeblock_t, right)); - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); +pclog(" offsetof(codeblock_t, page_mask)=%i\n", offsetof(codeblock_t, page_mask)); +pclog(" offsetof(codeblock_t, page_mask2)=%i\n", offsetof(codeblock_t, page_mask2)); +pclog(" offsetof(codeblock_t, dirty_mask)=%i\n", offsetof(codeblock_t, dirty_mask)); +pclog(" offsetof(codeblock_t, dirty_mask2)=%i\n", offsetof(codeblock_t, dirty_mask2)); +pclog(" offsetof(codeblock_t, prev)=%i\n", offsetof(codeblock_t, prev)); +pclog(" offsetof(codeblock_t, next)=%i\n", offsetof(codeblock_t, next)); +pclog(" offsetof(codeblock_t, prev_2)=%i\n", offsetof(codeblock_t, prev_2)); +pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); #if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, (BLOCK_SIZE+1) * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock_data = malloc((BLOCK_SIZE+1) * BLOCK_DATA_SIZE; + codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE; #endif codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE + 1; c++) + for (c = 0; c < BLOCK_SIZE; c++) { codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; @@ -302,7 +301,7 @@ pclog(" offsetof(codeblock_t, right=%i\n", offsetof(codeblock_t, right)); #if defined(__linux__) || defined(__APPLE__) start = (void *)((long)codeblock_data & pagemask); - len = (((BLOCK_SIZE+1) * BLOCK_DATA_SIZE) + pagesize) & pagemask; + len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { perror("mprotect"); @@ -311,7 +310,7 @@ pclog(" offsetof(codeblock_t, right=%i\n", offsetof(codeblock_t, right)); #endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); - block_current = BLOCK_SIZE; + block_current = 0; block_pos = 0; mem_abrt_rout = &codeblock[block_current].data[block_pos]; addbyte(0x83); /*ADDL $16+4,%esp*/ diff --git a/src/mem.c b/src/mem.c index 6fa3a69..ad095a3 100644 --- a/src/mem.c +++ b/src/mem.c @@ -1499,8 +1499,8 @@ void mem_reset_page_blocks() pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; - pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; - pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; + pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = BLOCK_INVALID; + pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = BLOCK_INVALID; } } diff --git a/src/mem.h b/src/mem.h index 2aabde9..a015acc 100644 --- a/src/mem.h +++ b/src/mem.h @@ -119,10 +119,10 @@ typedef struct page_t uint8_t *mem; - struct codeblock_t *block[4], *block_2[4]; + uint16_t block[4], block_2[4]; /*Head of codeblock tree associated with this page*/ - struct codeblock_t *head; + uint16_t head; uint64_t code_present_mask[4], dirty_mask[4]; } page_t; From 43b5b836448eadff7283c6a0bd1da9fcfdc02429 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 30 Nov 2018 13:18:56 +0000 Subject: [PATCH 074/181] Reduce codeblock_hash table to uint16_t. --- src/386_dynarec.c | 6 ++++-- src/codegen.c | 2 +- src/codegen.h | 2 +- src/codegen_backend.c | 8 ++++---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 8954538..1238cc0 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -602,7 +602,7 @@ void exec386_dynarec(int cycs) { uint32_t phys_addr = get_phys(cs+cpu_state.pc); int hash = HASH(phys_addr); - codeblock_t *block = codeblock_hash[hash]; + codeblock_t *block = &codeblock[codeblock_hash[hash]]; int valid_block = 0; trap = 0; @@ -630,7 +630,10 @@ void exec386_dynarec(int cycs) (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); if (valid_block) + { block = new_block; + codeblock_hash[hash] = get_block_nr(block); + } } } } @@ -675,7 +678,6 @@ void exec386_dynarec(int cycs) { void (*code)() = (void *)&block->data[BLOCK_START]; - codeblock_hash[hash] = block; // if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc); inrecomp=1; diff --git a/src/codegen.c b/src/codegen.c index ba9c06a..7a74756 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -14,7 +14,7 @@ int has_ea; codeblock_t *codeblock; -codeblock_t **codeblock_hash; +uint16_t *codeblock_hash; void (*codegen_timing_start)(); void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); diff --git a/src/codegen.h b/src/codegen.h index 72a3820..93657a1 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -65,7 +65,7 @@ uint8_t *codeblock_data; extern codeblock_t *codeblock; -extern codeblock_t **codeblock_hash; +extern uint16_t *codeblock_hash; /*Code block uses FPU*/ #define CODEBLOCK_HAS_FPU 1 diff --git a/src/codegen_backend.c b/src/codegen_backend.c index de292e3..500230d 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -92,7 +92,7 @@ void codegen_reset() int c; memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); mem_reset_page_blocks(); for (c = 0; c < BLOCK_SIZE; c++) @@ -211,8 +211,8 @@ static void delete_block(codeblock_t *block) { uint32_t old_pc = block->pc; - if (block == codeblock_hash[HASH(block->phys)]) - codeblock_hash[HASH(block->phys)] = NULL; + if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) + codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; if (block->pc == BLOCK_PC_INVALID) fatal("Deleting deleted block\n"); @@ -279,7 +279,7 @@ void codegen_block_init(uint32_t phys_addr) cpu_recomp_reuse++; } block_num = HASH(phys_addr); - codeblock_hash[block_num] = &codeblock[block_current]; + codeblock_hash[block_num] = block_current; block->ins = 0; block->pc = cs + cpu_state.pc; From d5f07a8594402e0b883d08326e2aa9101707f81c Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 30 Nov 2018 13:19:16 +0000 Subject: [PATCH 075/181] Fix bad use of flags variable in wx-sdl2-display.c. --- src/wx-sdl2-display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wx-sdl2-display.c b/src/wx-sdl2-display.c index 18bbc9e..0de48c5 100644 --- a/src/wx-sdl2-display.c +++ b/src/wx-sdl2-display.c @@ -639,6 +639,8 @@ int render() if (win_doresize) { + int flags = SDL_GetWindowFlags(window); + win_doresize = 0; if (!vid_resize || (flags&SDL_WINDOW_FULLSCREEN)) { SDL_GetWindowSize(window, &rect.w, &rect.h); From 99ca11d148793c3b13f8be51a80d75e4f12ca836 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 2 Dec 2018 12:38:31 +0000 Subject: [PATCH 076/181] Added initial emulation of FIC VA-503+ (Super 7). This includes preliminary emulation of the VIA MVP3 northbridge, VT82C586B 'PIPC' southbridge, and Winbond W83877TF SuperIO chip. --- src/ibm.h | 1 + src/mem_bios.c | 8 ++ src/model.c | 18 +++ src/mvp3.c | 219 ++++++++++++++++++++++++++++++++++ src/mvp3.h | 1 + src/nvr.c | 6 +- src/vt82c586b.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vt82c586b.h | 1 + src/w83877tf.c | 202 +++++++++++++++++++++++++++++++ src/w83877tf.h | 1 + 10 files changed, 765 insertions(+), 2 deletions(-) create mode 100644 src/mvp3.c create mode 100644 src/mvp3.h create mode 100644 src/vt82c586b.c create mode 100644 src/vt82c586b.h create mode 100644 src/w83877tf.c create mode 100644 src/w83877tf.h diff --git a/src/ibm.h b/src/ibm.h index 2221e8c..fb7865c 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -465,6 +465,7 @@ enum ROM_XI8088, ROM_IBMPS2_M70_TYPE3, ROM_IBMPS2_M70_TYPE4, + ROM_FIC_VA503P, ROM_MAX }; diff --git a/src/mem_bios.c b/src/mem_bios.c index dc5a904..c4229c5 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -900,6 +900,14 @@ int loadbios() fclose(f); biosmask = 0x1ffff; return 1; + + case ROM_FIC_VA503P: + f = romfopen("fic_va503p/je4333.bin","rb"); + if (!f) break; + romfread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index 55be58b..5fe572d 100644 --- a/src/model.c +++ b/src/model.c @@ -34,6 +34,7 @@ #include "lpt.h" #include "mem.h" #include "mouse_ps2.h" +#include "mvp3.h" #include "neat.h" #include "nmi.h" #include "nvr.h" @@ -61,6 +62,8 @@ #include "vid_pcjr.h" #include "vid_tandy.h" #include "vid_t1000.h" +#include "vt82c586b.h" +#include "w83877tf.h" #include "wd76c10.h" #include "xi8088.h" @@ -106,6 +109,7 @@ void at_pb520r_init(); void at_pb570_init(); void compaq_pip_init(); void xt_xi8088_init(); +void at_mvp3_init(); int model; int AMSTRAD, AT, PCI, TANDY; @@ -189,6 +193,8 @@ MODEL models[] = {"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 256, 1, at_i430vx_init, NULL}, + {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL}, + {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0} }; @@ -659,6 +665,18 @@ void at_i430vx_init() device_add(&intel_flash_bxt_device); } +void at_mvp3_init() +{ + at_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_slot(8); + pci_slot(9); + pci_slot(10); + mvp3_init(); + vt82c586b_init(7, 8, 9, 10, 0); + w83877tf_init(); +} + void model_init() { pclog("Initting as %s\n", model_getname()); diff --git a/src/mvp3.c b/src/mvp3.c new file mode 100644 index 0000000..2760d99 --- /dev/null +++ b/src/mvp3.c @@ -0,0 +1,219 @@ +#include + +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "pci.h" + +#include "mvp3.h" + +static struct +{ + uint8_t host_bridge_regs[256]; + uint8_t pci_bridge_regs[256]; +} mvp3; + +static void mvp3_map(uint32_t addr, uint32_t size, int state) +{ + pclog("mvp3_map: addr=%08x size=%08x state=%i\n", addr, size, state); + switch (state & 3) + { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + +static uint8_t mvp3_read(int func, int addr, void *priv) +{ + switch (func) + { + case 0: + return mvp3.host_bridge_regs[addr]; + + case 1: + return mvp3.pci_bridge_regs[addr]; + + default: + return 0xff; + } +} + + +static void mvp3_host_bridge_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 4) || (addr >= 5 && addr < 7) + || (addr >= 8 && addr < 0xd) + || (addr >= 0xe && addr < 0x12) + || (addr >= 0x14 && addr < 0x50) + || (addr >= 0x79 && addr < 0x7e) + || (addr >= 0x85 && addr < 0x88) + || (addr >= 0x8c && addr < 0xa8) + || (addr >= 0xad && addr < 0xfd)) + return; + + switch (addr) + { + case 0x04: /*Command*/ + mvp3.host_bridge_regs[0x04] = (mvp3.host_bridge_regs[0x04] & ~0x40) | (val & 0x40); + break; + case 0x07: /*Status*/ + mvp3.host_bridge_regs[0x07] &= ~(val & 0xb0); + break; + + case 0x12: /*Graphics Aperture Base*/ + mvp3.host_bridge_regs[0x12] = (val & 0xf0); + break; + case 0x13: /*Graphics Aperture Base*/ + mvp3.host_bridge_regs[0x13] = val; + break; + + case 0x61: /*Shadow RAM Control 1*/ + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0x03) + mvp3_map(0xc0000, 0x04000, val & 0x03); + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0x0c) + mvp3_map(0xc4000, 0x04000, (val & 0x0c) >> 2); + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0x30) + mvp3_map(0xc8000, 0x04000, (val & 0x30) >> 4); + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0xc0) + mvp3_map(0xcc000, 0x04000, (val & 0xc0) >> 6); + mvp3.host_bridge_regs[0x61] = val; + return; + case 0x62: /*Shadow RAM Control 2*/ + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0x03) + mvp3_map(0xd0000, 0x04000, val & 0x03); + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0x0c) + mvp3_map(0xd4000, 0x04000, (val & 0x0c) >> 2); + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0x30) + mvp3_map(0xd8000, 0x04000, (val & 0x30) >> 4); + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0xc0) + mvp3_map(0xdc000, 0x04000, (val & 0xc0) >> 6); + mvp3.host_bridge_regs[0x62] = val; + return; + case 0x63: /*Shadow RAM Control 3*/ + if ((mvp3.host_bridge_regs[0x63] ^ val) & 0x30) + mvp3_map(0xf0000, 0x10000, (val & 0x30) >> 4); + if ((mvp3.host_bridge_regs[0x63] ^ val) & 0xc0) + mvp3_map(0xe0000, 0x10000, (val & 0xc0) >> 6); + mvp3.host_bridge_regs[0x63] = val; +// if (val == 0xb0) +// output = 3; + return; + + default: + mvp3.host_bridge_regs[addr] = val; + break; + } +} +static void mvp3_pci_bridge_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 4) || (addr >= 5 && addr < 7) + || (addr >= 8 && addr < 0x18) + || (addr == 0x1b) + || (addr >= 0x1e && addr < 0x20) + || (addr >= 0x28 && addr < 0x3e) + || (addr >= 0x43)) + return; + + switch (addr) + { + case 0x04: /*Command*/ + mvp3.pci_bridge_regs[0x04] = (mvp3.pci_bridge_regs[0x04] & ~0x47) | (val & 0x47); + break; + case 0x07: /*Status*/ + mvp3.pci_bridge_regs[0x07] &= ~(val & 0x30); + break; + + case 0x20: /*Memory Base*/ + mvp3.pci_bridge_regs[0x20] = val & 0xf0; + break; + case 0x22: /*Memory Limit*/ + mvp3.pci_bridge_regs[0x22] = val & 0xf0; + break; + case 0x24: /*Prefetchable Memory Base*/ + mvp3.pci_bridge_regs[0x24] = val & 0xf0; + break; + case 0x26: /*Prefetchable Memory Limit*/ + mvp3.pci_bridge_regs[0x26] = val & 0xf0; + break; + + default: + mvp3.pci_bridge_regs[addr] = val; + break; + } +} + +static void mvp3_write(int func, int addr, uint8_t val, void *priv) +{ + switch (func) + { + case 0: + mvp3_host_bridge_write(addr, val); + break; + + case 1: + mvp3_pci_bridge_write(addr, val); + break; + } +} + +void mvp3_init() +{ + pci_add_specific(0, mvp3_read, mvp3_write, NULL); + + memset(&mvp3, 0, sizeof(mvp3)); + mvp3.host_bridge_regs[0x00] = 0x06; mvp3.host_bridge_regs[0x01] = 0x11; /*VIA*/ + mvp3.host_bridge_regs[0x02] = 0x98; mvp3.host_bridge_regs[0x03] = 0x05; /*VT82C598MVP*/ + mvp3.host_bridge_regs[0x04] = 0x06; mvp3.host_bridge_regs[0x05] = 0x00; + mvp3.host_bridge_regs[0x06] = 0x90; mvp3.host_bridge_regs[0x07] = 0x02; + mvp3.host_bridge_regs[0x0b] = 0x06; + mvp3.host_bridge_regs[0x10] = 0x08; + mvp3.host_bridge_regs[0x34] = 0xa0; + + mvp3.host_bridge_regs[0x5a] = 0x01; + mvp3.host_bridge_regs[0x5b] = 0x01; + mvp3.host_bridge_regs[0x5c] = 0x01; + mvp3.host_bridge_regs[0x5d] = 0x01; + mvp3.host_bridge_regs[0x5e] = 0x01; + mvp3.host_bridge_regs[0x5f] = 0x01; + + mvp3.host_bridge_regs[0x64] = 0xec; + mvp3.host_bridge_regs[0x65] = 0xec; + mvp3.host_bridge_regs[0x66] = 0xec; + mvp3.host_bridge_regs[0x6b] = 0x01; + + mvp3.host_bridge_regs[0xa0] = 0x02; + mvp3.host_bridge_regs[0xa2] = 0x10; + mvp3.host_bridge_regs[0xa4] = 0x03; + mvp3.host_bridge_regs[0xa5] = 0x02; + mvp3.host_bridge_regs[0xa6] = 0x00; + mvp3.host_bridge_regs[0xa7] = 0x07; + + mvp3.pci_bridge_regs[0x00] = 0x06; mvp3.pci_bridge_regs[0x01] = 0x11; /*VIA*/ + mvp3.pci_bridge_regs[0x02] = 0x98; mvp3.pci_bridge_regs[0x03] = 0x85; /*VT82C598MVP*/ + mvp3.pci_bridge_regs[0x04] = 0x07; mvp3.pci_bridge_regs[0x05] = 0x00; + mvp3.pci_bridge_regs[0x06] = 0x20; mvp3.pci_bridge_regs[0x07] = 0x02; + mvp3.pci_bridge_regs[0x0a] = 0x04; + mvp3.pci_bridge_regs[0x0b] = 0x06; + mvp3.pci_bridge_regs[0x0e] = 0x01; + + mvp3.pci_bridge_regs[0x1c] = 0xf0; + + mvp3.pci_bridge_regs[0x20] = 0xf0; + mvp3.pci_bridge_regs[0x21] = 0xff; + + mvp3.pci_bridge_regs[0x24] = 0xf0; + mvp3.pci_bridge_regs[0x25] = 0xff; +} diff --git a/src/mvp3.h b/src/mvp3.h new file mode 100644 index 0000000..69dac83 --- /dev/null +++ b/src/mvp3.h @@ -0,0 +1 @@ +void mvp3_init(); diff --git a/src/nvr.c b/src/nvr.c index fa8c1f4..edabac9 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -306,7 +306,8 @@ void loadnvr() case ROM_XI8088: f = nvrfopen("xi8088.nvr", "rb"); nvrmask = 127; break; case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","rb"); break; case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","rb"); break; - + case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break; + default: return; } if (!f) @@ -396,7 +397,8 @@ void savenvr() case ROM_XI8088: f = nvrfopen("xi8088.nvr", "wb"); break; case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","wb"); break; case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","wb"); break; - + case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break; + default: return; } fwrite(nvrram,128,1,f); diff --git a/src/vt82c586b.c b/src/vt82c586b.c new file mode 100644 index 0000000..fd67002 --- /dev/null +++ b/src/vt82c586b.c @@ -0,0 +1,310 @@ +#include + +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "pci.h" +#include "x86.h" + +#include "vt82c586b.h" + +static struct +{ + uint8_t pci_isa_bridge_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[256]; + uint8_t power_regs[256]; + + uint8_t sysctrl; +} vt82c586b; + +static uint8_t vt82c586b_read(int func, int addr, void *priv) +{ + switch (func) + { + case 0: + return vt82c586b.pci_isa_bridge_regs[addr]; + + case 1: + return vt82c586b.ide_regs[addr]; + + case 2: + return vt82c586b.usb_regs[addr]; + + case 3: + return vt82c586b.power_regs[addr]; + + default: + return 0xff; + } +} + +static void vt82c586b_pci_isa_bridge_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 4) || (addr == 5) || (addr == 6) + || (addr >= 8 && addr < 0x40) + || (addr == 0x49) + || (addr == 0x4b) + || (addr >= 0x51 && addr < 0x54) + || (addr >= 0x5d && addr < 0x60) + || (addr >= 0x68 && addr < 0x6a) + || (addr >= 0x71)) + return; + + switch (addr) + { + case 4: + vt82c586b.pci_isa_bridge_regs[4] = (val & 8) | 7; + break; + case 6: + vt82c586b.pci_isa_bridge_regs[6] &= ~(val & 0xb0); + break; + + case 0x47: + if ((val & 0x81) == 0x81) + resetx86(); + vt82c586b.pci_isa_bridge_regs[0x47] = val & 0xfe; + break; + + case 0x55: + if (!(val & 0xf0)) + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTD, val >> 4); + vt82c586b.pci_isa_bridge_regs[0x55] = val; + break; + case 0x56: + if (!(val & 0xf0)) + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA, val >> 4); + if (!(val & 0x0f)) + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTB, val & 0xf); + vt82c586b.pci_isa_bridge_regs[0x56] = val; + break; + case 0x57: + if (!(val & 0xf0)) + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTC, val >> 4); + vt82c586b.pci_isa_bridge_regs[0x57] = val; + break; + + default: + vt82c586b.pci_isa_bridge_regs[addr] = val; + break; + } +} +static void vt82c586b_ide_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 6) || (addr == 8) + || (addr >= 0xa && addr < 0x0d) + || (addr >= 0x0e && addr < 0x20) + || (addr >= 0x22 && addr < 0x3c) + || (addr >= 0x3d && addr < 0x40) + || (addr >= 0x54 && addr < 0x60) + || (addr >= 0x52 && addr < 0x68) + || (addr >= 0x62)) + return; + + switch (addr) + { + case 4: + vt82c586b.ide_regs[4] = (val & 8) | 7; + break; + case 6: + vt82c586b.ide_regs[6] &= ~(val & 0xb0); + break; + + case 9: + vt82c586b.ide_regs[9] = (vt82c586b.pci_isa_bridge_regs[9] & ~0x70) | 0x8a; + break; + + case 0x20: + vt82c586b.ide_regs[0x20] = (val & ~0xf) | 1; + break; + + default: + vt82c586b.ide_regs[addr] = val; + break; + } +} +static void vt82c586b_usb_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 7) || (addr >= 8 && addr < 0xd) + || (addr >= 0xe && addr < 0x20) + || (addr >= 0x22 && addr < 0x3c) + || (addr >= 0x3e && addr < 0x40) + || (addr >= 0x42 && addr < 0x44) + || (addr >= 0x46 && addr < 0xc0) + || (addr >= 0xc2)) + return; + + switch (addr) + { + case 7: + vt82c586b.usb_regs[7] = val & 0x7f; + break; + + case 0x20: + vt82c586b.usb_regs[0x20] = (val & ~0x1f) | 1; + break; + + default: + vt82c586b.usb_regs[addr] = val; + break; + } +} +static void vt82c586b_power_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 0xd) || (addr >= 0xe && addr < 0x40) + || (addr == 0x43) + || (addr == 0x48) + || (addr >= 0x4a && addr < 0x50) + || (addr >= 0x54)) + return; + + switch (addr) + { + default: + vt82c586b.power_regs[addr] = val; + break; + } +} + +static void vt82c586b_write(int func, int addr, uint8_t val, void *priv) +{ + switch (func) + { + case 0: + vt82c586b_pci_isa_bridge_write(addr, val); + break; + + case 1: + vt82c586b_ide_write(addr, val); + break; + + case 2: + vt82c586b_usb_write(addr, val); + break; + + case 3: + vt82c586b_power_write(addr, val); + break; + } +} + +uint8_t vt82c586b_read_sysctrl(uint16_t port, void *p) +{ + return vt82c586b.sysctrl; +} + +void vt82c586b_write_sysctrl(uint16_t port, uint8_t val, void *p) +{ + if ((mem_a20_alt ^ val) & 2) + { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~vt82c586b.sysctrl & val) & 1) + { + softresetx86(); + cpu_set_edx(); + } + vt82c586b.sysctrl = val; +} + +void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) +{ + pci_add_specific(card, vt82c586b_read, vt82c586b_write, NULL); + io_sethandler(0x0092, 0x0001, vt82c586b_read_sysctrl, NULL, NULL, vt82c586b_write_sysctrl, NULL, NULL, NULL); + + memset(&vt82c586b, 0, sizeof(vt82c586b)); + vt82c586b.pci_isa_bridge_regs[0x00] = 0x06; vt82c586b.pci_isa_bridge_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.pci_isa_bridge_regs[0x02] = 0x86; vt82c586b.pci_isa_bridge_regs[0x03] = 0x05; /*VT82C586B*/ + vt82c586b.pci_isa_bridge_regs[0x04] = 0x0f; vt82c586b.pci_isa_bridge_regs[0x05] = 0x00; + vt82c586b.pci_isa_bridge_regs[0x06] = 0x00; vt82c586b.pci_isa_bridge_regs[0x07] = 0x02; + vt82c586b.pci_isa_bridge_regs[0x0a] = 0x01; + vt82c586b.pci_isa_bridge_regs[0x0b] = 0x06; + vt82c586b.pci_isa_bridge_regs[0x0e] = 0x80; + + /*ISA bus control*/ + vt82c586b.pci_isa_bridge_regs[0x48] = 0x01; + vt82c586b.pci_isa_bridge_regs[0x4a] = 0x04; + vt82c586b.pci_isa_bridge_regs[0x4f] = 0x03; + + /*Plug and Play control*/ + vt82c586b.pci_isa_bridge_regs[0x50] = 0x24; + vt82c586b.pci_isa_bridge_regs[0x59] = 0x04; + + vt82c586b.ide_regs[0x00] = 0x06; vt82c586b.ide_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.ide_regs[0x02] = 0x71; vt82c586b.ide_regs[0x03] = 0x05; + vt82c586b.ide_regs[0x04] = 0x80; vt82c586b.ide_regs[0x05] = 0x00; + vt82c586b.ide_regs[0x06] = 0x80; vt82c586b.ide_regs[0x07] = 0x02; + vt82c586b.ide_regs[0x09] = 0x85; + vt82c586b.ide_regs[0x0a] = 0x01; + vt82c586b.ide_regs[0x0b] = 0x01; + + vt82c586b.ide_regs[0x10] = 0xf1; vt82c586b.ide_regs[0x11] = 0x01; + vt82c586b.ide_regs[0x14] = 0xf5; vt82c586b.ide_regs[0x15] = 0x03; + vt82c586b.ide_regs[0x18] = 0x71; vt82c586b.ide_regs[0x19] = 0x01; + vt82c586b.ide_regs[0x1c] = 0x75; vt82c586b.ide_regs[0x1d] = 0x03; + vt82c586b.ide_regs[0x20] = 0x01; vt82c586b.ide_regs[0x21] = 0xcc; + vt82c586b.ide_regs[0x3c] = 0x0e; + + vt82c586b.ide_regs[0x40] = 0x08; + vt82c586b.ide_regs[0x41] = 0x02; + vt82c586b.ide_regs[0x42] = 0x09; + vt82c586b.ide_regs[0x43] = 0x3a; + vt82c586b.ide_regs[0x44] = 0x68; + vt82c586b.ide_regs[0x46] = 0xc0; + vt82c586b.ide_regs[0x48] = 0xa8; + vt82c586b.ide_regs[0x49] = 0xa8; + vt82c586b.ide_regs[0x4a] = 0xa8; + vt82c586b.ide_regs[0x4b] = 0xa8; + vt82c586b.ide_regs[0x4c] = 0xff; + vt82c586b.ide_regs[0x4e] = 0xff; + vt82c586b.ide_regs[0x4f] = 0xff; + vt82c586b.ide_regs[0x50] = 0x03; + vt82c586b.ide_regs[0x51] = 0x03; + vt82c586b.ide_regs[0x52] = 0x03; + vt82c586b.ide_regs[0x53] = 0x03; + vt82c586b.ide_regs[0x61] = 0x02; + vt82c586b.ide_regs[0x68] = 0x02; + + vt82c586b.usb_regs[0x00] = 0x06; vt82c586b.usb_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.usb_regs[0x02] = 0x38; vt82c586b.usb_regs[0x03] = 0x30; + vt82c586b.usb_regs[0x04] = 0x00; vt82c586b.usb_regs[0x05] = 0x00; + vt82c586b.usb_regs[0x06] = 0x00; vt82c586b.usb_regs[0x07] = 0x02; + vt82c586b.usb_regs[0x0a] = 0x03; + vt82c586b.usb_regs[0x0b] = 0x0c; + vt82c586b.usb_regs[0x0d] = 0x16; + vt82c586b.usb_regs[0x20] = 0x01; + vt82c586b.usb_regs[0x21] = 0x03; + vt82c586b.usb_regs[0x3d] = 0x04; + + vt82c586b.usb_regs[0x60] = 0x10; + vt82c586b.usb_regs[0xc1] = 0x20; + + vt82c586b.power_regs[0x00] = 0x06; vt82c586b.power_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.power_regs[0x02] = 0x40; vt82c586b.power_regs[0x03] = 0x30; + vt82c586b.power_regs[0x04] = 0x00; vt82c586b.power_regs[0x05] = 0x00; + vt82c586b.power_regs[0x06] = 0x80; vt82c586b.power_regs[0x07] = 0x02; + vt82c586b.power_regs[0x08] = 0x10; /*Production version (3041)*/ + vt82c586b.power_regs[0x48] = 0x01; + + if (pci_a) + pci_set_card_routing(pci_a, PCI_INTA); + if (pci_b) + pci_set_card_routing(pci_b, PCI_INTB); + if (pci_c) + pci_set_card_routing(pci_c, PCI_INTC); + if (pci_d) + pci_set_card_routing(pci_d, PCI_INTD); +} diff --git a/src/vt82c586b.h b/src/vt82c586b.h new file mode 100644 index 0000000..0f6981f --- /dev/null +++ b/src/vt82c586b.h @@ -0,0 +1 @@ +void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d); diff --git a/src/w83877tf.c b/src/w83877tf.c new file mode 100644 index 0000000..78c2a63 --- /dev/null +++ b/src/w83877tf.c @@ -0,0 +1,202 @@ +#include "ibm.h" + +#include "fdc.h" +#include "io.h" +#include "lpt.h" +#include "serial.h" +#include "w83877tf.h" + +typedef struct w83877tf_t +{ + int enable_regs; + uint8_t key[2]; + int index; + uint8_t regs[256]; +} w83877tf_t; + +static w83877tf_t w83877tf_global; + +static void w83877tf_write_25x(uint16_t port, uint8_t val, void *p); +static uint8_t w83877tf_read_25x(uint16_t port, void *p); +static void w83877tf_write_3fx(uint16_t port, uint8_t val, void *p); +static uint8_t w83877tf_read_3fx(uint16_t port, void *p); + +static void w83877tf_write_reg(w83877tf_t *w83877tf, int index, uint8_t val) +{ +// pclog("w83877tf_write: index=%02x val=%02x\n", index, val); + switch (index) + { + case 0x16: + if (val == 2) /*Written by VA-503+ BIOS. Apparently should not change IO mapping*/ + return; + + io_removehandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global); + io_removehandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global); + if (val & 0x01) + io_sethandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global); + else + io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global); + + if ((w83877tf->regs[0x16] & 4) && !(val & 4)) + { + w83877tf->regs[0x20] = 0; + w83877tf->regs[0x23] = 0; + w83877tf->regs[0x24] = 0; + w83877tf->regs[0x25] = 0; + w83877tf->regs[0x26] = 0; + w83877tf->regs[0x27] = 0; + w83877tf->regs[0x28] = 0; + w83877tf->regs[0x29] = 0; + } + break; + } + + w83877tf->regs[index] = val; + + + fdc_remove(); + if (w83877tf->regs[0x20] >= 0x40) + fdc_add(); + + lpt1_remove(); + lpt2_remove(); + if (w83877tf->regs[0x23] >= 0x40) + lpt1_init(w83877tf->regs[0x23] << 2); + + serial1_remove(); + if (w83877tf->regs[0x24] >= 0x40) + serial1_set((w83877tf->regs[0x24] & ~1) << 2, w83877tf->regs[0x28] >> 4); + + serial2_remove(); + if (w83877tf->regs[0x25] >= 0x40) + serial2_set((w83877tf->regs[0x25] & ~1) << 2, w83877tf->regs[0x28] & 0xf); + +// pclog("LPT at %04x\n", w83877tf->regs[0x23] << 2); +// pclog("Serial1 at %04x %i\n", (w83877tf->regs[0x24] & ~1) << 2, w83877tf->regs[0x28] >> 4); +// pclog("Serial2 at %04x %i\n", (w83877tf->regs[0x25] & ~1) << 2, w83877tf->regs[0x28] & 0xf); +} + +static uint8_t w83877tf_read_reg(w83877tf_t *w83877tf, int index) +{ + switch (w83877tf->index) + { + case 0x09: + return 0x0c; /*W83877TF ID*/ + } + return w83877tf->regs[index]; +} + +static void w83877tf_write_25x(uint16_t port, uint8_t val, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + +// pclog("w83877tf_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x250: /*Enable register*/ + w83877tf->enable_regs = (val == 0x89) ? 1 : 0; + break; + case 0x251: /*Index*/ + if (w83877tf->enable_regs) + w83877tf->index = val; + break; + case 0x252: /*Data*/ + if (w83877tf->enable_regs) + w83877tf_write_reg(w83877tf, w83877tf->index, val); + break; + } +} + +static uint8_t w83877tf_read_25x(uint16_t port, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + + switch (port) + { + case 0x251: /*Index*/ + if (w83877tf->enable_regs) + return w83877tf->index; + break; + + case 0x252: /*Data*/ + if (w83877tf->enable_regs) + return w83877tf_read_reg(w83877tf, w83877tf->index); + break; + } + + return 0xff; +} + +static void w83877tf_write_3fx(uint16_t port, uint8_t val, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + +// pclog("w83877tf_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x3f0: /*Enable/index register*/ + if (val == 0xaa) + w83877tf->enable_regs = 0; + else if (!w83877tf->enable_regs) + { + w83877tf->key[1] = w83877tf->key[0]; + w83877tf->key[0] = val; + w83877tf->enable_regs = (w83877tf->key[0] == 0x87 && w83877tf->key[1] == 0x87); + } + else + w83877tf->index = val; + break; + case 0x3f1: /*Data*/ + if (w83877tf->enable_regs) + w83877tf_write_reg(w83877tf, w83877tf->index, val); + break; + } +} + +static uint8_t w83877tf_read_3fx(uint16_t port, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + uint8_t ret = 0xff; + + switch (port) + { + case 0x3f0: /*Index*/ + if (w83877tf->enable_regs) + ret = w83877tf->index; + break; + + case 0x3f1: /*Data*/ + if (w83877tf->enable_regs) + ret = w83877tf_read_reg(w83877tf, w83877tf->index); + break; + } + +// pclog("w83877tf_read: port=%04x val=%02x\n", port, ret); + + return ret; +} + +void w83877tf_init() +{ + memset(&w83877tf_global, 0, sizeof(w83877tf_t)); + + io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global); + + /*Defaults*/ + w83877tf_global.regs[0x03] = 0x30; + w83877tf_global.regs[0x09] = 0x0c; + w83877tf_global.regs[0x0b] = 0x0c; + w83877tf_global.regs[0x0c] = 0x28; + w83877tf_global.regs[0x0d] = 0xa3; + w83877tf_global.regs[0x16] = 0x04; + w83877tf_global.regs[0x20] = 0xfc; + w83877tf_global.regs[0x23] = 0xde; + w83877tf_global.regs[0x24] = 0xfe; + w83877tf_global.regs[0x25] = 0xbe; + w83877tf_global.regs[0x26] = 0x23; + w83877tf_global.regs[0x27] = 0x05; + w83877tf_global.regs[0x28] = 0x43; + w83877tf_global.regs[0x29] = 0x60; +} diff --git a/src/w83877tf.h b/src/w83877tf.h new file mode 100644 index 0000000..dcfb853 --- /dev/null +++ b/src/w83877tf.h @@ -0,0 +1 @@ +void w83877tf_init(); From 5043cff3f9527b8af4946b6ad3960c465f048ff9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 2 Dec 2018 15:46:28 +0000 Subject: [PATCH 077/181] Move SFF-8038i IDE bus mastering code out of PIIX files. Add bus mastering to VT82C586B emulation. --- src/ide.c | 16 ++-- src/ide.h | 9 +- src/ide_atapi.c | 8 +- src/ide_sff8038i.c | 208 +++++++++++++++++++++++++++++++++++++++++++ src/ide_sff8038i.h | 13 +++ src/model.c | 2 +- src/piix.c | 213 ++------------------------------------------- src/vt82c586b.c | 39 ++++++++- 8 files changed, 282 insertions(+), 226 deletions(-) create mode 100644 src/ide_sff8038i.c create mode 100644 src/ide_sff8038i.h diff --git a/src/ide.c b/src/ide.c index 44e74a7..0cbad14 100644 --- a/src/ide.c +++ b/src/ide.c @@ -94,9 +94,10 @@ IDE *ext_ide; char ide_fn[7][512]; -int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size); -int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size); -void (*ide_bus_master_set_irq)(int channel); +int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size, void *p); +int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size, void *p); +void (*ide_bus_master_set_irq)(int channel, void *p); +void *ide_bus_master_p; pc_timer_t ide_timer[2]; @@ -111,7 +112,7 @@ void ide_irq_raise(IDE *ide) // if (ide->board && !ide->irqstat) pclog("IDE_IRQ_RAISE\n"); picint((ide->board)?(1<<15):(1<<14)); if (ide_bus_master_set_irq) - ide_bus_master_set_irq(ide->board); + ide_bus_master_set_irq(ide->board, ide_bus_master_p); } ide->irqstat=1; ide->service=1; @@ -905,7 +906,7 @@ void callbackide(int ide_board) if (ide_bus_master_read_data) { - if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512)) + if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512, ide_bus_master_p)) timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { @@ -983,7 +984,7 @@ void callbackide(int ide_board) if (ide_bus_master_write_data) { - if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512)) + if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512, ide_bus_master_p)) timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { @@ -1270,11 +1271,12 @@ static void ide_close(void *p) { } -void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel)) +void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, void *p), int (*write_data)(int channel, uint8_t *data, int size, void *p), void (*set_irq)(int channel, void *p), void *p) { ide_bus_master_read_data = read_data; ide_bus_master_write_data = write_data; ide_bus_master_set_irq = set_irq; + ide_bus_master_p = p; } device_t ide_device = diff --git a/src/ide.h b/src/ide.h index aed1200..0c2ce0b 100644 --- a/src/ide.h +++ b/src/ide.h @@ -16,12 +16,13 @@ extern void ide_pri_enable(); extern void ide_sec_enable(); extern void ide_pri_disable(); extern void ide_sec_disable(); -extern void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel)); +extern void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, void *p), int (*write_data)(int channel, uint8_t *data, int size, void *p), void (*set_irq)(int channel, void *p), void *p); void ide_irq_raise(struct IDE *ide); -extern int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size); -extern int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size); -extern void (*ide_bus_master_set_irq)(int channel); +extern int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size, void *p); +extern int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size, void *p); +extern void (*ide_bus_master_set_irq)(int channel, void *p); +extern void *ide_bus_master_p; #include "ide_atapi.h" diff --git a/src/ide_atapi.c b/src/ide_atapi.c index ab4330e..78a648b 100644 --- a/src/ide_atapi.c +++ b/src/ide_atapi.c @@ -258,7 +258,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_write_data) { - if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) + if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos, ide_bus_master_p)) { atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA; timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); @@ -430,7 +430,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_read_data) { - if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) + if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos, ide_bus_master_p)) { atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA; timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); @@ -535,7 +535,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) case ATAPI_STATE_RETRY_READ_DMA: { - if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) + if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos, ide_bus_master_p)) { timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } @@ -549,7 +549,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) case ATAPI_STATE_RETRY_WRITE_DMA: { - if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) + if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos, ide_bus_master_p)) { timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } diff --git a/src/ide_sff8038i.c b/src/ide_sff8038i.c new file mode 100644 index 0000000..79eda27 --- /dev/null +++ b/src/ide_sff8038i.c @@ -0,0 +1,208 @@ +/*Emulation of SFF-8038i IDE bus mastering interface. + Used by PIIX and VT82C586B IDE controllers*/ +#include "ibm.h" +#include "ide.h" +#include "ide_sff8038i.h" +#include "mem.h" + +static void sff_bus_master_next_addr(sff_busmaster_t *busmaster, int channel) +{ + busmaster[channel].addr = (*(uint32_t *)(&ram[busmaster[channel].ptr_cur])) & ~1; + busmaster[channel].count = (*(uint32_t *)(&ram[busmaster[channel].ptr_cur + 4])) & 0xfffe; + if (!busmaster[channel].count) + busmaster[channel].count = 0x10000; + busmaster[channel].eot = (*(uint32_t *)(&ram[busmaster[channel].ptr_cur + 4])) >> 31; + busmaster[channel].ptr_cur += 8; +// pclog("New DMA settings on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); +} + +void sff_bus_master_write(uint16_t port, uint8_t val, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int channel = (port & 8) ? 1 : 0; +// pclog("PIIX Bus Master write %04X %02X %04x:%08x\n", port, val, CS, pc); + switch (port & 7) + { + case 0: + if ((val & 1) && !(busmaster[channel].command & 1)) /*Start*/ + { + busmaster[channel].ptr_cur = busmaster[channel].ptr; + sff_bus_master_next_addr(busmaster, channel); + busmaster[channel].status |= 1; + } + if (!(val & 1) && (busmaster[channel].command & 1)) /*Stop*/ + busmaster[channel].status &= ~1; + + busmaster[channel].command = val; + break; + case 2: + busmaster[channel].status = (val & 0x60) | ((busmaster[channel].status & ~val) & 6) | (busmaster[channel].status & 1); + break; + case 4: + busmaster[channel].ptr = (busmaster[channel].ptr & 0xffffff00) | val; + break; + case 5: + busmaster[channel].ptr = (busmaster[channel].ptr & 0xffff00ff) | (val << 8); + break; + case 6: + busmaster[channel].ptr = (busmaster[channel].ptr & 0xff00ffff) | (val << 16); + break; + case 7: + busmaster[channel].ptr = (busmaster[channel].ptr & 0x00ffffff) | (val << 24); + break; + } +} + +uint8_t sff_bus_master_read(uint16_t port, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int channel = (port & 8) ? 1 : 0; +// pclog("PIIX Bus Master read %04X %04x:%08x\n", port, CS, pc); + switch (port & 7) + { + case 0: + return busmaster[channel].command; + case 2: + return busmaster[channel].status; + case 4: + return busmaster[channel].ptr; + case 5: + return busmaster[channel].ptr >> 8; + case 6: + return busmaster[channel].ptr >> 16; + case 7: + return busmaster[channel].ptr >> 24; + } + return 0xff; +} + +static int sff_bus_master_data_read(int channel, uint8_t *data, int size, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int transferred = 0; + + if (!(busmaster[channel].status & 1)) + return 1; /*DMA disabled*/ + + while (transferred < size) + { + if (busmaster[channel].count < (size - transferred) && busmaster[channel].eot) + fatal("DMA on channel %i - Read count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, busmaster[channel].addr, busmaster[channel].count, busmaster[channel].eot, size); + + mem_invalidate_range(busmaster[channel].addr, busmaster[channel].addr+(size-1)); + + if (busmaster[channel].count < (size - transferred)) + { +// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = busmaster[channel].count; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(&ram[busmaster[channel].addr], data + transferred, count); + } + transferred += busmaster[channel].count; + busmaster[channel].addr += busmaster[channel].count; + busmaster[channel].count = 0; + } + else + { +// pclog("Transferring larger - %i bytes\n", size - transferred); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = size - transferred; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(&ram[busmaster[channel].addr], data + transferred, count); + } + busmaster[channel].addr += (size - transferred); + busmaster[channel].count -= (size - transferred); + transferred += (size - transferred); + } + +// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); + + if (!busmaster[channel].count) + { +// pclog("DMA on channel %i - block over\n", channel); + if (busmaster[channel].eot) /*End of transfer?*/ + { +// pclog("DMA on channel %i - transfer over\n", channel); + busmaster[channel].status &= ~1; + } + else + sff_bus_master_next_addr(busmaster, channel); + } + } + return 0; +} +static int sff_bus_master_data_write(int channel, uint8_t *data, int size, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int transferred = 0; + + if (!(busmaster[channel].status & 1)) + return 1; /*DMA disabled*/ + + while (transferred < size) + { + if (busmaster[channel].count < (size - transferred) && busmaster[channel].eot) + fatal("DMA on channel %i - Write count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, busmaster[channel].addr, busmaster[channel].count, busmaster[channel].eot, size); + + if (busmaster[channel].count < (size - transferred)) + { +// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = busmaster[channel].count; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(data + transferred, &ram[busmaster[channel].addr], count); + } + transferred += busmaster[channel].count; + busmaster[channel].addr += busmaster[channel].count; + busmaster[channel].count = 0; + } + else + { +// pclog("Transferring larger - %i bytes\n", size - transferred); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = size - transferred; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(data + transferred, &ram[busmaster[channel].addr], count); + } + busmaster[channel].addr += (size - transferred); + busmaster[channel].count -= (size - transferred); + transferred += (size - transferred); + } + +// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); + + if (!busmaster[channel].count) + { +// pclog("DMA on channel %i - block over\n", channel); + if (busmaster[channel].eot) /*End of transfer?*/ + { +// pclog("DMA on channel %i - transfer over\n", channel); + busmaster[channel].status &= ~1; + } + else + sff_bus_master_next_addr(busmaster, channel); + } + } + return 0; +} + +static void sff_bus_master_set_irq(int channel, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + + busmaster[channel].status |= 4; +} + +void sff_bus_master_init(sff_busmaster_t *busmaster) +{ + ide_set_bus_master(sff_bus_master_data_read, sff_bus_master_data_write, sff_bus_master_set_irq, busmaster); +} diff --git a/src/ide_sff8038i.h b/src/ide_sff8038i.h new file mode 100644 index 0000000..9ade5ad --- /dev/null +++ b/src/ide_sff8038i.h @@ -0,0 +1,13 @@ +typedef struct sff_busmaster_t +{ + uint8_t command; + uint8_t status; + uint32_t ptr, ptr_cur; + int count; + uint32_t addr; + int eot; +} sff_busmaster_t; + +uint8_t sff_bus_master_read(uint16_t port, void *p); +void sff_bus_master_write(uint16_t port, uint8_t val, void *p); +void sff_bus_master_init(sff_busmaster_t *busmaster); diff --git a/src/model.c b/src/model.c index 5fe572d..7d3a540 100644 --- a/src/model.c +++ b/src/model.c @@ -681,7 +681,7 @@ void model_init() { pclog("Initting as %s\n", model_getname()); AMSTRAD = AT = PCI = TANDY = 0; - ide_set_bus_master(NULL, NULL, NULL); + ide_set_bus_master(NULL, NULL, NULL, NULL); models[model].init(); if (models[model].device) diff --git a/src/piix.c b/src/piix.c index d8a2a18..73676cf 100644 --- a/src/piix.c +++ b/src/piix.c @@ -7,6 +7,7 @@ #include "ibm.h" #include "ide.h" +#include "ide_sff8038i.h" #include "io.h" #include "mem.h" #include "pci.h" @@ -14,10 +15,8 @@ #include "piix.h" -uint8_t piix_bus_master_read(uint16_t port, void *priv); -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); - static uint8_t card_piix[256], card_piix_ide[256]; +static sff_busmaster_t piix_busmaster[2]; void piix_write(int func, int addr, uint8_t val, void *priv) { @@ -62,9 +61,9 @@ void piix_write(int func, int addr, uint8_t val, void *priv) if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ { uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - io_removehandler(0, 0x10000, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + io_removehandler(0, 0x10000, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, piix_busmaster); if (card_piix_ide[0x04] & 1) - io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + io_sethandler(base, 0x10, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, piix_busmaster); } if (addr == 4 || addr == 0x41 || addr == 0x43) { @@ -140,206 +139,6 @@ uint8_t piix_read(int func, int addr, void *priv) return card_piix[addr]; } -struct -{ - uint8_t command; - uint8_t status; - uint32_t ptr, ptr_cur; - int count; - uint32_t addr; - int eot; -} piix_busmaster[2]; - -static void piix_bus_master_next_addr(int channel) -{ - piix_busmaster[channel].addr = (*(uint32_t *)(&ram[piix_busmaster[channel].ptr_cur])) & ~1; - piix_busmaster[channel].count = (*(uint32_t *)(&ram[piix_busmaster[channel].ptr_cur + 4])) & 0xfffe; - if (!piix_busmaster[channel].count) - piix_busmaster[channel].count = 0x10000; - piix_busmaster[channel].eot = (*(uint32_t *)(&ram[piix_busmaster[channel].ptr_cur + 4])) >> 31; - piix_busmaster[channel].ptr_cur += 8; -// pclog("New DMA settings on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); -} - -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv) -{ - int channel = (port & 8) ? 1 : 0; -// pclog("PIIX Bus Master write %04X %02X %04x:%08x\n", port, val, CS, pc); - switch (port & 7) - { - case 0: - if ((val & 1) && !(piix_busmaster[channel].command & 1)) /*Start*/ - { - piix_busmaster[channel].ptr_cur = piix_busmaster[channel].ptr; - piix_bus_master_next_addr(channel); - piix_busmaster[channel].status |= 1; - } - if (!(val & 1) && (piix_busmaster[channel].command & 1)) /*Stop*/ - piix_busmaster[channel].status &= ~1; - - piix_busmaster[channel].command = val; - break; - case 2: - piix_busmaster[channel].status = (val & 0x60) | ((piix_busmaster[channel].status & ~val) & 6) | (piix_busmaster[channel].status & 1); - break; - case 4: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffffff00) | val; - break; - case 5: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffff00ff) | (val << 8); - break; - case 6: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xff00ffff) | (val << 16); - break; - case 7: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0x00ffffff) | (val << 24); - break; - } -} - -uint8_t piix_bus_master_read(uint16_t port, void *priv) -{ - int channel = (port & 8) ? 1 : 0; -// pclog("PIIX Bus Master read %04X %04x:%08x\n", port, CS, pc); - switch (port & 7) - { - case 0: - return piix_busmaster[channel].command; - case 2: - return piix_busmaster[channel].status; - case 4: - return piix_busmaster[channel].ptr; - case 5: - return piix_busmaster[channel].ptr >> 8; - case 6: - return piix_busmaster[channel].ptr >> 16; - case 7: - return piix_busmaster[channel].ptr >> 24; - } - return 0xff; -} - -int piix_bus_master_data_read(int channel, uint8_t *data, int size) -{ - int transferred = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ - - while (transferred < size) - { - if (piix_busmaster[channel].count < (size - transferred) && piix_busmaster[channel].eot) - fatal("DMA on channel %i - Read count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot, size); - - mem_invalidate_range(piix_busmaster[channel].addr, piix_busmaster[channel].addr+(size-1)); - - if (piix_busmaster[channel].count < (size - transferred)) - { -// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = piix_busmaster[channel].count; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(&ram[piix_busmaster[channel].addr], data + transferred, count); - } - transferred += piix_busmaster[channel].count; - piix_busmaster[channel].addr += piix_busmaster[channel].count; - piix_busmaster[channel].count = 0; - } - else - { -// pclog("Transferring larger - %i bytes\n", size - transferred); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = size - transferred; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(&ram[piix_busmaster[channel].addr], data + transferred, count); - } - piix_busmaster[channel].addr += (size - transferred); - piix_busmaster[channel].count -= (size - transferred); - transferred += (size - transferred); - } - -// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); - - if (!piix_busmaster[channel].count) - { -// pclog("DMA on channel %i - block over\n", channel); - if (piix_busmaster[channel].eot) /*End of transfer?*/ - { -// pclog("DMA on channel %i - transfer over\n", channel); - piix_busmaster[channel].status &= ~1; - } - else - piix_bus_master_next_addr(channel); - } - } - return 0; -} -int piix_bus_master_data_write(int channel, uint8_t *data, int size) -{ - int transferred = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ - - while (transferred < size) - { - if (piix_busmaster[channel].count < (size - transferred) && piix_busmaster[channel].eot) - fatal("DMA on channel %i - Write count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot, size); - - if (piix_busmaster[channel].count < (size - transferred)) - { -// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = piix_busmaster[channel].count; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(data + transferred, &ram[piix_busmaster[channel].addr], count); - } - transferred += piix_busmaster[channel].count; - piix_busmaster[channel].addr += piix_busmaster[channel].count; - piix_busmaster[channel].count = 0; - } - else - { -// pclog("Transferring larger - %i bytes\n", size - transferred); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = size - transferred; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(data + transferred, &ram[piix_busmaster[channel].addr], count); - } - piix_busmaster[channel].addr += (size - transferred); - piix_busmaster[channel].count -= (size - transferred); - transferred += (size - transferred); - } - -// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); - - if (!piix_busmaster[channel].count) - { -// pclog("DMA on channel %i - block over\n", channel); - if (piix_busmaster[channel].eot) /*End of transfer?*/ - { -// pclog("DMA on channel %i - transfer over\n", channel); - piix_busmaster[channel].status &= ~1; - } - else - piix_bus_master_next_addr(channel); - } - } - return 0; -} - -void piix_bus_master_set_irq(int channel) -{ - piix_busmaster[channel].status |= 4; -} void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) { @@ -379,8 +178,8 @@ void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/ card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00; card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00; - - ide_set_bus_master(piix_bus_master_data_read, piix_bus_master_data_write, piix_bus_master_set_irq); + + sff_bus_master_init(piix_busmaster); pci_set_card_routing(pci_a, PCI_INTA); pci_set_card_routing(pci_b, PCI_INTB); diff --git a/src/vt82c586b.c b/src/vt82c586b.c index fd67002..34a064b 100644 --- a/src/vt82c586b.c +++ b/src/vt82c586b.c @@ -1,6 +1,8 @@ #include #include "ibm.h" +#include "ide.h" +#include "ide_sff8038i.h" #include "io.h" #include "mem.h" #include "pci.h" @@ -16,6 +18,8 @@ static struct uint8_t power_regs[256]; uint8_t sysctrl; + + sff_busmaster_t busmaster[2]; } vt82c586b; static uint8_t vt82c586b_read(int func, int addr, void *priv) @@ -101,7 +105,7 @@ static void vt82c586b_pci_isa_bridge_write(int addr, uint8_t val) static void vt82c586b_ide_write(int addr, uint8_t val) { /*Read-only addresses*/ - if ((addr < 6) || (addr == 8) + if ((addr < 4) || (addr == 5) || (addr == 8) || (addr >= 0xa && addr < 0x0d) || (addr >= 0x0e && addr < 0x20) || (addr >= 0x22 && addr < 0x3c) @@ -114,7 +118,7 @@ static void vt82c586b_ide_write(int addr, uint8_t val) switch (addr) { case 4: - vt82c586b.ide_regs[4] = (val & 8) | 7; + vt82c586b.ide_regs[4] = val & 0x85; break; case 6: vt82c586b.ide_regs[6] &= ~(val & 0xb0); @@ -132,11 +136,32 @@ static void vt82c586b_ide_write(int addr, uint8_t val) vt82c586b.ide_regs[addr] = val; break; } + + if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ + { + uint16_t base = (vt82c586b.ide_regs[0x20] & 0xf0) | (vt82c586b.ide_regs[0x21] << 8); + io_removehandler(0, 0x10000, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, vt82c586b.busmaster); + if (vt82c586b.ide_regs[0x04] & 1) + io_sethandler(base, 0x10, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, vt82c586b.busmaster); + } + if (addr == 4 || addr == 0x40) + { + ide_pri_disable(); + ide_sec_disable(); + if (vt82c586b.ide_regs[0x04] & 1) + { + if (vt82c586b.ide_regs[0x40] & 0x02) + ide_pri_enable(); + if (vt82c586b.ide_regs[0x40] & 0x01) + ide_sec_enable(); + } + } } static void vt82c586b_usb_write(int addr, uint8_t val) { /*Read-only addresses*/ - if ((addr < 7) || (addr >= 8 && addr < 0xd) + if ((addr < 4) || (addr == 5) || (addr == 6) + || (addr >= 8 && addr < 0xd) || (addr >= 0xe && addr < 0x20) || (addr >= 0x22 && addr < 0x3c) || (addr >= 0x3e && addr < 0x40) @@ -147,6 +172,9 @@ static void vt82c586b_usb_write(int addr, uint8_t val) switch (addr) { + case 4: + vt82c586b.usb_regs[4] = val & 0x97; + break; case 7: vt82c586b.usb_regs[7] = val & 0x7f; break; @@ -307,4 +335,9 @@ void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) pci_set_card_routing(pci_c, PCI_INTC); if (pci_d) pci_set_card_routing(pci_d, PCI_INTD); + + sff_bus_master_init(vt82c586b.busmaster); + + ide_pri_disable(); + ide_sec_disable(); } From da2d819ed4d5d9fdd7aa85b6f28995043fc20e60 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 3 Dec 2018 21:59:41 +0000 Subject: [PATCH 078/181] Added WinChip 2 emulation, along with (currently non-recompiled) 3DNow! instruction emulation. --- src/386_ops.h | 112 ++++++++++++-- src/codegen.c | 2 +- src/cpu.c | 146 ++++++++++++++++++- src/cpu.h | 15 +- src/ibm.h | 1 + src/model.c | 2 +- src/x86_ops.h | 8 + src/x86_ops_3dnow.h | 346 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 607 insertions(+), 25 deletions(-) create mode 100644 src/x86_ops_3dnow.h diff --git a/src/386_ops.h b/src/386_ops.h index f091c93..2ad1789 100644 --- a/src/386_ops.h +++ b/src/386_ops.h @@ -104,6 +104,15 @@ static inline uint32_t POP_L_seg(uint32_t seg) return ret; } +static int ILLEGAL(uint32_t fetchdat) +{ + cpu_state.pc = cpu_state.oldpc; + +// fatal("Illegal instruction %08X\n", fetchdat); + x86illegal(); + return 0; +} + #include "x86_ops_arith.h" #include "x86_ops_atomic.h" #include "x86_ops_bcd.h" @@ -118,6 +127,7 @@ static inline uint32_t POP_L_seg(uint32_t seg) #include "x86_ops_jump.h" #include "x86_ops_misc.h" #include "x86_ops_mmx.h" +#include "x86_ops_3dnow.h" #include "x86_ops_mmx_arith.h" #include "x86_ops_mmx_cmp.h" #include "x86_ops_mmx_logic.h" @@ -140,15 +150,6 @@ static inline uint32_t POP_L_seg(uint32_t seg) #include "x86_ops_string.h" #include "x86_ops_xchg.h" -static int ILLEGAL(uint32_t fetchdat) -{ - cpu_state.pc = cpu_state.oldpc; - -// fatal("Illegal instruction %08X\n", fetchdat); - x86illegal(); - return 0; -} - static int op0F_w_a16(uint32_t fetchdat) { int opcode = fetchdat & 0xff; @@ -455,7 +456,98 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -OpFn OP_TABLE(pentium_0f)[1024] = +OpFn OP_TABLE(winchip2_0f)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, +/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, +/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, +/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, +/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, +/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, +/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, +/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, +/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, +}; + +OpFn OP_TABLE(pentium_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ diff --git a/src/codegen.c b/src/codegen.c index 7a74756..f0f1873 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -276,7 +276,7 @@ static uint8_t opcode_modrm[256] = }; static uint8_t opcode_0f_modrm[256] = { - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/ diff --git a/src/cpu.c b/src/cpu.c index c5958c5..c265d26 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -34,6 +34,7 @@ OpFn *x86_dynarec_opcodes_df_a16; OpFn *x86_dynarec_opcodes_df_a32; OpFn *x86_dynarec_opcodes_REPE; OpFn *x86_dynarec_opcodes_REPNE; +OpFn *x86_dynarec_opcodes_3DNOW; OpFn *x86_opcodes; OpFn *x86_opcodes_0f; @@ -55,6 +56,7 @@ OpFn *x86_opcodes_df_a16; OpFn *x86_opcodes_df_a32; OpFn *x86_opcodes_REPE; OpFn *x86_opcodes_REPNE; +OpFn *x86_opcodes_3DNOW; enum { @@ -68,6 +70,12 @@ enum CPUID_MMX = (1 << 23) }; +/*Addition flags returned by CPUID function 0x80000001*/ +enum +{ + CPUID_3DNOW = (1 << 31) +}; + int cpu = 3, cpu_manufacturer = 0; CPU *cpu_s; int cpu_multi; @@ -79,6 +87,7 @@ int cpu_hasMMX, cpu_hasMSR; int cpu_hasCR4; int cpu_hasCX8; int cpu_hasVME; +int cpu_has3DNOW; int cpu_use_dynarec; int cpu_cyrix_alignment; @@ -402,8 +411,22 @@ CPU cpus_WinChip[] = {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2}, {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7}, {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_WinChip_SS7[] = +{ + /*IDT WinChip (Super Socket 7)*/ + {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, {"", -1, 0, 0, 0} }; @@ -505,6 +528,7 @@ void cpu_set() cpu_hasMSR = 0; cpu_hasCR4 = 0; cpu_hasCX8 = 0; + cpu_has3DNOW = 0; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; has_vlb = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type <= CPU_Cx5x86); @@ -548,8 +572,10 @@ void cpu_set() x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); x86_opcodes_REPE = ops_REPE; x86_opcodes_REPNE = ops_REPNE; + x86_opcodes_3DNOW = ops_3DNOW; x86_dynarec_opcodes_REPE = dynarec_ops_REPE; x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; + x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW; if (hasfpu) { @@ -950,7 +976,7 @@ void cpu_set() timing_bt = 3-1; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ cpu_hasrdtsc = 1; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + msr.fcr = (1 << 8) | (1 << 16); cpu_hasMMX = cpu_hasMSR = 1; cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; @@ -978,6 +1004,46 @@ void cpu_set() codegen_timing_set(&codegen_timing_winchip); break; + case CPU_WINCHIP2: + x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 2; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 2; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + cpu_hasrdtsc = 1; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); + cpu_hasMMX = cpu_hasMSR = cpu_has3DNOW = 1; + cpu_hasCR4 = 1; + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; + /*unknown*/ + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 7; + timing_iret_v86 = 26; + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 4; + timing_call_pm = 15; + timing_call_pm_gate = 26; + timing_call_pm_gate_inner = 35; + timing_retf_rm = 4; + timing_retf_pm = 7; + timing_retf_pm_outer = 23; + timing_jmp_rm = 5; + timing_jmp_pm = 7; + timing_jmp_pm_gate = 17; + timing_misaligned = 2; + cpu_cyrix_alignment = 1; + codegen_timing_set(&codegen_timing_winchip); + break; + case CPU_PENTIUM: x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); timing_rr = 1; /*register dest - register src*/ @@ -1308,7 +1374,7 @@ void cpu_CPUID() else { EBX = 0x746e6543; /*CentaurHauls*/ - ECX = 0x736c7561; + ECX = 0x736c7561; EDX = 0x48727561; } } @@ -1317,14 +1383,74 @@ void cpu_CPUID() EAX = 0x540; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_hasCX8) - EDX |= CPUID_CMPXCHG8B; + if (cpu_hasCX8) + EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) EDX |= CPUID_MMX; } else EAX = EBX = ECX = EDX = 0; break; + + case CPU_WINCHIP2: + switch (EAX) + { + case 0: + EAX = 1; + if (msr.fcr2 & (1 << 14)) + { + EBX = msr.fcr3 >> 32; + ECX = msr.fcr3 & 0xffffffff; + EDX = msr.fcr2 >> 32; + } + else + { + EBX = 0x746e6543; /*CentaurHauls*/ + ECX = 0x736c7561; + EDX = 0x48727561; + } + break; + case 1: + EAX = 0x580; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_hasCX8) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000005; + break; + case 0x80000001: + EAX = 0x580; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_hasCX8) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + if (cpu_has3DNOW) + EDX |= CPUID_3DNOW; + break; + + case 0x80000002: /*Processor name string*/ + EAX = 0x20544449; /*IDT WinChip 2-3D*/ + EBX = 0x436e6957; + ECX = 0x20706968; + EDX = 0x44332d32; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x08800880; /*TLBs*/ + ECX = 0x20040120; /*L1 data cache*/ + EDX = 0x20020120; /*L1 instruction cache*/ + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; case CPU_PENTIUM: if (!EAX) @@ -1447,6 +1573,7 @@ void cpu_RDMSR() switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type) { case CPU_WINCHIP: + case CPU_WINCHIP2: EAX = EDX = 0; switch (ECX) { @@ -1507,6 +1634,7 @@ void cpu_WRMSR() switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type) { case CPU_WINCHIP: + case CPU_WINCHIP2: switch (ECX) { case 0x02: @@ -1525,9 +1653,13 @@ void cpu_WRMSR() msr.fcr = EAX; cpu_hasMMX = EAX & (1 << 9); if (EAX & (1 << 1)) - cpu_hasCX8 = 1; + cpu_hasCX8 = 1; else - cpu_hasCX8 = 0; + cpu_hasCX8 = 0; + if ((EAX & (1 << 20)) && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_WINCHIP2) + cpu_has3DNOW = 1; + else + cpu_has3DNOW = 0; if (EAX & (1 << 29)) CPUID = 0; else diff --git a/src/cpu.h b/src/cpu.h index ca6242f..acde362 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -28,12 +28,13 @@ extern int cpu, cpu_manufacturer; /*586 class CPUs*/ #define CPU_WINCHIP 15 -#define CPU_PENTIUM 16 -#define CPU_PENTIUMMMX 17 -#define CPU_Cx6x86 18 -#define CPU_Cx6x86MX 19 -#define CPU_Cx6x86L 20 -#define CPU_CxGX1 21 +#define CPU_WINCHIP2 16 +#define CPU_PENTIUM 17 +#define CPU_PENTIUMMMX 18 +#define CPU_Cx6x86 19 +#define CPU_Cx6x86MX 20 +#define CPU_Cx6x86L 21 +#define CPU_CxGX1 22 #define MANU_INTEL 0 #define MANU_AMD 1 @@ -84,6 +85,7 @@ extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; extern CPU cpus_WinChip[]; +extern CPU cpus_WinChip_SS7[]; extern CPU cpus_Pentium5V[]; extern CPU cpus_PentiumS5[]; extern CPU cpus_Pentium[]; @@ -111,6 +113,7 @@ extern int cpu_hasMMX; extern int cpu_hasCR4; extern int cpu_hasVME; extern int cpu_hasCX8; +extern int cpu_has3DNOW; #define CR4_TSD (1 << 2) #define CR4_DE (1 << 3) diff --git a/src/ibm.h b/src/ibm.h index fb7865c..e99c232 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -132,6 +132,7 @@ typedef union MMX_REG int16_t sw[4]; uint8_t b[8]; int8_t sb[8]; + float f[2]; } MMX_REG; struct diff --git a/src/model.c b/src/model.c index 7d3a540..015eb48 100644 --- a/src/model.c +++ b/src/model.c @@ -193,7 +193,7 @@ MODEL models[] = {"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 256, 1, at_i430vx_init, NULL}, - {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL}, + {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip_SS7}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL}, {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0} }; diff --git a/src/x86_ops.h b/src/x86_ops.h index 7919ec4..73a0b6f 100644 --- a/src/x86_ops.h +++ b/src/x86_ops.h @@ -25,6 +25,7 @@ extern OpFn *x86_dynarec_opcodes_df_a16; extern OpFn *x86_dynarec_opcodes_df_a32; extern OpFn *x86_dynarec_opcodes_REPE; extern OpFn *x86_dynarec_opcodes_REPNE; +extern OpFn *x86_dynarec_opcodes_3DNOW; extern OpFn dynarec_ops_286[1024]; extern OpFn dynarec_ops_286_0f[1024]; @@ -33,6 +34,7 @@ extern OpFn dynarec_ops_386[1024]; extern OpFn dynarec_ops_386_0f[1024]; extern OpFn dynarec_ops_winchip_0f[1024]; +extern OpFn dynarec_ops_winchip2_0f[1024]; extern OpFn dynarec_ops_pentium_0f[1024]; extern OpFn dynarec_ops_pentiummmx_0f[1024]; @@ -67,6 +69,8 @@ extern OpFn dynarec_ops_fpu_686_df_a32[256]; extern OpFn dynarec_ops_REPE[1024]; extern OpFn dynarec_ops_REPNE[1024]; +extern OpFn dynarec_ops_3DNOW[256]; + extern OpFn *x86_opcodes; extern OpFn *x86_opcodes_0f; extern OpFn *x86_opcodes_d8_a16; @@ -87,6 +91,7 @@ extern OpFn *x86_opcodes_df_a16; extern OpFn *x86_opcodes_df_a32; extern OpFn *x86_opcodes_REPE; extern OpFn *x86_opcodes_REPNE; +extern OpFn *x86_opcodes_3DNOW; extern OpFn ops_286[1024]; extern OpFn ops_286_0f[1024]; @@ -95,6 +100,7 @@ extern OpFn ops_386[1024]; extern OpFn ops_386_0f[1024]; extern OpFn ops_winchip_0f[1024]; +extern OpFn ops_winchip2_0f[1024]; extern OpFn ops_pentium_0f[1024]; extern OpFn ops_pentiummmx_0f[1024]; @@ -130,4 +136,6 @@ extern OpFn ops_fpu_686_df_a32[256]; extern OpFn ops_REPE[1024]; extern OpFn ops_REPNE[1024]; +extern OpFn ops_3DNOW[256]; + #endif /*_X86_OPS_H*/ diff --git a/src/x86_ops_3dnow.h b/src/x86_ops_3dnow.h new file mode 100644 index 0000000..d57a3a3 --- /dev/null +++ b/src/x86_ops_3dnow.h @@ -0,0 +1,346 @@ +#include + +static int opPREFETCH_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + + CLOCK_CYCLES(1); + return 0; +} +static int opPREFETCH_a32(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + + CLOCK_CYCLES(1); + return 0; +} + +static int opFEMMS(uint32_t fetchdat) +{ + ILLEGAL_ON(!cpu_hasMMX); + if (cr0 & 4) + { + x86_int(7); + return 1; + } + x87_emms(); + CLOCK_CYCLES(1); + return 0; +} + +static int opPAVGUSB(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] + src.b[0] + 1) >> 1; + cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] + src.b[1] + 1) >> 1; + cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] + src.b[2] + 1) >> 1; + cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] + src.b[3] + 1) >> 1; + cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] + src.b[4] + 1) >> 1; + cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] + src.b[5] + 1) >> 1; + cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] + src.b[6] + 1) >> 1; + cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] + src.b[7] + 1) >> 1; + + return 0; +} +static int opPF2ID(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].sl[0] = (int32_t)src.f[0]; + cpu_state.MM[cpu_reg].sl[1] = (int32_t)src.f[1]; + + return 0; +} +static int opPFACC(uint32_t fetchdat) +{ + MMX_REG src; + float tempf; + + MMX_GETSRC(); + + tempf = cpu_state.MM[cpu_reg].f[0] + cpu_state.MM[cpu_reg].f[1]; + cpu_state.MM[cpu_reg].f[1] = src.f[0] + src.f[1]; + cpu_state.MM[cpu_reg].f[0] = tempf; + + return 0; +} +static int opPFADD(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] += src.f[0]; + cpu_state.MM[cpu_reg].f[1] += src.f[1]; + + return 0; +} +static int opPFCMPEQ(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] == src.f[0]) ? 0xffffffff : 0; + cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] == src.f[1]) ? 0xffffffff : 0; + + return 0; +} +static int opPFCMPGE(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] >= src.f[0]) ? 0xffffffff : 0; + cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] >= src.f[1]) ? 0xffffffff : 0; + + return 0; +} +static int opPFCMPGT(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] > src.f[0]) ? 0xffffffff : 0; + cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] > src.f[1]) ? 0xffffffff : 0; + + return 0; +} +static int opPFMAX(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + if (src.f[0] > cpu_state.MM[cpu_reg].f[0]) + cpu_state.MM[cpu_reg].f[0] = src.f[0]; + if (src.f[1] > cpu_state.MM[cpu_reg].f[1]) + cpu_state.MM[cpu_reg].f[1] = src.f[1]; + + return 0; +} +static int opPFMIN(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + if (src.f[0] < cpu_state.MM[cpu_reg].f[0]) + cpu_state.MM[cpu_reg].f[0] = src.f[0]; + if (src.f[1] < cpu_state.MM[cpu_reg].f[1]) + cpu_state.MM[cpu_reg].f[1] = src.f[1]; + + return 0; +} +static int opPFMUL(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] *= src.f[0]; + cpu_state.MM[cpu_reg].f[1] *= src.f[1]; + + return 0; +} +static int opPFRCP(uint32_t fetchdat) +{ + union + { + uint32_t i; + float f; + } src; + + if (cpu_mod == 3) + { + src.f = cpu_state.MM[cpu_rm].f[0]; + CLOCK_CYCLES(1); + } + else + { + SEG_CHECK_READ(cpu_state.ea_seg); + src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); + } + + cpu_state.MM[cpu_reg].f[0] = 1.0/src.f; + cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0]; + + return 0; +} +/*Since opPFRCP() calculates a full precision reciprocal, treat the followup iterations as MOVs*/ +static int opPFRCPIT1(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] = src.f[0]; + cpu_state.MM[cpu_reg].f[1] = src.f[1]; + + return 0; +} +static int opPFRCPIT2(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] = src.f[0]; + cpu_state.MM[cpu_reg].f[1] = src.f[1]; + + return 0; +} +static int opPFRSQRT(uint32_t fetchdat) +{ + union + { + uint32_t i; + float f; + } src; + + if (cpu_mod == 3) + { + src.f = cpu_state.MM[cpu_rm].f[0]; + CLOCK_CYCLES(1); + } + else + { + SEG_CHECK_READ(cpu_state.ea_seg); + src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); + } + + cpu_state.MM[cpu_reg].f[0] = 1.0/sqrt(src.f); + cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0]; + + return 0; +} +/*Since opPFRSQRT() calculates a full precision inverse square root, treat the followup iteration as a NOP*/ +static int opPFRSQIT1(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + UNUSED(src); + + return 0; +} +static int opPFSUB(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] -= src.f[0]; + cpu_state.MM[cpu_reg].f[1] -= src.f[1]; + + return 0; +} +static int opPFSUBR(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] = src.f[0] - cpu_state.MM[cpu_reg].f[0]; + cpu_state.MM[cpu_reg].f[1] = src.f[1] - cpu_state.MM[cpu_reg].f[1]; + + return 0; +} +static int opPI2FD(uint32_t fetchdat) +{ + MMX_REG src; + + MMX_GETSRC(); + + cpu_state.MM[cpu_reg].f[0] = (float)src.sl[0]; + cpu_state.MM[cpu_reg].f[1] = (float)src.sl[1]; + + return 0; +} +static int opPMULHRW(uint32_t fetchdat) +{ + if (cpu_mod == 3) + { + cpu_state.MM[cpu_reg].w[0] = (((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)cpu_state.MM[cpu_rm].sw[0]) + 0x8000) >> 16; + cpu_state.MM[cpu_reg].w[1] = (((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)cpu_state.MM[cpu_rm].sw[1]) + 0x8000) >> 16; + cpu_state.MM[cpu_reg].w[2] = (((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)cpu_state.MM[cpu_rm].sw[2]) + 0x8000) >> 16; + cpu_state.MM[cpu_reg].w[3] = (((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)cpu_state.MM[cpu_rm].sw[3]) + 0x8000) >> 16; + CLOCK_CYCLES(1); + } + else + { + MMX_REG src; + + SEG_CHECK_READ(cpu_state.ea_seg); + src.l[0] = readmeml(easeg, cpu_state.eaaddr); + src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; + cpu_state.MM[cpu_reg].w[0] = ((int32_t)(cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + 0x8000) >> 16; + cpu_state.MM[cpu_reg].w[1] = ((int32_t)(cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) + 0x8000) >> 16; + cpu_state.MM[cpu_reg].w[2] = ((int32_t)(cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + 0x8000) >> 16; + cpu_state.MM[cpu_reg].w[3] = ((int32_t)(cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) + 0x8000) >> 16; + CLOCK_CYCLES(2); + } + return 0; +} + +OpFn OP_TABLE(3DNOW)[256] = +{ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPI2FD, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPF2ID, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ opPFCMPGE, ILLEGAL, ILLEGAL, ILLEGAL, opPFMIN, ILLEGAL, opPFRCP, opPFRSQRT, ILLEGAL, ILLEGAL, opPFSUB, ILLEGAL, ILLEGAL, ILLEGAL, opPFADD, ILLEGAL, +/*a0*/ opPFCMPGT, ILLEGAL, ILLEGAL, ILLEGAL, opPFMAX, ILLEGAL, opPFRCPIT1, opPFRSQIT1, ILLEGAL, ILLEGAL, opPFSUBR, ILLEGAL, ILLEGAL, ILLEGAL, opPFACC, ILLEGAL, +/*b0*/ opPFCMPEQ, ILLEGAL, ILLEGAL, ILLEGAL, opPFMUL, ILLEGAL, opPFRCPIT2, opPMULHRW, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPAVGUSB, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +static int op3DNOW_a16(uint32_t fetchdat) +{ + uint8_t opcode; + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + opcode = fastreadb(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + return x86_opcodes_3DNOW[opcode](0); +} +static int op3DNOW_a32(uint32_t fetchdat) +{ + uint8_t opcode; + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + opcode = fastreadb(cs + cpu_state.pc); + if (cpu_state.abrt) return 1; + cpu_state.pc++; + + return x86_opcodes_3DNOW[opcode](0); +} From ca39b51803e9b263f0e06c95e0c8776423450eb6 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 4 Dec 2018 21:35:26 +0000 Subject: [PATCH 079/181] Fix address calculation on PCMPEQD and PCMPGTD. --- src/x86_ops_mmx_cmp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86_ops_mmx_cmp.h b/src/x86_ops_mmx_cmp.h index ea090f5..b61ac67 100644 --- a/src/x86_ops_mmx_cmp.h +++ b/src/x86_ops_mmx_cmp.h @@ -166,7 +166,7 @@ static int opPCMPEQD_a32(uint32_t fetchdat) MMX_ENTER(); - fetch_ea_16(fetchdat); + fetch_ea_32(fetchdat); MMX_GETSRC(); cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].l[0] == src.l[0]) ? 0xffffffff : 0; @@ -195,7 +195,7 @@ static int opPCMPGTD_a32(uint32_t fetchdat) MMX_ENTER(); - fetch_ea_16(fetchdat); + fetch_ea_32(fetchdat); MMX_GETSRC(); cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].sl[0] > src.sl[0]) ? 0xffffffff : 0; From 9b8b6c2c706df7c37c4bfd481f115906e927112e Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 4 Dec 2018 21:35:51 +0000 Subject: [PATCH 080/181] Add Winchip 2A CPUs. --- src/cpu.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index c265d26..750f473 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -414,19 +414,25 @@ CPU cpus_WinChip[] = {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, {"", -1, 0, 0, 0} }; CPU cpus_WinChip_SS7[] = { /*IDT WinChip (Super Socket 7)*/ - {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, - {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, - {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 2A/266", CPU_WINCHIP2, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2A/300", CPU_WINCHIP2, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, {"", -1, 0, 0, 0} }; From 7ec6f1e4ce9e7c4b875845939111c31bc1040745 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 5 Dec 2018 20:54:56 +0000 Subject: [PATCH 081/181] Added Winchip 2 timing model. --- src/codegen.h | 1 + src/codegen_timing_common.c | 4 +- src/codegen_timing_winchip2.c | 753 ++++++++++++++++++++++++++++++++++ src/cpu.c | 2 +- 4 files changed, 757 insertions(+), 3 deletions(-) create mode 100644 src/codegen_timing_winchip2.c diff --git a/src/codegen.h b/src/codegen.h index 93657a1..8e40af1 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -334,6 +334,7 @@ extern codegen_timing_t codegen_timing_pentium; extern codegen_timing_t codegen_timing_686; extern codegen_timing_t codegen_timing_486; extern codegen_timing_t codegen_timing_winchip; +extern codegen_timing_t codegen_timing_winchip2; void codegen_timing_set(codegen_timing_t *timing); diff --git a/src/codegen_timing_common.c b/src/codegen_timing_common.c index b56335a..43aa4b8 100644 --- a/src/codegen_timing_common.c +++ b/src/codegen_timing_common.c @@ -274,7 +274,7 @@ uint64_t opcode_deps_0f[256] = /*00*/ MODRM, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + 0, MODRM, 0, MODRM, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, @@ -356,7 +356,7 @@ uint64_t opcode_deps_0f_mod3[256] = /*00*/ MODRM, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + 0, MODRM, 0, MODRM, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/codegen_timing_winchip2.c b/src/codegen_timing_winchip2.c new file mode 100644 index 0000000..0644298 --- /dev/null +++ b/src/codegen_timing_winchip2.c @@ -0,0 +1,753 @@ +/*Since IDT/Centaur didn't document cycle timings in the WinChip datasheets, and + I don't currently own a WinChip 2 to test against, most of the timing here is + a guess. This code makes the current (probably wrong) assumptions : + - FPU uses same timings as a Pentium, except for FXCH (which doesn't pair) + - 3DNow! instructions perfectly pair + - MMX follows mostly Pentium rules - one pipeline has shift/pack, one has + multiply, and other instructions can execute in either pipeline + - Instructions with prefixes can pair if both instructions are fully decoded + when the first instruction starts execution.*/ +#include "ibm.h" +#include "cpu.h" +#include "x86.h" +#include "x86_ops.h" +#include "x87.h" +#include "mem.h" +#include "codegen.h" +#include "codegen_ops.h" +#include "codegen_timing_common.h" + +/*Instruction has different execution time for 16 and 32 bit data. Does not pair */ +#define CYCLES_HAS_MULTI (1 << 31) + +#define CYCLES_FPU (1 << 30) + +#define CYCLES_IS_MMX_MUL (1 << 29) +#define CYCLES_IS_MMX_SHIFT (1 << 28) +#define CYCLES_IS_MMX_ANY (1 << 27) +#define CYCLES_IS_3DNOW (1 << 26) + +#define CYCLES_MMX_MUL(c) (CYCLES_IS_MMX_MUL | c) +#define CYCLES_MMX_SHIFT(c) (CYCLES_IS_MMX_SHIFT | c) +#define CYCLES_MMX_ANY(c) (CYCLES_IS_MMX_ANY | c) +#define CYCLES_3DNOW(c) (CYCLES_IS_3DNOW | c) + +#define CYCLES_IS_MMX (CYCLES_IS_MMX_MUL | CYCLES_IS_MMX_SHIFT | CYCLES_IS_MMX_ANY | CYCLES_IS_3DNOW) + +#define GET_CYCLES(c) (c & ~(CYCLES_HAS_MULTI | CYCLES_FPU | CYCLES_IS_MMX)) + +#define CYCLES(c) c +#define CYCLES2(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8)) + +/*comp_time = cycles until instruction complete + i_overlap = cycles that overlap with integer + f_overlap = cycles that overlap with subsequent FPU*/ +#define FPU_CYCLES(comp_time, i_overlap, f_overlap) (comp_time) | (i_overlap << 8) | (f_overlap << 16) | CYCLES_FPU + +#define FPU_COMP_TIME(timing) (timing & 0xff) +#define FPU_I_OVERLAP(timing) ((timing >> 8) & 0xff) +#define FPU_F_OVERLAP(timing) ((timing >> 16) & 0xff) + +#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing)) + +#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing)) + +#define FPU_RESULT_LATENCY(timing) ((timing >> 8) & 0xff) + +#define INVALID 0 + +static uint32_t opcode_timings[256] = +{ +/*00*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), INVALID, +/*10*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), +/*20*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), +/*30*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), + +/*40*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17), +/*70*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), + +/*80*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6), +/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3), +/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), +/*b0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), + +/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(3), CYCLES(0), +/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), +/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID +}; + +static uint32_t opcode_timings_mod3[256] = +{ +/*00*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), INVALID, +/*10*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), +/*20*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), +/*30*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), + +/*40*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17), +/*70*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), + +/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1), +/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3), +/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), +/*b0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), + +/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(3), CYCLES(0), +/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), +/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID, +}; + +static uint32_t opcode_timings_0f[256] = +{ +/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1), +/*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*60*/ CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), +/*70*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES(100), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), + +/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), +/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), INVALID, INVALID, CYCLES(3), CYCLES(3), INVALID, CYCLES(13), CYCLES(3), CYCLES(3), INVALID, CYCLES2(18,30), +/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), INVALID, INVALID, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3), + +/*c0*/ CYCLES(4), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*d0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), +/*e0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), +/*f0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, +}; +static uint32_t opcode_timings_0f_mod3[256] = +{ +/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1), +/*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, +/*60*/ CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), +/*70*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES(100), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), + +/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), +/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), INVALID, INVALID, CYCLES(3), CYCLES(3), INVALID, CYCLES(13), CYCLES(3), CYCLES(3), INVALID, CYCLES2(18,30), +/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), INVALID, INVALID, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3), + +/*c0*/ CYCLES(4), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), +/*d0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), +/*e0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), +/*f0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, +}; + +static uint32_t opcode_timings_shift[8] = +{ + CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) +}; +static uint32_t opcode_timings_shift_mod3[8] = +{ + CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) +}; + +static uint32_t opcode_timings_f6[8] = +{ + CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) +}; +static uint32_t opcode_timings_f6_mod3[8] = +{ + CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) +}; +static uint32_t opcode_timings_f7[8] = +{ + CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) +}; +static uint32_t opcode_timings_f7_mod3[8] = +{ + CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) +}; +static uint32_t opcode_timings_ff[8] = +{ + CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID +}; +static uint32_t opcode_timings_ff_mod3[8] = +{ + CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID +}; + +static uint32_t opcode_timings_d8[8] = +{ +/* FADDs FMULs FCOMs FCOMPs*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), +/* FSUBs FSUBRs FDIVs FDIVRs*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) +}; +static uint32_t opcode_timings_d8_mod3[8] = +{ +/* FADD FMUL FCOM FCOMP*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), +/* FSUB FSUBR FDIV FDIVR*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) +}; + +static uint32_t opcode_timings_d9[8] = +{ +/* FLDs FSTs FSTPs*/ + FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), +/* FLDENV FLDCW FSTENV FSTCW*/ + FPU_CYCLES(32,0,0), FPU_CYCLES(8,0,0), FPU_CYCLES(48,0,0), FPU_CYCLES(2,0,0) +}; +static uint32_t opcode_timings_d9_mod3[64] = +{ + /*FLD*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), + /*FXCH*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), + /*FNOP*/ + FPU_CYCLES(3,0,0), INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + /*FSTP*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), +/* opFCHS opFABS*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), INVALID, INVALID, +/* opFTST opFXAM*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(21,4,0), INVALID, INVALID, +/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/ + FPU_CYCLES(2,0,0), FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), +/* opFLDEG2 opFLDLN2 opFLDZ*/ + FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), FPU_CYCLES(2,0,0), INVALID, +/* opF2XM1 opFYL2X opFPTAN opFPATAN*/ + FPU_CYCLES(53,2,2), FPU_CYCLES(103,2,2),FPU_CYCLES(120,36,0),FPU_CYCLES(112,2,2), +/* opFDECSTP opFINCSTP,*/ + INVALID, INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), +/* opFPREM opFSQRT opFSINCOS*/ + FPU_CYCLES(64,2,2), INVALID, FPU_CYCLES(70,69,2),FPU_CYCLES(89,2,2), +/* opFRNDINT opFSCALE opFSIN opFCOS*/ + FPU_CYCLES(9,0,0), FPU_CYCLES(20,5,0), FPU_CYCLES(65,2,2), FPU_CYCLES(65,2,2) +}; + +static uint32_t opcode_timings_da[8] = +{ +/* FIADDl FIMULl FICOMl FICOMPl*/ + FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0), +/* FISUBl FISUBRl FIDIVl FIDIVRl*/ + FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2) +}; +static uint32_t opcode_timings_da_mod3[8] = +{ + INVALID, INVALID, INVALID, INVALID, +/* FCOMPP*/ + INVALID, FPU_CYCLES(1,0,0), INVALID, INVALID +}; + + +static uint32_t opcode_timings_db[8] = +{ +/* FLDil FSTil FSTPil*/ + FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0), +/* FLDe FSTPe*/ + INVALID, FPU_CYCLES(3,0,0), INVALID, FPU_CYCLES(3,0,0) +}; +static uint32_t opcode_timings_db_mod3[64] = +{ + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/* opFNOP opFCLEX opFINIT*/ + INVALID, FPU_CYCLES(1,0,0), FPU_CYCLES(7,0,0), FPU_CYCLES(17,0,0), +/* opFNOP opFNOP*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, +}; + +static uint32_t opcode_timings_dc[8] = +{ +/* FADDd FMULd FCOMd FCOMPd*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), +/* FSUBd FSUBRd FDIVd FDIVRd*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) +}; +static uint32_t opcode_timings_dc_mod3[8] = +{ +/* opFADDr opFMULr*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),INVALID, INVALID, +/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) +}; + +static uint32_t opcode_timings_dd[8] = +{ +/* FLDd FSTd FSTPd*/ + FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), +/* FRSTOR FSAVE FSTSW*/ + FPU_CYCLES(70,0,0), INVALID, FPU_CYCLES(127,0,0), FPU_CYCLES(6,0,0) +}; +static uint32_t opcode_timings_dd_mod3[8] = +{ +/* FFFREE FST FSTP*/ + FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), +/* FUCOM FUCOMP*/ + FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),INVALID, INVALID +}; + +static uint32_t opcode_timings_de[8] = +{ +/* FIADDw FIMULw FICOMw FICOMPw*/ + FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0), +/* FISUBw FISUBRw FIDIVw FIDIVRw*/ + FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2) +}; +static uint32_t opcode_timings_de_mod3[8] = +{ +/* FADDP FMULP FCOMPP*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(1,0,0), +/* FSUBP FSUBRP FDIVP FDIVRP*/ + FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) +}; + +static uint32_t opcode_timings_df[8] = +{ +/* FILDiw FISTiw FISTPiw*/ + FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0), +/* FILDiq FBSTP FISTPiq*/ + INVALID, FPU_CYCLES(3,2,2), FPU_CYCLES(148,0,0), FPU_CYCLES(6,0,0) +}; +static uint32_t opcode_timings_df_mod3[8] = +{ + INVALID, INVALID, INVALID, INVALID, +/* FSTSW AX*/ + FPU_CYCLES(6,0,0), INVALID, INVALID, INVALID +}; + +static uint32_t opcode_timings_8x[8] = +{ + CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) +}; +static uint32_t opcode_timings_8x_mod3[8] = +{ + CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) +}; +static uint32_t opcode_timings_81[8] = +{ + CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) +}; +static uint32_t opcode_timings_81_mod3[8] = +{ + CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) +}; + +static int timing_count; +static uint8_t last_prefix; +static uint32_t regmask_modified; +static int decode_delay, decode_delay_offset; +static int fpu_latency; +static int fpu_st_latency[8]; + +static int u_pipe_full; +static uint32_t u_pipe_opcode; +static uint32_t *u_pipe_timings; +static uint32_t u_pipe_op_32; +static uint32_t u_pipe_regmask; +static uint32_t u_pipe_fetchdat; +static int u_pipe_decode_delay_offset; +static uint64_t *u_pipe_deps; + +int can_pair(uint32_t timing_a, uint32_t timing_b, uint8_t regmask_b) +{ + /*Only MMX/3DNow instructions can pair*/ + if (!(timing_b & CYCLES_IS_MMX)) + return 0; + /*Only one MMX multiply per cycle*/ + if ((timing_a & CYCLES_IS_MMX_MUL) && (timing_b & CYCLES_IS_MMX_MUL)) + return 0; + /*Only one MMX shift/pack per cycle*/ + if ((timing_a & CYCLES_IS_MMX_SHIFT) && (timing_b & CYCLES_IS_MMX_SHIFT)) + return 0; + /*Second instruction can not access registers written by first*/ + if (u_pipe_regmask & regmask_b) + return 0; + /*Must have had enough time to decode prefixes*/ + if ((decode_delay+decode_delay_offset+u_pipe_decode_delay_offset) > 0) + return 0; + + return 1; +} + +static inline int COUNT(uint32_t c, int op_32) +{ + if (c & CYCLES_FPU) + return FPU_I_LATENCY(c); + if (c & CYCLES_HAS_MULTI) + { + if (op_32 & 0x100) + return (c >> 8) & 0xff; + return c & 0xff; + } + return GET_CYCLES(c); +} + +static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) +{ + uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); + + /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not + cause AGIs with each other, but do with instructions that use it explicitly*/ + if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP)) + addr_regmask |= (1 << REG_ESP); + + return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; +} + +static int codegen_fpu_latencies(uint64_t deps, int reg) +{ + int latency = fpu_latency; + + if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) + latency = fpu_st_latency[0]; + if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) + latency = fpu_st_latency[1]; + if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) + latency = fpu_st_latency[reg]; + + return latency; +} + +#define SUB_AND_CLAMP(latency, count) \ + latency -= count; \ + if (latency < 0) \ + latency = 0 + +static void codegen_fpu_latency_clock(int count) +{ + SUB_AND_CLAMP(fpu_latency, count); + SUB_AND_CLAMP(fpu_st_latency[0], count); + SUB_AND_CLAMP(fpu_st_latency[1], count); + SUB_AND_CLAMP(fpu_st_latency[2], count); + SUB_AND_CLAMP(fpu_st_latency[3], count); + SUB_AND_CLAMP(fpu_st_latency[4], count); + SUB_AND_CLAMP(fpu_st_latency[5], count); + SUB_AND_CLAMP(fpu_st_latency[6], count); + SUB_AND_CLAMP(fpu_st_latency[7], count); +} + +static void codegen_instruction(uint32_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) +{ + int instr_cycles, latency = 0; + + if ((timings[opcode] & CYCLES_FPU) && !(deps[opcode] & FPU_FXCH)) + instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7); + else + instr_cycles = 0; + + if ((decode_delay + decode_delay_offset) > 0) + codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles); + else + codegen_fpu_latency_clock(instr_cycles); + instr_cycles += COUNT(timings[opcode], op_32); + instr_cycles += exec_delay; + if ((decode_delay + decode_delay_offset) > 0) + codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset; + else + codegen_block_cycles += instr_cycles; + decode_delay = (-instr_cycles) + 1; + + if (deps[opcode] & FPU_POP) + { + int c; + + for (c = 0; c < 7; c++) + fpu_st_latency[c] = fpu_st_latency[c+1]; + fpu_st_latency[7] = 0; + } + if (deps[opcode] & FPU_POP2) + { + int c; + + for (c = 0; c < 6; c++) + fpu_st_latency[c] = fpu_st_latency[c+2]; + fpu_st_latency[6] = fpu_st_latency[7] = 0; + } + if (timings[opcode] & CYCLES_FPU) + { + /* if (fpu_latency) + fatal("Bad latency FPU\n");*/ + fpu_latency = FPU_F_LATENCY(timings[opcode]); + } + + if (deps[opcode] & FPU_PUSH) + { + int c; + + for (c = 0; c < 7; c++) + fpu_st_latency[c+1] = fpu_st_latency[c]; + fpu_st_latency[0] = 0; + } + if (deps[opcode] & FPU_WRITE_ST0) + { +/* if (fpu_st_latency[0]) + fatal("Bad latency ST0\n");*/ + fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]); + } + if (deps[opcode] & FPU_WRITE_ST1) + { +/* if (fpu_st_latency[1]) + fatal("Bad latency ST1\n");*/ + fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]); + } + if (deps[opcode] & FPU_WRITE_STREG) + { + int reg = fetchdat & 7; + if (deps[opcode] & FPU_POP) + reg--; + if (reg >= 0 && + !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) && + !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1))) + { +/* if (fpu_st_latency[reg]) + fatal("Bad latency STREG %i %08x %i %016llx %02x\n",fpu_st_latency[reg], fetchdat, reg, timings[opcode], opcode);*/ + fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]); + } + } +} + +static void codegen_timing_winchip2_block_start() +{ + regmask_modified = 0; + decode_delay = decode_delay_offset = 0; + u_pipe_full = 0; +} + +static void codegen_timing_winchip2_start() +{ + timing_count = 0; + last_prefix = 0; +} + +static void codegen_timing_winchip2_prefix(uint8_t prefix, uint32_t fetchdat) +{ + if (prefix == 0x0f) + { + /*0fh prefix is 'free'*/ + last_prefix = prefix; + return; + } + /*On WinChip all prefixes take 1 cycle to decode. Decode may be shadowed + by execution of previous instructions*/ + decode_delay_offset++; + last_prefix = prefix; +} + +static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) +{ + uint32_t *timings; + uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); + int agi_stall = 0; + + switch (last_prefix) + { + case 0x0f: + timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; +// pclog("timings 0f\n"); + break; + + case 0xd8: + timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; +// pclog("timings d8\n"); + break; + case 0xd9: + timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; +// pclog("timings d9\n"); + break; + case 0xda: + timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; +// pclog("timings da\n"); + break; + case 0xdb: + timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; +// pclog("timings db\n"); + break; + case 0xdc: + timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; +// pclog("timings dc\n"); + break; + case 0xdd: + timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; +// pclog("timings dd\n"); + break; + case 0xde: + timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; +// pclog("timings de\n"); + break; + case 0xdf: + timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; +// pclog("timings df\n"); + break; + + default: + switch (opcode) + { + case 0x80: case 0x82: case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + opcode = (fetchdat >> 3) & 7; +// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x); + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; +// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x); + break; + + case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; +// pclog("timings c0\n"); + break; + + case 0xf6: + timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; +// pclog("timings f6\n"); + break; + case 0xf7: + timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; +// pclog("timings f7\n"); + break; + case 0xff: + timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; +// pclog("timings ff\n"); + break; + + default: + timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; +// pclog("timings normal\n"); + break; + } + } + + if (u_pipe_full) + { + uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32); + + if (can_pair(u_pipe_timings[u_pipe_opcode], timings[opcode], regmask)) + { + int cycles_a = u_pipe_timings[u_pipe_opcode] & 0xff; + int cycles_b = timings[opcode] & 0xff; + uint32_t timing = (cycles_a > cycles_b) ? u_pipe_timings[u_pipe_opcode] : timings[opcode]; + uint64_t temp_deps = 0; + + if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + + codegen_instruction(&timing, &temp_deps, 0, 0, 0, 0, agi_stall); + u_pipe_full = 0; + decode_delay_offset = 0; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask; + return; + } + else + { + /*No pairing, run first instruction now*/ + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); + u_pipe_full = 0; + regmask_modified = u_pipe_regmask; + } + } + if (timings[opcode] & CYCLES_IS_MMX) + { + /*Might pair with next instruction*/ + u_pipe_full = 1; + u_pipe_opcode = opcode; + u_pipe_timings = timings; + u_pipe_op_32 = op_32; + u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); + u_pipe_fetchdat = fetchdat; + u_pipe_decode_delay_offset = decode_delay_offset; + u_pipe_deps = deps; + decode_delay_offset = 0; + return; + } + + if (check_agi(deps, opcode, fetchdat, op_32)) + agi_stall = 1; + codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall); + decode_delay_offset = 0; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); +} + +static void codegen_timing_winchip2_block_end() +{ + if (u_pipe_full) + { + int agi_stall = 0; + + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); + u_pipe_full = 0; + } +} + +codegen_timing_t codegen_timing_winchip2 = +{ + codegen_timing_winchip2_start, + codegen_timing_winchip2_prefix, + codegen_timing_winchip2_opcode, + codegen_timing_winchip2_block_start, + codegen_timing_winchip2_block_end +}; diff --git a/src/cpu.c b/src/cpu.c index 750f473..59cc22c 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1047,7 +1047,7 @@ void cpu_set() timing_jmp_pm_gate = 17; timing_misaligned = 2; cpu_cyrix_alignment = 1; - codegen_timing_set(&codegen_timing_winchip); + codegen_timing_set(&codegen_timing_winchip2); break; case CPU_PENTIUM: From a9541dadeac6f2c30c0ab12e2cb4023bb6868bf9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 6 Dec 2018 20:02:35 +0000 Subject: [PATCH 082/181] Added preliminary emulation of AMD K6 CPUs. --- src/cpu.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 7 + src/model.c | 4 +- 3 files changed, 383 insertions(+), 2 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index 59cc22c..eca0d0d 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -500,6 +500,55 @@ CPU cpus_Pentium[] = {"", -1, 0, 0, 0} }; +CPU cpus_K6_S7[] = +{ + /*AMD K6*/ + {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6-2/300 AFR-66", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_K6_SS7[] = +{ + /*AMD K6*/ + {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6-2/300", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"K6-2/333", CPU_K6_2, 28, 333333333, 5, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, + {"K6-2/350", CPU_K6_2, 28, 350000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 42}, + {"K6-2/366", CPU_K6_2, 28, 366666666, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 44}, + {"K6-2/380", CPU_K6_2, 28, 380000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 46}, + {"K6-2/400", CPU_K6_2, 28, 400000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, + {"K6-2/450", CPU_K6_2, 28, 450000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-2/475", CPU_K6_2, 28, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, + {"K6-2/500", CPU_K6_2, 28, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + {"K6-2/533", CPU_K6_2, 28, 533333333, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, + {"K6-2/550", CPU_K6_2, 28, 550000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, + {"K6-2+/450", CPU_K6_2P, 28, 450000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-2+/475", CPU_K6_2P, 28, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, + {"K6-2+/500", CPU_K6_2P, 28, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + {"K6-2+/533", CPU_K6_2P, 28, 533333333, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, + {"K6-2+/550", CPU_K6_2P, 28, 550000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, + {"K6-III/400", CPU_K6_3, 28, 400000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, + {"K6-III/450", CPU_K6_3, 28, 450000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-III+/400", CPU_K6_3P, 28, 400000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, + {"K6-III+/450", CPU_K6_3P, 28, 450000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-III+/475", CPU_K6_3P, 28, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, + {"K6-III+/500", CPU_K6_3P, 28, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + {"", -1, 0, 0, 0} +}; + void cpu_set_edx() { EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; @@ -1287,6 +1336,91 @@ void cpu_set() ccr4 = 0x80; break; + case CPU_K6: + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 0; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /*unknown*/ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; + cpu_hasrdtsc = 1; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + cpu_hasMMX = 1; + cpu_hasMSR = 1; + cpu_hasCR4 = 1; + cpu_hasVME = 1; + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; + codegen_timing_set(&codegen_timing_pentium); + break; + + case CPU_K6_2: + case CPU_K6_3: + case CPU_K6_2P: + case CPU_K6_3P: + x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 0; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /*unknown*/ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; + cpu_hasrdtsc = 1; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + cpu_hasMMX = 1; + cpu_hasMSR = 1; + cpu_hasCR4 = 1; + cpu_hasVME = 1; + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; + codegen_timing_set(&codegen_timing_pentium); + break; + default: fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); } @@ -1571,6 +1705,220 @@ void cpu_CPUID() EAX = EBX = ECX = EDX = 0; break; + case CPU_K6: + switch (EAX) + { + case 0: + EAX = 1; + EBX = 0x68747541; /*AuthenticAMD*/ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000005; + break; + case 0x80000001: + EAX = CPUID+0x100; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; + break; + + case 0x80000002: /*Processor name string*/ + EAX = 0x2d444d41; /*AMD-K6tm w/ mult*/ + EBX = 0x6d74364b; + ECX = 0x202f7720; + EDX = 0x746c756d; + break; + + case 0x80000003: /*Processor name string*/ + EAX = 0x64656d69; /*imedia extension*/ + EBX = 0x65206169; + ECX = 0x6e657478; + EDX = 0x6e6f6973; + break; + + case 0x80000004: /*Processor name string*/ + EAX = 0x00000073; /*s*/ + EBX = 0x00000000; + ECX = 0x00000000; + EDX = 0x00000000; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x02800140; /*TLBs*/ + ECX = 0x20020220; /*L1 data cache*/ + EDX = 0x20020220; /*L1 instruction cache*/ + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; + + case CPU_K6_2: + switch (EAX) + { + case 0: + EAX = 1; + EBX = 0x68747541; /*AuthenticAMD*/ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000005; + break; + case 0x80000001: + EAX = CPUID+0x100; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW; + break; + + case 0x80000002: /*Processor name string*/ + EAX = 0x2d444d41; /*AMD-K6(tm) 3D pr*/ + EBX = 0x7428364b; + ECX = 0x3320296d; + EDX = 0x72702044; + break; + + case 0x80000003: /*Processor name string*/ + EAX = 0x7365636f; /*ocessor*/ + EBX = 0x00726f73; + ECX = 0x00000000; + EDX = 0x00000000; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x02800140; /*TLBs*/ + ECX = 0x20020220; /*L1 data cache*/ + EDX = 0x20020220; /*L1 instruction cache*/ + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; + + case CPU_K6_3: + switch (EAX) + { + case 0: + EAX = 1; + EBX = 0x68747541; /*AuthenticAMD*/ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000006; + break; + case 0x80000001: + EAX = CPUID+0x100; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW; + break; + + case 0x80000002: /*Processor name string*/ + EAX = 0x2d444d41; /*AMD-K6(tm) 3D+ P*/ + EBX = 0x7428364b; + ECX = 0x3320296d; + EDX = 0x50202b44; + break; + + case 0x80000003: /*Processor name string*/ + EAX = 0x65636f72; /*rocessor*/ + EBX = 0x726f7373; + ECX = 0x00000000; + EDX = 0x00000000; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x02800140; /*TLBs*/ + ECX = 0x20020220; /*L1 data cache*/ + EDX = 0x20020220; /*L1 instruction cache*/ + break; + + case 0x80000006: /*L2 Cache information*/ + ECX = 0x01004220; + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; + + case CPU_K6_2P: + case CPU_K6_3P: + switch (EAX) + { + case 0: + EAX = 1; + EBX = 0x68747541; /*AuthenticAMD*/ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000007; + break; + case 0x80000001: + EAX = CPUID+0x100; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW; + break; + + case 0x80000002: /*Processor name string*/ + EAX = 0x2d444d41; /*AMD-K6(tm)-III P*/ + EBX = 0x7428364b; + ECX = 0x492d296d; + EDX = 0x50204949; + break; + + case 0x80000003: /*Processor name string*/ + EAX = 0x65636f72; /*rocessor*/ + EBX = 0x726f7373; + ECX = 0x00000000; + EDX = 0x00000000; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x02800140; /*TLBs*/ + ECX = 0x20020220; /*L1 data cache*/ + EDX = 0x20020220; /*L1 instruction cache*/ + break; + + case 0x80000006: /*L2 Cache information*/ + if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_K6_3P) + ECX = 0x01004220; + else + ECX = 0x00804220; + break; + + case 0x80000007: /*PowerNow information*/ + EDX = 7; + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; } } @@ -1632,6 +1980,20 @@ void cpu_RDMSR() break; } break; + case CPU_K6: + case CPU_K6_2: + case CPU_K6_3: + case CPU_K6_2P: + case CPU_K6_3P: + EAX = EDX = 0; + switch (ECX) + { + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + } + break; } } @@ -1700,6 +2062,18 @@ void cpu_WRMSR() break; } break; + case CPU_K6: + case CPU_K6_2: + case CPU_K6_3: + case CPU_K6_2P: + case CPU_K6_3P: + switch (ECX) + { + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + } + break; } } diff --git a/src/cpu.h b/src/cpu.h index acde362..02a1340 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -35,6 +35,11 @@ extern int cpu, cpu_manufacturer; #define CPU_Cx6x86MX 20 #define CPU_Cx6x86L 21 #define CPU_CxGX1 22 +#define CPU_K6 23 +#define CPU_K6_2 24 +#define CPU_K6_3 25 +#define CPU_K6_2P 26 +#define CPU_K6_3P 27 #define MANU_INTEL 0 #define MANU_AMD 1 @@ -90,6 +95,8 @@ extern CPU cpus_Pentium5V[]; extern CPU cpus_PentiumS5[]; extern CPU cpus_Pentium[]; extern CPU cpus_6x86[]; +extern CPU cpus_K6_S7[]; +extern CPU cpus_K6_SS7[]; extern CPU cpus_pcjr[]; extern CPU cpus_europc[]; diff --git a/src/model.c b/src/model.c index 015eb48..d060d67 100644 --- a/src/model.c +++ b/src/model.c @@ -191,9 +191,9 @@ MODEL models[] = {"[Socket 5] Intel Advanced/ZP", ROM_ZAPPA, "zappa", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_zappa_init, NULL}, {"[Socket 5] Packard Bell PB570", ROM_PB570, "pb570", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_pb570_init, NULL}, - {"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 256, 1, at_i430vx_init, NULL}, + {"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_S7}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_i430vx_init, NULL}, - {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip_SS7}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL}, + {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_SS7}, {"IDT", cpus_WinChip_SS7}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL}, {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0} }; From fd10fdd3727dac73bc15ec9bf07ea632be0d48dd Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 6 Dec 2018 20:02:51 +0000 Subject: [PATCH 083/181] Fix ATCLK timings on Winchip 2 CPUs. --- src/cpu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index eca0d0d..1b2e0ef 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -413,9 +413,9 @@ CPU cpus_WinChip[] = {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, (7*8)/2}, {"", -1, 0, 0, 0} }; @@ -427,12 +427,12 @@ CPU cpus_WinChip_SS7[] = {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, - {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, - {"WinChip 2A/266", CPU_WINCHIP2, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2A/300", CPU_WINCHIP2, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, + {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, + {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24}, + {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 28}, + {"WinChip 2A/266", CPU_WINCHIP2, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28}, + {"WinChip 2A/300", CPU_WINCHIP2, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, {"", -1, 0, 0, 0} }; From cfd4ac3a4ff3065e1157f2b3fd03781116b560b1 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 9 Dec 2018 22:17:11 +0000 Subject: [PATCH 084/181] Added initial timing model for K6 CPUs. --- src/codegen.c | 4 +- src/codegen.h | 5 +- src/codegen_timing_486.c | 2 +- src/codegen_timing_686.c | 2 +- src/codegen_timing_common.c | 165 +++ src/codegen_timing_common.h | 2 + src/codegen_timing_k6.c | 2288 +++++++++++++++++++++++++++++++++ src/codegen_timing_pentium.c | 2 +- src/codegen_timing_winchip.c | 2 +- src/codegen_timing_winchip2.c | 2 +- src/cpu.c | 4 +- 11 files changed, 2467 insertions(+), 11 deletions(-) create mode 100644 src/codegen_timing_k6.c diff --git a/src/codegen.c b/src/codegen.c index f0f1873..f42f22c 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -18,7 +18,7 @@ uint16_t *codeblock_hash; void (*codegen_timing_start)(); void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); -void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32); +void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); void (*codegen_timing_block_start)(); void (*codegen_timing_block_end)(); @@ -495,7 +495,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t } generate_call: - codegen_timing_opcode(opcode, fetchdat, op_32); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); codegen_accumulate(ACCREG_ins, 1); codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); diff --git a/src/codegen.h b/src/codegen.h index 8e40af1..e82b904 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -317,7 +317,7 @@ extern int codegen_block_cycles; extern void (*codegen_timing_start)(); extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); -extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32); +extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); extern void (*codegen_timing_block_start)(); extern void (*codegen_timing_block_end)(); @@ -325,7 +325,7 @@ typedef struct codegen_timing_t { void (*start)(); void (*prefix)(uint8_t prefix, uint32_t fetchdat); - void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32); + void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); void (*block_start)(); void (*block_end)(); } codegen_timing_t; @@ -335,6 +335,7 @@ extern codegen_timing_t codegen_timing_686; extern codegen_timing_t codegen_timing_486; extern codegen_timing_t codegen_timing_winchip; extern codegen_timing_t codegen_timing_winchip2; +extern codegen_timing_t codegen_timing_k6; void codegen_timing_set(codegen_timing_t *timing); diff --git a/src/codegen_timing_486.c b/src/codegen_timing_486.c index 4e05e24..cda0436 100644 --- a/src/codegen_timing_486.c +++ b/src/codegen_timing_486.c @@ -296,7 +296,7 @@ void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; } -void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) +void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) { int **timings; uint64_t *deps; diff --git a/src/codegen_timing_686.c b/src/codegen_timing_686.c index 9559e03..dab2b10 100644 --- a/src/codegen_timing_686.c +++ b/src/codegen_timing_686.c @@ -823,7 +823,7 @@ static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_3 return 0; } -void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) +void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) { uint32_t *timings; uint64_t *deps; diff --git a/src/codegen_timing_common.c b/src/codegen_timing_common.c index 43aa4b8..33ac5cf 100644 --- a/src/codegen_timing_common.c +++ b/src/codegen_timing_common.c @@ -434,6 +434,171 @@ uint64_t opcode_deps_0f_mod3[256] = MODRM, MODRM, MODRM, 0, }; +uint64_t opcode_deps_0f0f[256] = +{ +/*00*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, MODRM, 0, 0, + +/*10*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, MODRM, 0, 0, + +/*20*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*30*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*40*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*50*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*60*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*70*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*80*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*90*/ MODRM, 0, 0, 0, + MODRM, 0, MODRM, MODRM, + 0, 0, MODRM, 0, + 0, 0, MODRM, 0, + +/*a0*/ MODRM, 0, 0, 0, + MODRM, 0, MODRM, MODRM, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*b0*/ MODRM, 0, 0, 0, + MODRM, 0, MODRM, MODRM, + 0, 0, 0, 0, + 0, 0, 0, MODRM, + +/*c0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*d0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*e0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*f0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; +uint64_t opcode_deps_0f0f_mod3[256] = +{ +/*00*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, MODRM, 0, 0, + +/*10*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, MODRM, 0, 0, + +/*20*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*30*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*40*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*50*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*60*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*70*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*80*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*90*/ MODRM, 0, 0, 0, + MODRM, 0, MODRM, MODRM, + 0, 0, MODRM, 0, + 0, 0, MODRM, 0, + +/*a0*/ MODRM, 0, 0, 0, + MODRM, 0, MODRM, MODRM, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*b0*/ MODRM, 0, 0, 0, + MODRM, 0, MODRM, MODRM, + 0, 0, 0, 0, + 0, 0, 0, MODRM, + +/*c0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*d0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*e0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + +/*f0*/ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + uint64_t opcode_deps_shift[8] = { MODRM, MODRM, MODRM, MODRM, diff --git a/src/codegen_timing_common.h b/src/codegen_timing_common.h index ac7bd2a..b185270 100644 --- a/src/codegen_timing_common.h +++ b/src/codegen_timing_common.h @@ -82,6 +82,8 @@ extern uint64_t opcode_deps[256]; extern uint64_t opcode_deps_mod3[256]; extern uint64_t opcode_deps_0f[256]; extern uint64_t opcode_deps_0f_mod3[256]; +extern uint64_t opcode_deps_0f0f[256]; +extern uint64_t opcode_deps_0f0f_mod3[256]; extern uint64_t opcode_deps_shift[8]; extern uint64_t opcode_deps_shift_mod3[8]; extern uint64_t opcode_deps_shift_cl[8]; diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c new file mode 100644 index 0000000..a5d0cde --- /dev/null +++ b/src/codegen_timing_k6.c @@ -0,0 +1,2288 @@ +/*Most of the vector instructions here are a total guess. + Some of the timings are based on http://users.atw.hu/instlatx64/AuthenticAMD0000562_K6_InstLatX86.txt*/ +#include "ibm.h" +#include "cpu.h" +#include "model.h" +#include "x86.h" +#include "x86_ops.h" +#include "x87.h" +#include "386_common.h" +#include "mem.h" +#include "codegen.h" +#include "codegen_ops.h" +#include "codegen_timing_common.h" + +typedef enum uop_type_t +{ + UOP_ALU = 0, /*Executes in Integer X or Y units*/ + UOP_ALUX, /*Executes in Integer X unit*/ + UOP_LOAD, /*Executes in Load unit*/ + UOP_STORE, /*Executes in Store unit*/ + UOP_FLOAD, /*Executes in Load unit*/ + UOP_FSTORE, /*Executes in Store unit*/ + UOP_MLOAD, /*Executes in Load unit*/ + UOP_MSTORE, /*Executes in Store unit*/ + UOP_FLOAT, /*Executes in Floating Point unit*/ + UOP_MEU, /*Executes in Multimedia unit*/ + UOP_MEU_SHIFT, /*Executes in Multimedia unit or ALU X/Y. Uses MMX shifter*/ + UOP_MEU_MUL, /*Executes in Multimedia unit or ALU X/Y. Uses MMX/3DNow multiplier*/ + UOP_MEU_3DN, /*Executes in Multimedia unit or ALU X/Y. Uses 3DNow ALU*/ + UOP_BRANCH, /*Executes in Branch unit*/ + UOP_LIMM /*Does not require an execution unit*/ +} uop_type_t; + +typedef enum decode_type_t +{ + DECODE_SHORT, + DECODE_LONG, + DECODE_VECTOR +} decode_type_t; + +#define MAX_UOPS 10 + +typedef struct risc86_uop_t +{ + uop_type_t type; + int throughput; + int latency; +} risc86_uop_t; + +typedef struct risc86_instruction_t +{ + int nr_uops; + decode_type_t decode_type; + risc86_uop_t uop[MAX_UOPS]; +} risc86_instruction_t; + +static const risc86_instruction_t alu_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t alux_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_alu_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_alux_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t alu_store_op = +{ + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t alux_store_op = +{ + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t branch_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t limm_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LIMM, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t load_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} +}; + +static const risc86_instruction_t store_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; + + +static const risc86_instruction_t bswap_op = +{ + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t leave_op = +{ + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t lods_op = +{ + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t loop_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mov_reg_seg_op = +{ + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, +}; +static const risc86_instruction_t movs_op = +{ + .nr_uops = 4, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t pop_reg_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t pop_mem_op = +{ + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t push_imm_op = +{ + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2}, +}; +static const risc86_instruction_t push_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t push_seg_op = +{ + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t stos_op = +{ + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_reg_op = +{ + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_reg_b_op = +{ + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_mem_imm_op = +{ + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_mem_imm_b_op = +{ + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t xchg_op = +{ + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t m3dn_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_3DN, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mmx_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mmx_mul_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t mmx_shift_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_3dn_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_MEU_3DN, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_mmx_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_MEU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_mmx_mul_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t load_mmx_shift_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mload_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MLOAD, .throughput = 1, .latency = 2} +}; + +static const risc86_instruction_t mstore_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MSTORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t pmul_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t pmul_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; + +static const risc86_instruction_t float_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t load_float_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t fstore_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t fdiv_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 40, .latency = 40} +}; +static const risc86_instruction_t fdiv_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_FLOAT, .throughput = 40, .latency = 40} +}; +static const risc86_instruction_t fsin_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 62, .latency = 62} +}; +static const risc86_instruction_t fsqrt_op = +{ + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 41, .latency = 41} +}; + +static const risc86_instruction_t vector_fldcw_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 8, .latency = 8} +}; +static const risc86_instruction_t vector_float_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t vector_float_l_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 50, .latency = 50} +}; +static const risc86_instruction_t vector_flde_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[2] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t vector_fste_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2}, + .uop[1] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t vector_alu1_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu2_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu3_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu6_op = +{ + .nr_uops = 6, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[4] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[5] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux1_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux3_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux6_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[4] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[5] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu_store_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux_store_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_arpl_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_bound_op = +{ + .nr_uops = 4, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_bsx_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_call_far_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_cli_sti_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 7, .latency = 7} +}; +static const risc86_instruction_t vector_cmps_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_cmpsb_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_cmpxchg_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, +}; +static const risc86_instruction_t vector_cmpxchg_b_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, +}; +static const risc86_instruction_t vector_cpuid_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 22, .latency = 22} +}; +static const risc86_instruction_t vector_div16_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_div16_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_div32_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 18, .latency = 18} +}; +static const risc86_instruction_t vector_div32_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 18, .latency = 18} +}; +static const risc86_instruction_t vector_emms_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 25, .latency = 25} +}; +static const risc86_instruction_t vector_enter_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_femms_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 6, .latency = 6} +}; +static const risc86_instruction_t vector_in_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11} +}; +static const risc86_instruction_t vector_ins_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_int_op = +{ + .nr_uops = 5, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 20, .latency = 20}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[4] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_iret_op = +{ + .nr_uops = 5, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[3] = {.type = UOP_ALU, .throughput = 20, .latency = 20}, + .uop[4] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_invd_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1000, .latency = 1000} +}; +static const risc86_instruction_t vector_jmp_far_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_load_alu_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_load_alux_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_loop_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_lss_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_mov_mem_seg_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mov_seg_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_mov_seg_reg_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_mul_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mul_mem_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mul64_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mul64_mem_op = +{ + .nr_uops = 4, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_out_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_outs_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_STORE, .throughput = 10, .latency = 10}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_pusha_op = +{ + .nr_uops = 8, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[4] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[5] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[6] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[7] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_popa_op = +{ + .nr_uops = 8, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[4] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[5] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[6] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[7] = {.type = UOP_LOAD, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_popf_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 17, .latency = 17} +}; +static const risc86_instruction_t vector_push_mem_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_pushf_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_ret_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_retf_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[2] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_scas_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_scasb_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_setcc_mem_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_setcc_reg_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_test_mem_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_test_mem_b_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_xchg_mem_op = +{ + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_xlat_op = +{ + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t vector_wbinvd_op = +{ + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 10000, .latency = 10000} +}; + +#define INVALID NULL + +static const risc86_instruction_t *opcode_timings[256] = +{ +/* ADD ADD ADD ADD*/ +/*00*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* ADD ADD PUSH ES POP ES*/ + &alux_op, &alu_op, &push_seg_op, &vector_mov_seg_mem_op, +/* OR OR OR OR*/ + &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* OR OR PUSH CS */ + &alux_op, &alu_op, &push_seg_op, INVALID, + +/* ADC ADC ADC ADC*/ +/*10*/ &vector_alux_store_op, &vector_alu_store_op, &vector_load_alux_op, &vector_load_alu_op, +/* ADC ADC PUSH SS POP SS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, +/* SBB SBB SBB SBB*/ +/*10*/ &vector_alux_store_op, &vector_alu_store_op, &vector_load_alux_op, &vector_load_alu_op, +/* SBB SBB PUSH DS POP DS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, + +/* AND AND AND AND*/ +/*20*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* AND AND DAA*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, +/* SUB SUB SUB SUB*/ + &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* SUB SUB DAS*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, + +/* XOR XOR XOR XOR*/ +/*30*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* XOR XOR AAA*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, +/* CMP CMP CMP CMP*/ + &load_alux_op, &load_alu_op, &load_alux_op, &load_alu_op, +/* CMP CMP AAS*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, + +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ &alu_op, &alu_op, &alu_op, &alu_op, +/* INC ESP INC EBP INC ESI INC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, + +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ &store_op, &store_op, &store_op, &store_op, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + &store_op, &store_op, &store_op, &store_op, +/* POP EAX POP ECX POP EDX POP EBX*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, +/* POP ESP POP EBP POP ESI POP EDI*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, + +/* PUSHA POPA BOUND ARPL*/ +/*60*/ &vector_pusha_op, &vector_popa_op, &vector_bound_op, &vector_arpl_op, + INVALID, INVALID, INVALID, INVALID, +/* PUSH imm IMUL PUSH imm IMUL*/ + &push_imm_op, &vector_mul_op, &push_imm_op, &vector_mul_op, +/* INSB INSW OUTSB OUTSW*/ + &vector_ins_op, &vector_ins_op, &vector_outs_op, &vector_outs_op, + +/* Jxx*/ +/*70*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*80*/ INVALID, INVALID, INVALID, INVALID, +/* TEST TEST XCHG XCHG*/ + &vector_test_mem_b_op, &vector_test_mem_op, &vector_xchg_mem_op, &vector_xchg_mem_op, +/* MOV MOV MOV MOV*/ + &store_op, &store_op, &load_op, &load_op, +/* MOV from seg LEA MOV to seg POP*/ + &vector_mov_mem_seg_op, &store_op, &vector_mov_seg_mem_op, &pop_mem_op, + +/* NOP XCHG XCHG XCHG*/ +/*90*/ &limm_op, &xchg_op, &xchg_op, &xchg_op, +/* XCHG XCHG XCHG XCHG*/ + &xchg_op, &xchg_op, &xchg_op, &xchg_op, +/* CBW CWD CALL far WAIT*/ + &vector_alu1_op, &vector_alu1_op, &vector_call_far_op, &limm_op, +/* PUSHF POPF SAHF LAHF*/ + &vector_pushf_op, &vector_popf_op, &vector_alux1_op, &vector_alux1_op, + +/* MOV MOV MOV MOV*/ +/*a0*/ &load_op, &load_op, &store_op, &store_op, +/* MOVSB MOVSW CMPSB CMPSW*/ + &movs_op, &movs_op, &vector_cmpsb_op, &vector_cmps_op, +/* TEST TEST STOSB STOSW*/ + &test_reg_b_op, &test_reg_op, &stos_op, &stos_op, +/* LODSB LODSW SCASB SCASW*/ + &lods_op, &lods_op, &vector_scasb_op, &vector_scas_op, + +/* MOV*/ +/*b0*/ &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + +/* RET imm RET*/ +/*c0*/ INVALID, INVALID, &vector_ret_op, &vector_ret_op, +/* LES LDS MOV MOV*/ + &vector_lss_op, &vector_lss_op, &store_op, &store_op, +/* ENTER LEAVE RETF RETF*/ + &vector_enter_op, &leave_op, &vector_retf_op, &vector_retf_op, +/* INT3 INT INTO IRET*/ + &vector_int_op, &vector_int_op, &vector_int_op, &vector_iret_op, + + +/*d0*/ INVALID, INVALID, INVALID, INVALID, +/* AAM AAD SETALC XLAT*/ + &vector_alux6_op, &vector_alux3_op, &vector_alux1_op, &vector_xlat_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, +/* LOOPNE LOOPE LOOP JCXZ*/ +/*e0*/ &vector_loop_op, &vector_loop_op, &loop_op, &vector_loop_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, +/* CALL JMP JMP JMP*/ + &store_op, &branch_op, &vector_jmp_far_op, &branch_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, + +/* REPNE REPE*/ +/*f0*/ INVALID, INVALID, INVALID, INVALID, +/* HLT CMC*/ + &vector_alux1_op, &vector_alu2_op, INVALID, INVALID, +/* CLC STC CLI STI*/ + &vector_alu1_op, &vector_alu1_op, &vector_cli_sti_op, &vector_cli_sti_op, +/* CLD STD INCDEC*/ + &vector_alu1_op, &vector_alu1_op, &alux_store_op, INVALID +}; + +static const risc86_instruction_t *opcode_timings_mod3[256] = +{ +/* ADD ADD ADD ADD*/ +/*00*/ &alux_op, &alu_op, &alux_op, &alu_op, +/* ADD ADD PUSH ES POP ES*/ + &alux_op, &alu_op, &push_seg_op, &vector_mov_seg_mem_op, +/* OR OR OR OR*/ + &alux_op, &alu_op, &alux_op, &alu_op, +/* OR OR PUSH CS */ + &alux_op, &alu_op, &push_seg_op, INVALID, + +/* ADC ADC ADC ADC*/ +/*10*/ &vector_alux1_op, &vector_alu1_op, &vector_alux1_op, &vector_alu1_op, +/* ADC ADC PUSH SS POP SS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, +/* SBB SBB SBB SBB*/ + &vector_alux1_op, &vector_alu1_op, &vector_alux1_op, &vector_alu1_op, +/* SBB SBB PUSH DS POP DS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, + +/* AND AND AND AND*/ +/*20*/ &alux_op, &alu_op, &alux_op, &alu_op, +/* AND AND DAA*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, +/* SUB SUB SUB SUB*/ + &alux_op, &alu_op, &alux_op, &alu_op, +/* SUB SUB DAS*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, + +/* XOR XOR XOR XOR*/ +/*30*/ &alux_op, &alu_op, &alux_op, &alu_op, +/* XOR XOR AAA*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, +/* CMP CMP CMP CMP*/ + &alux_op, &alu_op, &alux_op, &alu_op, +/* CMP CMP AAS*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, + +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ &alu_op, &alu_op, &alu_op, &alu_op, +/* INC ESP INC EBP INC ESI INC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, + +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ &store_op, &store_op, &store_op, &store_op, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + &store_op, &store_op, &store_op, &store_op, +/* POP EAX POP ECX POP EDX POP EBX*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, +/* POP ESP POP EBP POP ESI POP EDI*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, + +/* PUSHA POPA BOUND ARPL*/ +/*60*/ &vector_pusha_op, &vector_popa_op, &vector_bound_op, &vector_arpl_op, + INVALID, INVALID, INVALID, INVALID, +/* PUSH imm IMUL PUSH imm IMUL*/ + &push_imm_op, &vector_mul_op, &push_imm_op, &vector_mul_op, +/* INSB INSW OUTSB OUTSW*/ + &vector_ins_op, &vector_ins_op, &vector_outs_op, &vector_outs_op, + +/* Jxx*/ +/*70*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*80*/ INVALID, INVALID, INVALID, INVALID, +/* TEST TEST XCHG XCHG*/ + &vector_alu1_op, &vector_alu1_op, &vector_alu3_op, &vector_alu3_op, +/* MOV MOV MOV MOV*/ + &store_op, &store_op, &load_op, &load_op, +/* MOV from seg LEA MOV to seg POP*/ + &mov_reg_seg_op, &store_op, &vector_mov_seg_reg_op, &pop_reg_op, + +/* NOP XCHG XCHG XCHG*/ +/*90*/ &limm_op, &xchg_op, &xchg_op, &xchg_op, +/* XCHG XCHG XCHG XCHG*/ + &xchg_op, &xchg_op, &xchg_op, &xchg_op, +/* CBW CWD CALL far WAIT*/ + &vector_alu1_op, &vector_alu1_op, &vector_call_far_op, &limm_op, +/* PUSHF POPF SAHF LAHF*/ + &vector_pushf_op, &vector_popf_op, &vector_alux1_op, &vector_alux1_op, + +/* MOV MOV MOV MOV*/ +/*a0*/ &load_op, &load_op, &store_op, &store_op, +/* MOVSB MOVSW CMPSB CMPSW*/ + &movs_op, &movs_op, &vector_cmpsb_op, &vector_cmps_op, +/* TEST TEST STOSB STOSW*/ + &test_reg_b_op, &test_reg_op, &stos_op, &stos_op, +/* LODSB LODSW SCASB SCASW*/ + &lods_op, &lods_op, &vector_scasb_op, &vector_scas_op, + +/* MOV*/ +/*b0*/ &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + +/* RET imm RET*/ +/*c0*/ INVALID, INVALID, &vector_ret_op, &vector_ret_op, +/* LES LDS MOV MOV*/ + &vector_lss_op, &vector_lss_op, &store_op, &store_op, +/* ENTER LEAVE RETF RETF*/ + &vector_enter_op, &leave_op, &vector_retf_op, &vector_retf_op, +/* INT3 INT INTO IRET*/ + &vector_int_op, &vector_int_op, &vector_int_op, &vector_iret_op, + + +/*d0*/ INVALID, INVALID, INVALID, INVALID, +/* AAM AAD SETALC XLAT*/ + &vector_alux6_op, &vector_alux3_op, &vector_alux1_op, &vector_xlat_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, +/* LOOPNE LOOPE LOOP JCXZ*/ +/*e0*/ &vector_loop_op, &vector_loop_op, &loop_op, &vector_loop_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, +/* CALL JMP JMP JMP*/ + &store_op, &branch_op, &vector_jmp_far_op, &branch_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, + +/* REPNE REPE*/ +/*f0*/ INVALID, INVALID, INVALID, INVALID, +/* HLT CMC*/ + &vector_alux1_op, &vector_alu2_op, INVALID, INVALID, +/* CLC STC CLI STI*/ + &vector_alu1_op, &vector_alu1_op, &vector_cli_sti_op, &vector_cli_sti_op, +/* CLD STD INCDEC*/ + &vector_alu1_op, &vector_alu1_op, &vector_alux1_op, INVALID +}; + +static const risc86_instruction_t *opcode_timings_0f[256] = +{ +/*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, + &vector_invd_op, &vector_wbinvd_op, INVALID, INVALID, + INVALID, &load_op, &vector_femms_op, &load_3dn_op, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*20*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + &vector_alu6_op, &vector_alu6_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, + &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, + &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, + INVALID, INVALID, &mload_op, &mload_op, + +/*70*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, + &load_mmx_op, &load_mmx_op, &load_mmx_op, &vector_emms_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, &mstore_op, &mstore_op, + +/*80*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*90*/ &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + +/*a0*/ &push_seg_op, &vector_mov_seg_mem_op, &vector_cpuid_op, &vector_load_alu_op, + &vector_alu_store_op, &vector_alu_store_op, INVALID, INVALID, + &push_seg_op, &vector_mov_seg_mem_op, INVALID, &vector_load_alu_op, + &vector_alu_store_op, &vector_alu_store_op, INVALID, &vector_mul_op, + +/*b0*/ &vector_cmpxchg_b_op, &vector_cmpxchg_op, &vector_lss_op, &vector_load_alu_op, + &vector_lss_op, &vector_lss_op, &load_alux_op, &load_alu_op, + INVALID, INVALID, &vector_load_alu_op, &vector_load_alu_op, + &vector_bsx_op, &vector_bsx_op, &load_alux_op, &load_alu_op, + +/*c0*/ &vector_alux_store_op, &vector_alu_store_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + +/*d0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, + INVALID, &load_mmx_mul_op, INVALID, INVALID, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + +/*e0*/ &load_mmx_op, &load_mmx_shift_op, &load_mmx_shift_op, INVALID, + INVALID, &pmul_mem_op, INVALID, INVALID, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + +/*f0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, + INVALID, &pmul_mem_op, INVALID, INVALID, + &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, + &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, +}; +static const risc86_instruction_t *opcode_timings_0f_mod3[256] = +{ +/*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, + &vector_invd_op, &vector_wbinvd_op, INVALID, INVALID, + INVALID, INVALID, &vector_femms_op, &m3dn_op, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*20*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + &vector_alu6_op, &vector_alu6_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ &mmx_op, &mmx_op, &mmx_op, &mmx_op, + &mmx_op, &mmx_op, &mmx_op, &mmx_op, + &mmx_op, &mmx_op, &mmx_op, &mmx_op, + INVALID, INVALID, &mmx_op, &mmx_op, + +/*70*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, + &mmx_op, &mmx_op, &mmx_op, &vector_emms_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, &mmx_op, &mmx_op, + +/*80*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*90*/ &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + +/*a0*/ &push_seg_op, &vector_mov_seg_mem_op, &vector_cpuid_op, &vector_alu1_op, + &vector_alu1_op, &vector_alu1_op, INVALID, INVALID, + &push_seg_op, &vector_mov_seg_mem_op, INVALID, &vector_alu1_op, + &vector_alu1_op, &vector_alu1_op, INVALID, &vector_mul_op, + +/*b0*/ &vector_cmpxchg_b_op, &vector_cmpxchg_op, &vector_lss_op, &vector_alu1_op, + &vector_lss_op, &vector_lss_op, &alux_op, &alu_op, + INVALID, INVALID, &vector_alu1_op, &vector_alu1_op, + &vector_bsx_op, &vector_bsx_op, &alux_op, &alu_op, + +/*c0*/ &vector_alux1_op, &vector_alu1_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + +/*d0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, + INVALID, &mmx_mul_op, INVALID, INVALID, + &mmx_op, &mmx_op, INVALID, &mmx_op, + &mmx_op, &mmx_op, INVALID, &mmx_op, + +/*e0*/ &mmx_op, &mmx_shift_op, &mmx_shift_op, INVALID, + INVALID, &pmul_op, INVALID, INVALID, + &mmx_op, &mmx_op, INVALID, &mmx_op, + &mmx_op, &mmx_op, INVALID, &mmx_op, + +/*f0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, + INVALID, &pmul_op, INVALID, INVALID, + &mmx_op, &mmx_op, &mmx_op, INVALID, + &mmx_op, &mmx_op, &mmx_op, INVALID, +}; + +static const risc86_instruction_t *opcode_timings_0f0f[256] = +{ +/*00*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &load_3dn_op, INVALID, INVALID, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &load_3dn_op, INVALID, INVALID, + +/*20*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*70*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*80*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*90*/ &load_3dn_op, INVALID, INVALID, INVALID, + &load_3dn_op, INVALID, &load_3dn_op, &load_3dn_op, + INVALID, INVALID, &load_3dn_op, INVALID, + INVALID, INVALID, &load_3dn_op, INVALID, + +/*a0*/ &load_3dn_op, INVALID, INVALID, INVALID, + &load_3dn_op, INVALID, &load_mmx_mul_op, &load_mmx_mul_op, + INVALID, INVALID, &load_3dn_op, INVALID, + INVALID, INVALID, &load_3dn_op, INVALID, + +/*b0*/ &load_3dn_op, INVALID, INVALID, INVALID, + &load_mmx_mul_op, INVALID, &load_mmx_mul_op, &load_mmx_mul_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, &load_mmx_op, + +/*c0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*d0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*e0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*f0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +}; +static const risc86_instruction_t *opcode_timings_0f0f_mod3[256] = +{ +/*00*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &m3dn_op, INVALID, INVALID, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &m3dn_op, INVALID, INVALID, + +/*20*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*70*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*80*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*90*/ &m3dn_op, INVALID, INVALID, INVALID, + &m3dn_op, INVALID, &m3dn_op, &m3dn_op, + INVALID, INVALID, &m3dn_op, INVALID, + INVALID, INVALID, &m3dn_op, INVALID, + +/*a0*/ &m3dn_op, INVALID, INVALID, INVALID, + &m3dn_op, INVALID, &mmx_mul_op, &mmx_mul_op, + INVALID, INVALID, &m3dn_op, INVALID, + INVALID, INVALID, &m3dn_op, INVALID, + +/*b0*/ &m3dn_op, INVALID, INVALID, INVALID, + &mmx_mul_op, INVALID, &mmx_mul_op, &mmx_mul_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, &mmx_op, + +/*c0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*d0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*e0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*f0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +}; + +static const risc86_instruction_t *opcode_timings_shift[8] = +{ + &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, + &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op +}; +static const risc86_instruction_t *opcode_timings_shift_b[8] = +{ + &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, + &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op +}; +static const risc86_instruction_t *opcode_timings_shift_mod3[8] = +{ + &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, + &alu_op, &alu_op, &alu_op, &alu_op +}; +static const risc86_instruction_t *opcode_timings_shift_b_mod3[8] = +{ + &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, + &alux_op, &alux_op, &alux_op, &alux_op +}; + +static const risc86_instruction_t *opcode_timings_80[8] = +{ + &alux_store_op, &alux_store_op, &vector_alux_store_op, &vector_alux_store_op, + &alux_store_op, &alux_store_op, &alux_store_op, &alux_store_op, +}; +static const risc86_instruction_t *opcode_timings_80_mod3[8] = +{ + &alux_op, &alux_op, &alux_store_op, &alux_store_op, + &alux_op, &alux_op, &alux_op, &alux_op, +}; +static const risc86_instruction_t *opcode_timings_8x[8] = +{ + &alu_store_op, &alu_store_op, &vector_alu_store_op, &vector_alu_store_op, + &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, +}; +static const risc86_instruction_t *opcode_timings_8x_mod3[8] = +{ + &alu_op, &alu_op, &alu_store_op, &alu_store_op, + &alu_op, &alu_op, &alu_op, &alu_op, +}; + +static const risc86_instruction_t *opcode_timings_f6[8] = +{ +/* TST NOT NEG*/ + &test_mem_imm_b_op, INVALID, &vector_alux_store_op, &vector_alux_store_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul_mem_op, &vector_mul_mem_op, &vector_div16_mem_op, &vector_div16_mem_op, +}; +static const risc86_instruction_t *opcode_timings_f6_mod3[8] = +{ +/* TST NOT NEG*/ + &test_reg_b_op, INVALID, &alux_op, &alux_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul_op, &vector_mul_op, &vector_div16_op, &vector_div16_op, +}; +static const risc86_instruction_t *opcode_timings_f7[8] = +{ +/* TST NOT NEG*/ + &test_mem_imm_op, INVALID, &vector_alu_store_op, &vector_alu_store_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul64_mem_op, &vector_mul64_mem_op, &vector_div32_mem_op, &vector_div32_mem_op, +}; +static const risc86_instruction_t *opcode_timings_f7_mod3[8] = +{ +/* TST NOT NEG*/ + &test_reg_op, INVALID, &alu_op, &alu_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul64_op, &vector_mul64_op, &vector_div32_op, &vector_div32_op, +}; +static const risc86_instruction_t *opcode_timings_ff[8] = +{ +/* INC DEC CALL CALL far*/ + &alu_store_op, &alu_store_op, &store_op, &vector_call_far_op, +/* JMP JMP far PUSH*/ + &branch_op, &vector_jmp_far_op, &push_mem_op, INVALID +}; +static const risc86_instruction_t *opcode_timings_ff_mod3[8] = +{ +/* INC DEC CALL CALL far*/ + &vector_alu1_op, &vector_alu1_op, &store_op, &vector_call_far_op, +/* JMP JMP far PUSH*/ + &branch_op, &vector_jmp_far_op, &vector_push_mem_op, INVALID +}; + +static const risc86_instruction_t *opcode_timings_d8[8] = +{ +/* FADDs FMULs FCOMs FCOMPs*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FSUBs FSUBRs FDIVs FDIVRs*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, +}; +static const risc86_instruction_t *opcode_timings_d8_mod3[8] = +{ +/* FADD FMUL FCOM FCOMP*/ + &float_op, &float_op, &float_op, &float_op, +/* FSUB FSUBR FDIV FDIVR*/ + &float_op, &float_op, &fdiv_op, &fdiv_op, +}; + +static const risc86_instruction_t *opcode_timings_d9[8] = +{ +/* FLDs FSTs FSTPs*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FLDENV FLDCW FSTENV FSTCW*/ + &vector_float_l_op, &vector_fldcw_op, &vector_float_l_op, &vector_float_op +}; +static const risc86_instruction_t *opcode_timings_d9_mod3[64] = +{ + /*FLD*/ + &float_op, &float_op, &float_op, &float_op, + &float_op, &float_op, &float_op, &float_op, + /*FXCH*/ + &float_op, &float_op, &float_op, &float_op, + &float_op, &float_op, &float_op, &float_op, + /*FNOP*/ + &float_op, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + /*FSTP*/ + &float_op, &float_op, &float_op, &float_op, + &float_op, &float_op, &float_op, &float_op, +/* opFCHS opFABS*/ + &float_op, &float_op, INVALID, INVALID, +/* opFTST opFXAM*/ + &float_op, &float_op, INVALID, INVALID, +/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/ + &float_op, &float_op, &float_op, &float_op, +/* opFLDEG2 opFLDLN2 opFLDZ*/ + &float_op, &float_op, &float_op, INVALID, +/* opF2XM1 opFYL2X opFPTAN opFPATAN*/ + &fsin_op, &fsin_op, &fsin_op, &fsin_op, +/* opFDECSTP opFINCSTP,*/ + INVALID, INVALID, &float_op, &float_op, +/* opFPREM opFSQRT opFSINCOS*/ + &fdiv_op, INVALID, &fsqrt_op, &fsin_op, +/* opFRNDINT opFSCALE opFSIN opFCOS*/ + &float_op, &fdiv_op, &fsin_op, &fsin_op +}; + +static const risc86_instruction_t *opcode_timings_da[8] = +{ +/* FIADDl FIMULl FICOMl FICOMPl*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FISUBl FISUBRl FIDIVl FIDIVRl*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, +}; +static const risc86_instruction_t *opcode_timings_da_mod3[8] = +{ + INVALID, INVALID, INVALID, INVALID, +/* FCOMPP*/ + INVALID, &float_op, INVALID, INVALID +}; + +static const risc86_instruction_t *opcode_timings_db[8] = +{ +/* FLDil FSTil FSTPil*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FLDe FSTPe*/ + INVALID, &vector_flde_op, INVALID, &vector_fste_op +}; +static const risc86_instruction_t *opcode_timings_db_mod3[64] = +{ + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/* opFNOP opFCLEX opFINIT*/ + INVALID, &float_op, &float_op, &float_op, +/* opFNOP opFNOP*/ + &float_op, &float_op, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, +}; + +static const risc86_instruction_t *opcode_timings_dc[8] = +{ +/* FADDd FMULd FCOMd FCOMPd*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FSUBd FSUBRd FDIVd FDIVRd*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, +}; +static const risc86_instruction_t *opcode_timings_dc_mod3[8] = +{ +/* opFADDr opFMULr*/ + &float_op, &float_op, INVALID, INVALID, +/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ + &float_op, &float_op, &fdiv_op, &fdiv_op +}; + +static const risc86_instruction_t *opcode_timings_dd[8] = +{ +/* FLDd FSTd FSTPd*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FRSTOR FSAVE FSTSW*/ + &vector_float_l_op, INVALID, &vector_float_l_op, &vector_float_l_op +}; +static const risc86_instruction_t *opcode_timings_dd_mod3[8] = +{ +/* FFFREE FST FSTP*/ + &float_op, INVALID, &float_op, &float_op, +/* FUCOM FUCOMP*/ + &float_op, &float_op, INVALID, INVALID +}; + +static const risc86_instruction_t *opcode_timings_de[8] = +{ +/* FIADDw FIMULw FICOMw FICOMPw*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FISUBw FISUBRw FIDIVw FIDIVRw*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, +}; +static const risc86_instruction_t *opcode_timings_de_mod3[8] = +{ +/* FADDP FMULP FCOMPP*/ + &float_op, &float_op, INVALID, &float_op, +/* FSUBP FSUBRP FDIVP FDIVRP*/ + &float_op, &float_op, &fdiv_op, &fdiv_op, +}; + +static const risc86_instruction_t *opcode_timings_df[8] = +{ +/* FILDiw FISTiw FISTPiw*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FILDiq FBSTP FISTPiq*/ + INVALID, &load_float_op, &vector_float_l_op, &fstore_op, +}; +static const risc86_instruction_t *opcode_timings_df_mod3[8] = +{ + INVALID, INVALID, INVALID, INVALID, +/* FSTSW AX*/ + &float_op, INVALID, INVALID, INVALID +}; + + +static uint8_t last_prefix; + +static int decode_timestamp; +static int last_complete_timestamp; + +typedef struct k6_unit_t +{ + uint32_t uop_mask; + int first_available_cycle; +} k6_unit_t; + +static int nr_units; +static k6_unit_t *units; + +/*K6 has dedicated MMX unit*/ +static k6_unit_t k6_units[] = +{ + {.uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX)}, /*Integer X*/ + {.uop_mask = (1 << UOP_ALU)}, /*Integer Y*/ + {.uop_mask = (1 << UOP_MEU) | (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL)}, /*Multimedia*/ + {.uop_mask = (1 << UOP_FLOAT)}, /*Floating point*/ + {.uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD)}, /*Load*/ + {.uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE)}, /*Store*/ + {.uop_mask = (1 << UOP_BRANCH)} /*Branch*/ +}; +#define NR_K6_UNITS (sizeof(k6_units) / sizeof(k6_unit_t)) + +/*K6-2 and later integrate MMX into ALU X & Y, sharing multiplier, shifter and + 3DNow ALU between two execution units*/ +static k6_unit_t k6_2_units[] = +{ + {.uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX) | (1 << UOP_MEU) | /*Integer X*/ + (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN)}, + {.uop_mask = (1 << UOP_ALU) | (1 << UOP_MEU) | /*Integer Y*/ + (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN)}, + {.uop_mask = (1 << UOP_FLOAT)}, /*Floating point*/ + {.uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD)}, /*Load*/ + {.uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE)}, /*Store*/ + {.uop_mask = (1 << UOP_BRANCH)} /*Branch*/ +}; +#define NR_K6_2_UNITS (sizeof(k6_2_units) / sizeof(k6_unit_t)) + +/*First available cycles of shared execution units. Each of these can be submitted + to by ALU X and Y*/ +static int mul_first_available_cycle; +static int shift_first_available_cycle; +static int m3dnow_first_available_cycle; + +static int uop_run(const risc86_uop_t *uop, int decode_time) +{ + int c; + k6_unit_t *best_unit = NULL; + int best_start_cycle = 99999; + + /*UOP_LIMM does not require execution*/ + if (uop->type == UOP_LIMM) + return decode_time; + + /*Handle shared units on K6-2 and later*/ + if (units == k6_2_units) + { + if (uop->type == UOP_MEU_MUL && decode_time < mul_first_available_cycle) + decode_time = mul_first_available_cycle; + else if (uop->type == UOP_MEU_SHIFT && decode_time < mul_first_available_cycle) + decode_time = shift_first_available_cycle; + else if (uop->type == UOP_MEU_3DN && decode_time < mul_first_available_cycle) + decode_time = m3dnow_first_available_cycle; + } + + /*Find execution unit for this uOP*/ + for (c = 0; c < nr_units; c++) + { + if (units[c].uop_mask & (1 << uop->type)) + { + if (units[c].first_available_cycle < best_start_cycle) + { + best_unit = &units[c]; + best_start_cycle = units[c].first_available_cycle; + } + } + } + if (!best_unit) + fatal("uop_run: can not find execution unit\n"); + + if (best_start_cycle < decode_time) + best_start_cycle = decode_time; + best_unit->first_available_cycle = best_start_cycle + uop->throughput; + + if (units == k6_2_units) + { + if (uop->type == UOP_MEU_MUL) + mul_first_available_cycle = best_start_cycle + uop->throughput; + else if (uop->type == UOP_MEU_SHIFT) + shift_first_available_cycle = best_start_cycle + uop->throughput; + else if (uop->type == UOP_MEU_3DN) + m3dnow_first_available_cycle = best_start_cycle + uop->throughput; + } + + return best_start_cycle + uop->throughput; +} + +/*The K6 decoder can decode, per clock : + - 1 or 2 'short' instructions, each up to 2 uOPs and 7 bytes long + - 1 'long' instruction, up to 4 uOPs + - 1 'vector' instruction, up to 4 uOPs per cycle, plus (I think) 1 cycle startup delay) +*/ +static struct +{ + int nr_uops; + const risc86_uop_t *uops[4]; + /*Earliest time a uop can start. If the timestamp is -1, then the uop is + part of a dependency chain and the start time is the completion time of + the previous uop*/ + int earliest_start[4]; +} decode_buffer; + +#define NR_OPQUADS 6 +/*Timestamps of when the last six opquads completed. The K6 scheduler retires + opquads in order, so this is needed to determine when the next can be scheduled*/ +static int opquad_completion_timestamp[NR_OPQUADS]; +static int next_opquad = 0; + +#define NR_REGS 8 +/*Timestamp of when last operation on an integer register completed*/ +static int reg_available_timestamp[NR_REGS]; +/*Timestamp of when last operation on an FPU register completed*/ +static int fpu_st_timestamp[8]; +/*Completion time of the last uop to be processed. Used to calculate timing of + dependent uop chains*/ +static int last_uop_timestamp = 0; + +void decode_flush() +{ + int c; + int uop_timestamp = 0; + + /*Decoded opquad can not be submitted if there are no free spaces in the + opquad buffer*/ + if (decode_timestamp < opquad_completion_timestamp[next_opquad]) + decode_timestamp = opquad_completion_timestamp[next_opquad]; + + /*Ensure that uops can not be submitted before they have been decoded*/ + if (decode_timestamp > last_uop_timestamp) + last_uop_timestamp = decode_timestamp; + + /*Submit uops to execution units, and determine the latest completion time*/ + for (c = 0; c < decode_buffer.nr_uops; c++) + { + int start_timestamp; + + if (decode_buffer.earliest_start[c] == -1) + start_timestamp = last_uop_timestamp; + else + start_timestamp = decode_buffer.earliest_start[c]; + + last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); + if (last_uop_timestamp > uop_timestamp) + uop_timestamp = last_uop_timestamp; + } + + /*Calculate opquad completion time. Since opquads complete in order, it + must be after the last completion.*/ + if (uop_timestamp <= last_complete_timestamp) + last_complete_timestamp = last_complete_timestamp + 1; + else + last_complete_timestamp = uop_timestamp; + + /*Advance to next opquad in buffer*/ + opquad_completion_timestamp[next_opquad] = last_complete_timestamp; + next_opquad++; + if (next_opquad == NR_OPQUADS) + next_opquad = 0; + + decode_timestamp++; + decode_buffer.nr_uops = 0; +} + +static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) +{ + uint32_t regmask_required; + uint32_t regmask_modified; + int c, d; + int earliest_start = 0; + + /*Generate input register mask, and determine the earliest time this + instruction can start. This is not accurate, as this is calculated per + x86 instruction when it should be handled per uop*/ + regmask_required = get_dstdep_mask(deps, fetchdat, bit8); + regmask_required |= get_addr_regmask(deps, fetchdat, op_32); + for (c = 0; c < 8; c++) + { + if (regmask_required & (1 << c)) + { + if (reg_available_timestamp[c] > decode_timestamp) + earliest_start = reg_available_timestamp[c]; + } + } + if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) + earliest_start = fpu_st_timestamp[0]; + if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) + earliest_start = fpu_st_timestamp[1]; + if ((deps & FPU_RW_STREG)) + { + int reg = fetchdat & 7; + + if (fpu_st_timestamp[reg] > decode_timestamp) + earliest_start = fpu_st_timestamp[reg]; + } + + switch (ins->decode_type) + { + case DECODE_SHORT: + if (decode_buffer.nr_uops) + { + decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; + decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; + if (ins->nr_uops > 1) + { + decode_buffer.uops[decode_buffer.nr_uops+1] = &ins->uop[1]; + decode_buffer.earliest_start[decode_buffer.nr_uops+1] = -1; + } + decode_buffer.nr_uops += ins->nr_uops; + + decode_flush(); + } + else + { + decode_buffer.nr_uops = ins->nr_uops; + decode_buffer.uops[0] = &ins->uop[0]; + decode_buffer.earliest_start[0] = earliest_start; + if (ins->nr_uops > 1) + { + decode_buffer.uops[1] = &ins->uop[1]; + decode_buffer.earliest_start[1] = -1; + } + } + break; + + case DECODE_LONG: + if (decode_buffer.nr_uops) + decode_flush(); + + decode_buffer.nr_uops = ins->nr_uops; + for (c = 0; c < ins->nr_uops; c++) + { + decode_buffer.uops[c] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[c] = earliest_start; + else + decode_buffer.earliest_start[c] = -1; + } + decode_flush(); + break; + + case DECODE_VECTOR: + if (decode_buffer.nr_uops) + decode_flush(); + + decode_timestamp++; + d = 0; + + for (c = 0; c < ins->nr_uops; c++) + { + decode_buffer.uops[d] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[d] = earliest_start; + else + decode_buffer.earliest_start[d] = -1; + d++; + + if (d == 4) + { + d = 0; + decode_buffer.nr_uops = 4; + decode_flush(); + } + } + if (d) + { + decode_buffer.nr_uops = d; + decode_flush(); + } + break; + } + + /*Update write timestamps for any output registers*/ + regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); + for (c = 0; c < 8; c++) + { + if (regmask_modified & (1 << c)) + reg_available_timestamp[c] = last_complete_timestamp; + } + if (deps & FPU_POP) + { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c+1]; + fpu_st_timestamp[7] = 0; + } + if (deps & FPU_POP2) + { + for (c = 0; c < 6; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c+2]; + fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; + } + if (deps & FPU_PUSH) + { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c+1] = fpu_st_timestamp[c]; + fpu_st_timestamp[0] = 0; + } + if (deps & FPU_WRITE_ST0) + fpu_st_timestamp[0] = last_complete_timestamp; + if (deps & FPU_WRITE_ST1) + fpu_st_timestamp[1] = last_complete_timestamp; + if (deps & FPU_WRITE_STREG) + { + int reg = fetchdat & 7; + if (deps & FPU_POP) + reg--; + if (reg >= 0 && + !(reg == 0 && (deps & FPU_WRITE_ST0)) && + !(reg == 1 && (deps & FPU_WRITE_ST1))) + fpu_st_timestamp[reg] = last_complete_timestamp; + } +} + +void codegen_timing_k6_block_start() +{ + int c; + + for (c = 0; c < nr_units; c++) + units[c].first_available_cycle = 0; + + mul_first_available_cycle = 0; + shift_first_available_cycle = 0; + m3dnow_first_available_cycle = 0; + + decode_timestamp = 0; + last_complete_timestamp = 0; + + for (c = 0; c < NR_OPQUADS; c++) + opquad_completion_timestamp[c] = 0; + next_opquad = 0; + + for (c = 0; c < NR_REGS; c++) + reg_available_timestamp[c] = 0; + for (c = 0; c < 8; c++) + fpu_st_timestamp[c] = 0; +} + +void codegen_timing_k6_start() +{ + if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_K6) + { + units = k6_units; + nr_units = NR_K6_UNITS; + } + else + { + units = k6_2_units; + nr_units = NR_K6_2_UNITS; + } + last_prefix = 0; +} + +void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) +{ + if (prefix != 0x0f) + decode_timestamp++; + + last_prefix = prefix; +} + +void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +{ + const risc86_instruction_t **ins_table; + uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int old_last_complete_timestamp = last_complete_timestamp; + int bit8 = !(opcode & 1); + + switch (last_prefix) + { + case 0x0f: + if (opcode == 0x0f) + { + /*3DNow has the actual opcode after ModR/M, SIB and any offset*/ + uint32_t opcode_pc = op_pc + 1; /*Byte after ModR/M*/ + uint8_t modrm = fetchdat & 0xff; + uint8_t sib = (fetchdat >> 8) & 0xff; + + if ((modrm & 0xc0) != 0xc0) + { + if (op_32 & 0x200) + { + if ((modrm & 7) == 4) + { + /* Has SIB*/ + opcode_pc++; + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((sib & 0x07) == 0x05) + opcode_pc += 4; + } + else + { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((modrm & 0xc7) == 0x05) + opcode_pc += 4; + } + } + else + { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 2; + else if ((modrm & 0xc7) == 0x06) + opcode_pc += 2; + } + } + + opcode = fastreadb(cs + opcode_pc); + + ins_table = mod3 ? opcode_timings_0f0f_mod3 : opcode_timings_0f0f; + deps = mod3 ? opcode_deps_0f0f_mod3 : opcode_deps_0f0f; + } + else + { + ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + } +// pclog("timings 0f\n"); + break; + + case 0xd8: + ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; +// pclog("timings d8\n"); + break; + case 0xd9: + ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; +// pclog("timings d9\n"); + break; + case 0xda: + ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; +// pclog("timings da\n"); + break; + case 0xdb: + ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; +// pclog("timings db\n"); + break; + case 0xdc: + ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; +// pclog("timings dc\n"); + break; + case 0xdd: + ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; +// pclog("timings dd\n"); + break; + case 0xde: + ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; +// pclog("timings de\n"); + break; + case 0xdf: + ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; +// pclog("timings df\n"); + break; + + default: + switch (opcode) + { + case 0x80: case 0x82: + ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; +// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x); + break; + case 0x81: case 0x83: + ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; +// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x); + break; + + case 0xc0: case 0xd0: case 0xd2: + ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; +// pclog("timings c0\n"); + break; + + case 0xc1: case 0xd1: case 0xd3: + ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; +// pclog("timings c1\n"); + break; + + case 0xf6: + ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; +// pclog("timings f6\n"); + break; + case 0xf7: + ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; +// pclog("timings f7\n"); + break; + case 0xff: + ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; +// pclog("timings ff\n"); + break; + + default: + ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; +// pclog("timings normal\n"); + break; + } + } + + decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); + codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); +} + +void codegen_timing_k6_block_end() +{ + if (decode_buffer.nr_uops) + decode_flush(); +} + +codegen_timing_t codegen_timing_k6 = +{ + codegen_timing_k6_start, + codegen_timing_k6_prefix, + codegen_timing_k6_opcode, + codegen_timing_k6_block_start, + codegen_timing_k6_block_end +}; diff --git a/src/codegen_timing_pentium.c b/src/codegen_timing_pentium.c index 4194e3a..24748cb 100644 --- a/src/codegen_timing_pentium.c +++ b/src/codegen_timing_pentium.c @@ -1075,7 +1075,7 @@ static void codegen_instruction(uint64_t *timings, uint64_t *deps, uint8_t opcod } } -void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) +void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) { uint64_t *timings; uint64_t *deps; diff --git a/src/codegen_timing_winchip.c b/src/codegen_timing_winchip.c index bdf499e..56ee3af 100644 --- a/src/codegen_timing_winchip.c +++ b/src/codegen_timing_winchip.c @@ -296,7 +296,7 @@ void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; } -void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) +void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) { int **timings; uint64_t *deps; diff --git a/src/codegen_timing_winchip2.c b/src/codegen_timing_winchip2.c index 0644298..ec47099 100644 --- a/src/codegen_timing_winchip2.c +++ b/src/codegen_timing_winchip2.c @@ -563,7 +563,7 @@ static void codegen_timing_winchip2_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; } -static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) +static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) { uint32_t *timings; uint64_t *deps; diff --git a/src/cpu.c b/src/cpu.c index 1b2e0ef..accff09 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1374,7 +1374,7 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; - codegen_timing_set(&codegen_timing_pentium); + codegen_timing_set(&codegen_timing_k6); break; case CPU_K6_2: @@ -1418,7 +1418,7 @@ void cpu_set() cpu_hasCR4 = 1; cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; - codegen_timing_set(&codegen_timing_pentium); + codegen_timing_set(&codegen_timing_k6); break; default: From e26abe7a1f0c970ecdb51f35a6789eed1ec80b0e Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 14 Dec 2018 21:59:03 +0000 Subject: [PATCH 085/181] Added recompiled versions of 3DNow instructions - PF2ID, PFADD, PFCMPEQ, PFCMPGE, PFCMPGT, PFMAX, PFMIN, PFMUL, PFRCP, PFRCPIT1, PFRCPIT2, PFRSQRT, PFRSQIT1, PFSUB, PFSUBR and PI2FD. --- src/codegen.c | 74 ++++++++++- src/codegen_backend_arm64_ops.c | 69 +++++++++++ src/codegen_backend_arm64_ops.h | 12 ++ src/codegen_backend_arm64_uops.c | 189 ++++++++++++++++++++++++++++ src/codegen_backend_arm_ops.c | 63 ++++++++++ src/codegen_backend_arm_ops.h | 14 +++ src/codegen_backend_arm_uops.c | 189 ++++++++++++++++++++++++++++ src/codegen_backend_x86-64.c | 4 +- src/codegen_backend_x86-64_ops.c | 52 ++++++++ src/codegen_backend_x86-64_ops.h | 19 +++ src/codegen_backend_x86-64_uops.c | 198 ++++++++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 49 +++++++- src/codegen_backend_x86_ops.h | 17 +++ src/codegen_backend_x86_uops.c | 198 ++++++++++++++++++++++++++++++ src/codegen_ir_defs.h | 40 +++++- src/codegen_ops.c | 25 ++++ src/codegen_ops.h | 1 + src/codegen_ops_3dnow.c | 193 +++++++++++++++++++++++++++++ src/codegen_ops_3dnow.h | 15 +++ 19 files changed, 1412 insertions(+), 9 deletions(-) create mode 100644 src/codegen_ops_3dnow.c create mode 100644 src/codegen_ops_3dnow.h diff --git a/src/codegen.c b/src/codegen.c index f42f22c..a278cfe 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -306,10 +306,12 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t RecompOpFn *recomp_op_table = recomp_opcodes; int opcode_shift = 0; int opcode_mask = 0x3ff; + uint32_t recomp_opcode_mask = 0x1ff; uint32_t op_32 = use32; int over = 0; int test_modrm = 1; int pc_off = 0; + uint32_t next_pc = 0; #ifdef DEBUG_EXTRA uint8_t last_prefix = 0; #endif @@ -507,10 +509,68 @@ generate_call: (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) codegen_accumulate_flush(ir); -// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); - if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) + + if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f) { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](block, ir, opcode, fetchdat, op_32, op_pc); + /*3DNow opcodes are stored after ModR/M, SIB and any offset*/ + uint8_t modrm = fetchdat & 0xff; + uint8_t sib = (fetchdat >> 8) & 0xff; + uint32_t opcode_pc = op_pc + 1; + uint8_t opcode_3dnow; + + if ((modrm & 0xc0) != 0xc0) + { + if (op_32 & 0x200) + { + if ((modrm & 7) == 4) + { + /* Has SIB*/ + opcode_pc++; + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((sib & 0x07) == 0x05) + opcode_pc += 4; + } + else + { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((modrm & 0xc7) == 0x05) + opcode_pc += 4; + } + } + else + { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 2; + else if ((modrm & 0xc7) == 0x06) + opcode_pc += 2; + } + } + + opcode_3dnow = fastreadb(cs + opcode_pc); +// pclog("recomp_opcodes_3DNOW[%02x]=%p\n", opcode, recomp_opcodes_3DNOW[opcode]); + if (recomp_opcodes_3DNOW[opcode_3dnow]) + { + next_pc = opcode_pc + 1; + + op_table = x86_dynarec_opcodes_3DNOW; + recomp_op_table = recomp_opcodes_3DNOW; + opcode = opcode_3dnow; + recomp_opcode_mask = 0xff; + opcode_mask = 0xff; + } + } +// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); + if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) + { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc); if (new_pc) { if (new_pc != -1) @@ -532,7 +592,8 @@ generate_call: if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) + (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || + (op_table == x86_dynarec_opcodes_3DNOW)) { int stack_offset = 0; @@ -564,7 +625,10 @@ generate_call: uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); #endif - uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off); + if (op_table == x86_dynarec_opcodes_3DNOW) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off); uop_MOV_IMM(ir, IREG_oldpc, old_pc); if (op_32 != last_op_32) uop_MOV_IMM(ir, IREG_op32, op_32); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index ee2c0b6..7d71d31 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -119,9 +119,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_CMGT_V8B (0x0e203400) #define OPCODE_CMGT_V4H (0x0e603400) #define OPCODE_CMGT_V2S (0x0ea03400) +#define OPCODE_DUP_V2S (0x0e040400) #define OPCODE_EOR_V (0x2e201c00) #define OPCODE_FABS_D (0x1e60c000) #define OPCODE_FADD_D (0x1e602800) +#define OPCODE_FADD_V2S (0x0e20d400) +#define OPCODE_FCMEQ_V2S (0x0e20e400) +#define OPCODE_FCMGE_V2S (0x2e20e400) +#define OPCODE_FCMGT_V2S (0x2ea0e400) #define OPCODE_FCMP_D (0x1e602000) #define OPCODE_FCVT_D_S (0x1e22c000) #define OPCODE_FCVT_S_D (0x1e624000) @@ -133,17 +138,25 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_FCVTPS_X_D (0x9e680000) #define OPCODE_FCVTZS_W_D (0x1e780000) #define OPCODE_FCVTZS_X_D (0x9e780000) +#define OPCODE_FCVTZS_V2S (0x0ea1b800) #define OPCODE_FDIV_D (0x1e601800) +#define OPCODE_FDIV_S (0x1e201800) +#define OPCODE_FMAX_V2S (0x0e20f400) +#define OPCODE_FMIN_V2S (0x0ea0f400) #define OPCODE_FMOV_D_D (0x1e604000) #define OPCODE_FMOV_D_Q (0x9e670000) #define OPCODE_FMOV_Q_D (0x9e660000) #define OPCODE_FMOV_S_W (0x1e270000) #define OPCODE_FMOV_W_S (0x1e260000) +#define OPCODE_FMOV_S_ONE (0x1e2e1000) #define OPCODE_FMUL_D (0x1e600800) +#define OPCODE_FMUL_V2S (0x2e20dc00) #define OPCODE_FNEG_D (0x1e614000) #define OPCODE_FRINTX_D (0x1e674000) #define OPCODE_FSQRT_D (0x1e61c000) +#define OPCODE_FSQRT_S (0x1e21c000) #define OPCODE_FSUB_D (0x1e603800) +#define OPCODE_FSUB_V2S (0x0ea0d400) #define OPCODE_LDR_REG (0xb8606800) #define OPCODE_LDRX_REG (0xf8606800) #define OPCODE_LDRB_REG (0x38606800) @@ -227,6 +240,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16) +#define DUP_ELEMENT(element) ((element) << 19) + static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) { @@ -662,6 +677,11 @@ void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_ codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element) +{ + codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element)); +} + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ @@ -692,6 +712,22 @@ void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m { codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FCMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FCMGE_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FCMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg) { @@ -739,21 +775,46 @@ void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FCVTZS_V2S | Rd(dst_reg) | Rn(src_reg)); +} void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FDIV_S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FMAX_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FMIN_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FMUL_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } +void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_FSUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg) { @@ -775,6 +836,10 @@ void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg) +{ + codegen_addlong(block, OPCODE_FMOV_S_ONE | Rd(dst_reg)); +} void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg) { @@ -790,6 +855,10 @@ void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_FSQRT_S | Rd(dst_reg) | Rn(src_reg)); +} void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 048c354..a8c3fc2 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -71,6 +71,8 @@ void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_ void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element); + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); @@ -78,10 +80,17 @@ void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg); void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg); @@ -94,16 +103,19 @@ void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg); void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index c7729af..703a7e5 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1682,6 +1682,182 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a); + } + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use VRECPE/VRECPS)*/ + host_arm_FMOV_S_ONE(block, REG_D_TEMP); + host_arm_FDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); + host_arm_DUP_V2S(block, dest_reg, dest_reg, 0); + } + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ + host_arm_FSQRT_S(block, REG_D_TEMP, src_reg_a); + host_arm_FMOV_S_ONE(block, REG_D_TEMP); + host_arm_FDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); + host_arm_DUP_V2S(block, dest_reg, dest_reg, 0); + } + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a); + } + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2629,6 +2805,19 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, + [UOP_PFADD & UOP_MASK] = codegen_PFADD, + [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, + [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, + [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, + [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, + [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, + [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, + [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, + [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, + [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, + [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 12e9c68..85ffd9d 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -91,11 +91,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VADD_I8 0xf2000800 #define OPCODE_VADD_I16 0xf2100800 #define OPCODE_VADD_I32 0xf2200800 +#define OPCODE_VADD_F32 0xf2000d00 #define OPCODE_VAND_D 0xf2000110 #define OPCODE_VBIC_D 0xf2100110 +#define OPCODE_VCEQ_F32 0xf2000e00 #define OPCODE_VCEQ_I8 0xf3000810 #define OPCODE_VCEQ_I16 0xf3100810 #define OPCODE_VCEQ_I32 0xf3200810 +#define OPCODE_VCGE_F32 0xf3000e00 +#define OPCODE_VCGT_F32 0xf3200e00 #define OPCODE_VCGT_S8 0xf2000300 #define OPCODE_VCGT_S16 0xf2100300 #define OPCODE_VCGT_S32 0xf2200300 @@ -103,12 +107,17 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VCVT_D_IS 0xeeb80bc0 #define OPCODE_VCVT_D_S 0xeeb70ac0 #define OPCODE_VCVT_IS_D 0xeebd0bc0 +#define OPCODE_VCVT_S32_F32 0xf3bb0680 #define OPCODE_VCVT_S_D 0xeeb70bc0 #define OPCODE_VCVTR_IS_D 0xeebd0b40 #define OPCODE_VDIV 0xee800b00 +#define OPCODE_VDIV_S 0xee800a00 +#define OPCODE_VDUP_32 0xf3b40c00 #define OPCODE_VEOR_D 0xf3000110 #define OPCODE_VLDR_D 0xed900b00 #define OPCODE_VLDR_S 0xed900a00 +#define OPCODE_VMAX_F32 0xf200f00 +#define OPCODE_VMIN_F32 0xf220f00 #define OPCODE_VMOV_32_S 0xee100a10 #define OPCODE_VMOV_64_D 0xec500b10 #define OPCODE_VMOV_D_64 0xec400b10 @@ -116,9 +125,11 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMOV_D_D 0xeeb00b40 #define OPCODE_VMOVN_I32 0xf3b60200 #define OPCODE_VMOVN_I64 0xf3ba0200 +#define OPCODE_VMOV_F32_ONE 0xf2870f10 #define OPCODE_VMRS_APSR 0xeef1fa10 #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 +#define OPCODE_VMUL_F32 0xf3000d10 #define OPCODE_VMUL_S16 0xf2100910 #define OPCODE_VMULL_S16 0xf2900c00 #define OPCODE_VNEG_D 0xeeb10b40 @@ -148,6 +159,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VSHR_D_U64 0xf3800090 #define OPCODE_VSHRN 0xf2800810 #define OPCODE_VSQRT_D 0xeeb10bc0 +#define OPCODE_VSQRT_S 0xeeb10ac0 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 @@ -193,6 +205,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) +#define VDUP_32_IMM(imm) ((imm) << 19) + static inline uint32_t arm_data_offset(int offset) { if (offset < -0xffc || offset > 0xffc) @@ -808,6 +822,10 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VADD_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -833,6 +851,10 @@ void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); } +void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCEQ_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -845,6 +867,14 @@ void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r { codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGE_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGT_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -870,6 +900,10 @@ void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVT_S32_F32 | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); @@ -882,6 +916,14 @@ void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VDIV_S | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm) +{ + codegen_addlong(block, COND_AL | OPCODE_VDUP_32 | Rd(dst_reg) | Rm(src_reg_m) | VDUP_32_IMM(imm)); +} void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -926,6 +968,10 @@ void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(src_reg)); +} void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); @@ -935,10 +981,23 @@ void host_arm_VMRS_APSR(codeblock_t *block) codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); } +void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VMAX_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VMIN_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} + void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VMUL_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -1082,6 +1141,10 @@ void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VSQRT_S | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index b7877df..3c2ae77 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -145,13 +145,17 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m); +void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); @@ -161,9 +165,11 @@ void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -179,7 +185,13 @@ void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); +void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); + +void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg); + void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m); void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m); @@ -216,10 +228,12 @@ void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shif void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift); void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VSUB_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 8ceebbc..1a5d4e2 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1806,6 +1806,182 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_arm_VCVT_S32_F32(block, dest_reg, src_reg_a); + } + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VADD_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCEQ_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCGE_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VCGT_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMAX_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMIN_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VMUL_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use VRECPE/VRECPS)*/ + host_arm_VMOV_F32_ONE(block, REG_D_TEMP); + host_arm_VDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); + host_arm_VDUP_32(block, dest_reg, dest_reg, 0); + } + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ + host_arm_VSQRT_S(block, REG_D_TEMP, src_reg_a); + host_arm_VMOV_F32_ONE(block, REG_D_TEMP); + host_arm_VDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); + host_arm_VDUP_32(block, dest_reg, dest_reg, 0); + } + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_arm_VSUB_F32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_arm_VCVT_Q_F32_IS(block, dest_reg, src_reg_a); + } + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2775,6 +2951,19 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, + [UOP_PFADD & UOP_MASK] = codegen_PFADD, + [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, + [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, + [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, + [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, + [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, + [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, + [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, + [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, + [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, + [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 631402a..4cdf2b4 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -206,7 +206,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_PUSH(block, REG_RAX); host_x86_PUSH(block, REG_RDX); #if WIN64 - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28); if (size == 4 && is_float) host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data else if (size == 8) @@ -227,7 +227,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) else if (size == 8) host_x86_CALL(block, (void *)writememql); #if WIN64 - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28); #endif host_x86_POP(block, REG_RDX); host_x86_POP(block, REG_RAX); diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 04d0080..f077960 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -212,6 +212,10 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ +} void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); @@ -341,11 +345,25 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +{ + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ +} + void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ +} +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ +} + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ @@ -364,6 +382,10 @@ void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ @@ -384,6 +406,10 @@ void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); } +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} void host_x86_JMP(codeblock_t *block, void *p) { @@ -1216,6 +1242,19 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); } +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ +} +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ +} + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ +} void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); @@ -1635,6 +1674,10 @@ void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ } +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { @@ -1714,6 +1757,10 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); @@ -1751,6 +1798,11 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); +} + void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index a86e3ed..ea2eede 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -7,6 +7,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); @@ -27,17 +28,27 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +#define CMPPS_EQ 0 +#define CMPPS_NLT 5 +#define CMPPS_NLE 6 +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type); + void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_JMP(codeblock_t *block, void *p); @@ -146,7 +157,11 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); @@ -240,6 +255,7 @@ void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); @@ -250,6 +266,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); @@ -257,6 +274,8 @@ void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg); void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 4955609..ad11134 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1569,6 +1569,191 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + } + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); + } + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); + } + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); + } + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use RCPSS + iteration)*/ + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use RSQRTSS + iteration)*/ + host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); + } + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2384,6 +2569,19 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, + [UOP_PFADD & UOP_MASK] = codegen_PFADD, + [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, + [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, + [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, + [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, + [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, + [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, + [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, + [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, + [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, + [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index a861d14..97ba65f 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -185,6 +185,10 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ +} void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); @@ -309,11 +313,25 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +{ + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ +} + void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ +} +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ +} + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ @@ -327,6 +345,10 @@ void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { @@ -340,7 +362,11 @@ void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ +} +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ } void host_x86_INC32_ABS(codeblock_t *block, void *p) @@ -1024,6 +1050,19 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ } +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ +} +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ +} + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ +} void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); @@ -1406,6 +1445,10 @@ void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ } +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { @@ -1476,6 +1519,10 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index d07b0d9..22a8746 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -8,6 +8,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); @@ -27,17 +28,27 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); +#define CMPPS_EQ 0 +#define CMPPS_NLT 5 +#define CMPPS_NLE 6 +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type); + void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg); +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg); void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_INC32_ABS(codeblock_t *block, void *p); @@ -148,6 +159,10 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); @@ -242,6 +257,7 @@ void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); @@ -251,6 +267,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 67f28d4..e53b91d 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1572,6 +1572,191 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + } + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); + } + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); + } + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); + } + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use RCPSS + iteration)*/ + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + /*TODO: This could be improved (use RSQRTSS + iteration)*/ + host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); + } + else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) + { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) + { + host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); + } + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2394,6 +2579,19 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, + [UOP_PFADD & UOP_MASK] = codegen_PFADD, + [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, + [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, + [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, + [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, + [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, + [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, + [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, + [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, + [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, + [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 2a2733e..aa95c06 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -281,7 +281,32 @@ /*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ #define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9) -#define UOP_MAX 0xba +/*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/ +#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba) +/*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/ +#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb) +/*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/ +#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc) +/*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/ +#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd) +/*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/ +#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe) +/*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf) +/*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/ +#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0) +/*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1) +/*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/ +#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2) +/*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/ +#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3) +/*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/ +#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4) +/*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/ +#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5) + +#define UOP_MAX 0xc6 #define UOP_MASK 0xffff @@ -645,6 +670,19 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg) +#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg) +#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg) +#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg) + #define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 10b19d2..a339224 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -2,6 +2,7 @@ #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" +#include "codegen_ops_3dnow.h" #include "codegen_ops_arith.h" #include "codegen_ops_branch.h" #include "codegen_ops_fpu_arith.h" @@ -116,6 +117,30 @@ RecompOpFn recomp_opcodes_0f[512] = /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, }; +RecompOpFn recomp_opcodes_3DNOW[256] = +{ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPI2FD, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPF2ID, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ ropPFCMPGE, NULL, NULL, NULL, ropPFMIN, NULL, ropPFRCP, ropPFRSQRT, NULL, NULL, ropPFSUB, NULL, NULL, NULL, ropPFADD, NULL, +/*a0*/ ropPFCMPGT, NULL, NULL, NULL, ropPFMAX, NULL, ropPFRCPIT, ropPFRSQIT1, NULL, NULL, ropPFSUBR, NULL, NULL, NULL, NULL, NULL, +/*b0*/ ropPFCMPEQ, NULL, NULL, NULL, ropPFMUL, NULL, ropPFRCPIT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + RecompOpFn recomp_opcodes_d8[512] = { /*16-bit data*/ diff --git a/src/codegen_ops.h b/src/codegen_ops.h index 6e86be6..64f3547 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -9,6 +9,7 @@ typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t extern RecompOpFn recomp_opcodes[512]; extern RecompOpFn recomp_opcodes_0f[512]; +extern RecompOpFn recomp_opcodes_3DNOW[256]; extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; extern RecompOpFn recomp_opcodes_da[512]; diff --git a/src/codegen_ops_3dnow.c b/src/codegen_ops_3dnow.c new file mode 100644 index 0000000..ad846e4 --- /dev/null +++ b/src/codegen_ops_3dnow.c @@ -0,0 +1,193 @@ +#include "ibm.h" + +#include "x86.h" +#include "x86_flags.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_accumulate.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_3dnow.h" +#include "codegen_ops_helpers.h" + +#define ropParith(func) \ +uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ +{ \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + int src_reg = fetchdat & 7; \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } \ + else \ + { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 2; \ +} + +ropParith(PFADD) +ropParith(PFCMPEQ) +ropParith(PFCMPGE) +ropParith(PFCMPGT) +ropParith(PFMAX) +ropParith(PFMIN) +ropParith(PFMUL) +ropParith(PFSUB) + +uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 2; +} + +uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg)); + } + + return op_pc + 2; +} + +uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 2; +} + +uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 2; +} +uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 2; +} +uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + uop_MMX_ENTER(ir); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } + + return op_pc + 2; +} + +uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MMX_ENTER(ir); + + return op_pc + 2; +} diff --git a/src/codegen_ops_3dnow.h b/src/codegen_ops_3dnow.h new file mode 100644 index 0000000..3b124ae --- /dev/null +++ b/src/codegen_ops_3dnow.h @@ -0,0 +1,15 @@ +uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFCMPEQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFCMPGE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFCMPGT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFMAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFMIN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); From e8483acea54e98a76a87cabee330e5dc4a8be016 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 17 Dec 2018 19:36:54 +0000 Subject: [PATCH 086/181] Search through all host integer and FP registers when allocating registers. --- src/codegen_reg.c | 83 ++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 7d993fd..255fde7 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -214,6 +214,11 @@ static inline int ir_reg_is_invalid(ir_reg_t ir_reg) return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } +static inline int ir_get_get_refcount(ir_reg_t ir_reg) +{ + return reg_version_refcount[IREG_GET_REG(ir_reg.reg)][ir_reg.version]; +} + static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg) { if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER) @@ -401,9 +406,45 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i reg_set->dirty[c] = 0; } +static void alloc_reg(ir_reg_t ir_reg) +{ + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; + int c; + + for (c = 0; c < nr_regs; c++) + { + if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) + { + if (reg_set->regs[c].version != ir_reg.version) + fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg); + reg_set->locked |= (1 << c); + return; + } + } +} + +static void alloc_dest_reg(ir_reg_t ir_reg, int dest_reference) +{ + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; + int c; + + for (c = 0; c < nr_regs; c++) + { + if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) + { + if (reg_set->regs[c].version == ir_reg.version || (reg_set->regs[c].version == (ir_reg.version-1) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == dest_reference)) + reg_set->locked |= (1 << c); + else + fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference); + return; + } + } +} + void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) { - int c; int dest_reference = 0; host_reg_set.locked = 0; @@ -422,38 +463,14 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version-1) dest_reference++; } - for (c = 0; c < CODEGEN_HOST_REGS; c++) - { - host_reg_set_t *reg_set = get_reg_set(src_reg_a); - if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_a.reg)) - { - if (reg_set->regs[c].version != src_reg_a.version) - fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_a.version\n"); - reg_set->locked |= (1 << c); - } - reg_set = get_reg_set(src_reg_b); - if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_b.reg)) - { - if (reg_set->regs[c].version != src_reg_b.version) - fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n"); - reg_set->locked |= (1 << c); - } - reg_set = get_reg_set(src_reg_c); - if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_c.reg)) - { - if (reg_set->regs[c].version != src_reg_c.version) - fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_c.version\n"); - reg_set->locked |= (1 << c); - } - reg_set = get_reg_set(dest_reg_a); - if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dest_reg_a.reg)) - { - if (reg_set->regs[c].version == dest_reg_a.version || (reg_set->regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == dest_reference)) - reg_set->locked |= (1 << c); - else - fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, dest_reg_a.version, dest_reference); - } - } + if (!ir_reg_is_invalid(src_reg_a)) + alloc_reg(src_reg_a); + if (!ir_reg_is_invalid(src_reg_b)) + alloc_reg(src_reg_b); + if (!ir_reg_is_invalid(src_reg_c)) + alloc_reg(src_reg_c); + if (!ir_reg_is_invalid(dest_reg_a)) + alloc_dest_reg(dest_reg_a, dest_reference); } ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) From b26432caa8ea399d81a5f88835293d012d4f2010 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 17 Dec 2018 19:40:09 +0000 Subject: [PATCH 087/181] When allocating a read register, prioritise registers that will not be used again. --- src/codegen_reg.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 255fde7..c222d04 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -490,20 +490,29 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in if (c == reg_set->nr_regs) { - /*No unused registers. Search for an unlocked register*/ + /*No unused registers. Search for an unlocked register with no pending reads*/ for (c = 0; c < reg_set->nr_regs; c++) { - if (!(reg_set->locked & (1 << c))) + if (!(reg_set->locked & (1 << c)) && !ir_get_get_refcount(reg_set->regs[c])) break; } if (c == reg_set->nr_regs) - fatal("codegen_reg_alloc_read_reg - out of registers\n"); + { + /*Search for any unlocked register*/ + for (c = 0; c < reg_set->nr_regs; c++) + { + if (!(reg_set->locked & (1 << c))) + break; + } + if (c == reg_set->nr_regs) + fatal("codegen_reg_alloc_read_reg - out of registers\n"); + } if (reg_set->dirty[c]) codegen_reg_writeback(reg_set, block, c, 1); // pclog(" load %i\n", c); codegen_reg_load(reg_set, block, c, ir_reg); - reg_set->locked |= (1 << c); // fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c); + reg_set->locked |= (1 << c); // codegen_reg_writeback(block, c); reg_set->dirty[c] = 0; } From 93a5925f027ce5a4bd94f6411302df0041c24b44 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 19 Dec 2018 22:23:59 +0000 Subject: [PATCH 088/181] Use MOVZX on x86-64 when loading a word sized function parameter. Fixes issues when built with LLVM and -O3. --- src/codegen_backend_x86-64_uops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index ad11134..049c626 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -771,9 +771,9 @@ static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) if (REG_IS_W(src_size)) { #if WIN64 - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_MOVZX_REG_32_16(block, REG_ECX, src_reg); #else - host_x86_MOV16_REG_REG(block, REG_EDI, src_reg); + host_x86_MOVZX_REG_32_16(block, REG_EDI, src_reg); #endif } else From c86b919ed85c67336cf1bec3d2f2fc3a8abde7ab Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 19 Dec 2018 22:24:40 +0000 Subject: [PATCH 089/181] Fix writemem functions on x86-64 when !WIN64. --- src/codegen_backend_x86-64.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 4cdf2b4..22385dd 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -215,8 +215,14 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address #else + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8); //host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address - host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); //data + else if (size == 8) + host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); //data + else + host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data #endif if (size == 1) host_x86_CALL(block, (void *)writememb386l); @@ -228,6 +234,8 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_CALL(block, (void *)writememql); #if WIN64 host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28); +#else + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8); #endif host_x86_POP(block, REG_RDX); host_x86_POP(block, REG_RAX); From 1953f4afb9388b02a7eb41699589b87756b8ff43 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 19 Dec 2018 22:25:47 +0000 Subject: [PATCH 090/181] Use mmap() to allocate codeblock memory on x86-64 when not running on Windows. --- src/codegen_backend_x86-64.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 22385dd..5de8f75 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -286,7 +286,7 @@ void codegen_backend_init() #if defined WIN32 || defined _WIN32 || defined _WIN32 codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); + codeblock_data = mmap(0, BLOCK_SIZE * BLOCK_DATA_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0); #endif codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -299,16 +299,6 @@ void codegen_backend_init() codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; } - -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock & pagemask); - len = ((BLOCK_SIZE * sizeof(codeblock_t)) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; From 3c7d1b1204fe3e2e692ec7c2586725c4829c83a5 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 6 Jan 2019 13:46:17 +0000 Subject: [PATCH 091/181] Ensure that taken jump/branch instructions do not count as 0 cycles. Fixes Windows 95 hang with K6. --- src/codegen.c | 15 +++++++++++++++ src/codegen.h | 2 ++ src/codegen_timing_486.c | 8 +++++++- src/codegen_timing_686.c | 8 +++++++- src/codegen_timing_k6.c | 10 +++++++++- src/codegen_timing_pentium.c | 8 +++++++- src/codegen_timing_winchip.c | 8 +++++++- src/codegen_timing_winchip2.c | 8 +++++++- 8 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index a278cfe..653834c 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -21,6 +21,7 @@ void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); void (*codegen_timing_block_start)(); void (*codegen_timing_block_end)(); +int (*codegen_timing_jump_cycles)(); void codegen_timing_set(codegen_timing_t *timing) { @@ -29,6 +30,7 @@ void codegen_timing_set(codegen_timing_t *timing) codegen_timing_opcode = timing->opcode; codegen_timing_block_start = timing->block_start; codegen_timing_block_end = timing->block_end; + codegen_timing_jump_cycles = timing->jump_cycles; } int codegen_in_recompile; @@ -508,7 +510,20 @@ generate_call: (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) + { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = codegen_timing_jump_cycles(); + + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, -jump_cycles); codegen_accumulate_flush(ir); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, jump_cycles); + } if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f) { diff --git a/src/codegen.h b/src/codegen.h index e82b904..e0e8760 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -320,6 +320,7 @@ extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); extern void (*codegen_timing_block_start)(); extern void (*codegen_timing_block_end)(); +extern int (*codegen_timing_jump_cycles)(); typedef struct codegen_timing_t { @@ -328,6 +329,7 @@ typedef struct codegen_timing_t void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); void (*block_start)(); void (*block_end)(); + int (*jump_cycles)(); } codegen_timing_t; extern codegen_timing_t codegen_timing_pentium; diff --git a/src/codegen_timing_486.c b/src/codegen_timing_486.c index cda0436..6f9e3af 100644 --- a/src/codegen_timing_486.c +++ b/src/codegen_timing_486.c @@ -422,11 +422,17 @@ void codegen_timing_486_block_end() { } +int codegen_timing_486_jump_cycles() +{ + return 0; +} + codegen_timing_t codegen_timing_486 = { codegen_timing_486_start, codegen_timing_486_prefix, codegen_timing_486_opcode, codegen_timing_486_block_start, - codegen_timing_486_block_end + codegen_timing_486_block_end, + codegen_timing_486_jump_cycles }; diff --git a/src/codegen_timing_686.c b/src/codegen_timing_686.c index dab2b10..cc1e119 100644 --- a/src/codegen_timing_686.c +++ b/src/codegen_timing_686.c @@ -1067,11 +1067,17 @@ void codegen_timing_686_block_end() } } +int codegen_timing_686_jump_cycles() +{ + return 0; +} + codegen_timing_t codegen_timing_686 = { codegen_timing_686_start, codegen_timing_686_prefix, codegen_timing_686_opcode, codegen_timing_686_block_start, - codegen_timing_686_block_end + codegen_timing_686_block_end, + codegen_timing_686_jump_cycles }; diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c index a5d0cde..78d9678 100644 --- a/src/codegen_timing_k6.c +++ b/src/codegen_timing_k6.c @@ -2278,11 +2278,19 @@ void codegen_timing_k6_block_end() decode_flush(); } +int codegen_timing_k6_jump_cycles() +{ + if (decode_buffer.nr_uops) + return 1; + return 0; +} + codegen_timing_t codegen_timing_k6 = { codegen_timing_k6_start, codegen_timing_k6_prefix, codegen_timing_k6_opcode, codegen_timing_k6_block_start, - codegen_timing_k6_block_end + codegen_timing_k6_block_end, + codegen_timing_k6_jump_cycles }; diff --git a/src/codegen_timing_pentium.c b/src/codegen_timing_pentium.c index 24748cb..f21a70f 100644 --- a/src/codegen_timing_pentium.c +++ b/src/codegen_timing_pentium.c @@ -1328,11 +1328,17 @@ void codegen_timing_pentium_block_end() } } +int codegen_timing_pentium_jump_cycles() +{ + return 0; +} + codegen_timing_t codegen_timing_pentium = { codegen_timing_pentium_start, codegen_timing_pentium_prefix, codegen_timing_pentium_opcode, codegen_timing_pentium_block_start, - codegen_timing_pentium_block_end + codegen_timing_pentium_block_end, + codegen_timing_pentium_jump_cycles }; diff --git a/src/codegen_timing_winchip.c b/src/codegen_timing_winchip.c index 56ee3af..c23b30b 100644 --- a/src/codegen_timing_winchip.c +++ b/src/codegen_timing_winchip.c @@ -422,11 +422,17 @@ void codegen_timing_winchip_block_end() { } +int codegen_timing_winchip_jump_cycles() +{ + return 0; +} + codegen_timing_t codegen_timing_winchip = { codegen_timing_winchip_start, codegen_timing_winchip_prefix, codegen_timing_winchip_opcode, codegen_timing_winchip_block_start, - codegen_timing_winchip_block_end + codegen_timing_winchip_block_end, + codegen_timing_winchip_jump_cycles }; diff --git a/src/codegen_timing_winchip2.c b/src/codegen_timing_winchip2.c index ec47099..c85a0e9 100644 --- a/src/codegen_timing_winchip2.c +++ b/src/codegen_timing_winchip2.c @@ -743,11 +743,17 @@ static void codegen_timing_winchip2_block_end() } } +int codegen_timing_winchip2_jump_cycles() +{ + return 0; +} + codegen_timing_t codegen_timing_winchip2 = { codegen_timing_winchip2_start, codegen_timing_winchip2_prefix, codegen_timing_winchip2_opcode, codegen_timing_winchip2_block_start, - codegen_timing_winchip2_block_end + codegen_timing_winchip2_block_end, + codegen_timing_winchip2_jump_cycles }; From 8ee9b07ab227055eb805ada0452e9f14873ce65b Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 6 Jan 2019 14:23:23 +0000 Subject: [PATCH 092/181] Added decoder length limitations to K6 timing model --- src/codegen_timing_common.c | 16 ++++----- src/codegen_timing_common.h | 3 ++ src/codegen_timing_k6.c | 66 +++++++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/codegen_timing_common.c b/src/codegen_timing_common.c index 33ac5cf..c29f24f 100644 --- a/src/codegen_timing_common.c +++ b/src/codegen_timing_common.c @@ -823,21 +823,21 @@ uint64_t opcode_deps_df_mod3[8] = uint64_t opcode_deps_81[8] = { - MODRM, MODRM, MODRM, MODRM, - MODRM, MODRM, MODRM, MODRM + MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, + MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632 }; uint64_t opcode_deps_81_mod3[8] = { - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | MODRM | HAS_IMM1632 }; uint64_t opcode_deps_8x[8] = { - MODRM, MODRM, MODRM, MODRM, - MODRM, MODRM, MODRM, MODRM + MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, + MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8 }; uint64_t opcode_deps_8x_mod3[8] = { - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | MODRM | HAS_IMM8 }; diff --git a/src/codegen_timing_common.h b/src/codegen_timing_common.h index b185270..533a135 100644 --- a/src/codegen_timing_common.h +++ b/src/codegen_timing_common.h @@ -72,6 +72,9 @@ #define FPU_FXCH (1ull << 33) +#define HAS_IMM8 (1ull << 34) +#define HAS_IMM1632 (1ull << 35) + #define REGMASK_IMPL_ESP (1 << 8) #define REGMASK_SHIFTPACK (1 << 9) diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c index 78d9678..590e605 100644 --- a/src/codegen_timing_k6.c +++ b/src/codegen_timing_k6.c @@ -1723,6 +1723,7 @@ static const risc86_instruction_t *opcode_timings_df_mod3[8] = static uint8_t last_prefix; +static int prefixes; static int decode_timestamp; static int last_complete_timestamp; @@ -1899,12 +1900,64 @@ void decode_flush() decode_buffer.nr_uops = 0; } +/*The instruction is only of interest here if it's longer than 7 bytes, as that's the + limit on K6 short decoding*/ +static int codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) +{ + int len = prefixes + 1; /*Opcode*/ + if (deps & MODRM) + { + len++; /*ModR/M*/ + if (deps & HAS_IMM8) + len++; + if (deps & HAS_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; + + if (op_32 & 0x200) + { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) + { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } + else + { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } + else + { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; + } + } + + return len; +} + static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) { uint32_t regmask_required; uint32_t regmask_modified; int c, d; int earliest_start = 0; + decode_type_t decode_type = ins->decode_type; + int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); /*Generate input register mask, and determine the earliest time this instruction can start. This is not accurate, as this is calculated per @@ -1931,7 +1984,14 @@ static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, u earliest_start = fpu_st_timestamp[reg]; } - switch (ins->decode_type) + /*Short decoders are limited to 7 bytes*/ + if (decode_type == DECODE_SHORT && instr_length > 7) + decode_type = DECODE_LONG; + /*Long decoder is limited to 11 bytes*/ + else if (instr_length > 11) + decode_type = DECODE_VECTOR; + + switch (decode_type) { case DECODE_SHORT: if (decode_buffer.nr_uops) @@ -2051,7 +2111,7 @@ static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, u void codegen_timing_k6_block_start() { int c; - + for (c = 0; c < nr_units; c++) units[c].first_available_cycle = 0; @@ -2085,6 +2145,7 @@ void codegen_timing_k6_start() nr_units = NR_K6_2_UNITS; } last_prefix = 0; + prefixes = 0; } void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) @@ -2093,6 +2154,7 @@ void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) decode_timestamp++; last_prefix = prefix; + prefixes++; } void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) From 56a4d5cf83a046febd60c2932bdfcffc191f032f Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 10 Jan 2019 21:33:29 +0000 Subject: [PATCH 093/181] Use correct rounding mode on x86 and x86-64 recompiled versions of PF2ID. Fixes rendering errors on Unreal 3DNow! software renderer --- src/codegen_backend_x86-64.c | 1 + src/codegen_backend_x86-64_ops.c | 5 +++++ src/codegen_backend_x86-64_uops.c | 2 ++ src/codegen_backend_x86.c | 1 + src/codegen_backend_x86_uops.c | 2 ++ src/ibm.h | 3 +++ 6 files changed, 14 insertions(+) diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 5de8f75..29ca83a 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -310,6 +310,7 @@ void codegen_backend_init() "stmxcsr %0\n" : "=m" (cpu_state.old_fp_control) ); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } void codegen_set_rounding_mode(int mode) diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index f077960..0992683 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -541,6 +541,11 @@ void host_x86_LDMXCSR(codeblock_t *block, void *p) { codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ } + else if (offset < (1ull << 32)) + { + codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ + codegen_addlong(block, offset); + } else { fatal("host_x86_LDMXCSR - out of range %p\n", p); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 049c626..dd164d6 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1576,7 +1576,9 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } else fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 4a43ff0..82c1d87 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -333,6 +333,7 @@ pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); : "=m" (cpu_state.old_fp_control2), "=m" (cpu_state.old_fp_control) ); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } void codegen_set_rounding_mode(int mode) diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e53b91d..aa1c885 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1579,7 +1579,9 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } else fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); diff --git a/src/ibm.h b/src/ibm.h index e99c232..b587e62 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -181,6 +181,9 @@ struct uint32_t old_fp_control, new_fp_control; #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ uint16_t old_fp_control2, new_fp_control2; +#endif +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__ + uint32_t trunc_fp_control; #endif x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs; From 66fba50e063f2b6ca4eaf19c12a161aa53cee448 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 12 Jan 2019 15:15:43 +0000 Subject: [PATCH 094/181] Add new codegen memory allocator. This allows the recompiler to allocate memory from a central pool as required. This central pool is by default 64 MB on x86, x86-64 and ARMv8, and 32 MB on ARMv7. The current design does not allow for ARMv8 literal pools, therefore these have been removed. --- src/codegen.c | 1 + src/codegen.h | 12 +- src/codegen_backend.c | 32 +- src/codegen_backend.h | 39 --- src/codegen_backend_arm.c | 49 +-- src/codegen_backend_arm.h | 12 +- src/codegen_backend_arm64.c | 113 +++---- src/codegen_backend_arm64.h | 12 +- src/codegen_backend_arm64_ops.c | 230 ++++++++------ src/codegen_backend_arm64_ops.h | 7 +- src/codegen_backend_arm64_uops.c | 14 +- src/codegen_backend_arm_ops.c | 96 ++++-- src/codegen_backend_arm_ops.h | 2 + src/codegen_backend_arm_uops.c | 9 +- src/codegen_backend_x86-64.c | 169 ++++------ src/codegen_backend_x86-64.h | 11 +- src/codegen_backend_x86-64_ops.c | 512 +++++++++++++++++++++++++++--- src/codegen_backend_x86-64_ops.h | 2 + src/codegen_backend_x86-64_uops.c | 20 +- src/codegen_backend_x86.c | 121 +++---- src/codegen_backend_x86.h | 12 +- src/codegen_backend_x86_defs.h | 5 + src/codegen_backend_x86_ops.c | 488 ++++++++++++++++++++++++---- src/codegen_backend_x86_uops.c | 26 +- src/codegen_ir.c | 5 +- src/wx-sdl2-status.c | 7 +- 26 files changed, 1339 insertions(+), 667 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 653834c..5e3bc13 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -7,6 +7,7 @@ #include "386_common.h" #include "codegen_accumulate.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_ops.h" diff --git a/src/codegen.h b/src/codegen.h index e0e8760..e76391b 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -59,14 +59,18 @@ typedef struct codeblock_t present in two pages.*/ uint16_t prev, next; uint16_t prev_2, next_2; + + /*First mem_block_t used by this block. Any subsequent mem_block_ts + will be in the list starting at head_mem_block->next.*/ + struct mem_block_t *head_mem_block; } codeblock_t; -uint8_t *codeblock_data; - extern codeblock_t *codeblock; extern uint16_t *codeblock_hash; +extern uint8_t *block_write_data; + /*Code block uses FPU*/ #define CODEBLOCK_HAS_FPU 1 /*Code block is always entered with the same FPU top-of-stack*/ @@ -300,6 +304,10 @@ x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fe void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +/*Delete a random code block to free memory. This is obviously quite expensive, and + will only be called when the allocator is out of memory*/ +void codegen_delete_random_block(); + extern int cpu_block_end; extern uint32_t codegen_endpc; diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 500230d..db786b2 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -11,10 +11,13 @@ #include "codegen.h" #include "codegen_accumulate.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_reg.h" +uint8_t *block_write_data = NULL; + int codegen_flat_ds, codegen_flat_ss; int mmx_ebx_ecx_loaded; int codegen_flags_changed = 0; @@ -52,6 +55,7 @@ uint32_t instr_counts[256*256]; void codegen_init() { + codegen_allocator_init(); codegen_backend_init(); #ifdef DEBUG_EXTRA memset(instr_counts, 0, sizeof(instr_counts)); @@ -96,10 +100,7 @@ void codegen_reset() mem_reset_page_blocks(); for (c = 0; c < BLOCK_SIZE; c++) - { codeblock[c].pc = BLOCK_PC_INVALID; - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; - } } void dump_block() @@ -220,6 +221,28 @@ static void delete_block(codeblock_t *block) codeblock_tree_delete(block); remove_from_block_list(block, old_pc); + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; +} + +void codegen_delete_random_block() +{ + while (1) + { + int block_nr = rand() & BLOCK_MASK; + + if (block_nr && block_nr != block_current) + { + codeblock_t *block = &codeblock[block_nr]; + + if (block->pc != BLOCK_PC_INVALID && block->head_mem_block) + { + delete_block(block); + return; + } + } + } } void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) @@ -318,6 +341,9 @@ void codegen_block_start_recompile(codeblock_t *block) if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) fatal("Recompile to used block!\n"); + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block->status = cpu_cur_status; cpu_block_end = 0; diff --git a/src/codegen_backend.h b/src/codegen_backend.h index df6fcea..7a5c5c0 100644 --- a/src/codegen_backend.h +++ b/src/codegen_backend.h @@ -16,45 +16,6 @@ void codegen_backend_init(); void codegen_backend_prologue(codeblock_t *block); void codegen_backend_epilogue(codeblock_t *block); -static inline void addbyte(uint8_t val) -{ - codeblock[block_current].data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addword(uint16_t val) -{ - *(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addlong(uint32_t val) -{ - *(uint32_t *)&codeblock[block_current].data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - -static inline void addquad(uint64_t val) -{ - *(uint64_t *)&codeblock[block_current].data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } -} - struct ir_data_t; struct uop_t; diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index d2b0fe4..bb861ae 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -3,6 +3,7 @@ #include #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" @@ -126,8 +127,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); - - block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size, int is_float) @@ -199,8 +198,6 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) fatal("build_store_routine - unknown size %i\n", size); host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); - - block_pos = (block_pos + 63) & ~63; } static void build_loadstore_routines(codeblock_t *block) @@ -246,13 +243,13 @@ static void build_fp_round_routine(codeblock_t *block) host_arm_MOV_REG(block, REG_LR, REG_TEMP2); host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); - addlong(0); + host_arm_NOP(block); jump_table = (uint32_t *)&block->data[block_pos]; - addlong(0); - addlong(0); - addlong(0); - addlong(0); + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); @@ -279,12 +276,11 @@ static void build_fp_round_routine(codeblock_t *block) jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); host_arm_MOV_REG(block, REG_PC, REG_LR); - - block_pos = (block_pos + 63) & ~63; } void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -293,13 +289,6 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); -#endif - if (!codeblock_data) - fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -307,29 +296,24 @@ void codegen_backend_init() memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); for (c = 0; c < BLOCK_SIZE; c++) - { codeblock[c].pc = BLOCK_PC_INVALID; - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; - } -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock_data & pagemask); - len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; build_loadstore_routines(&codeblock[block_current]); +printf("block_pos=%i\n", block_pos); codegen_fp_round = &codeblock[block_current].data[block_pos]; build_fp_round_routine(&codeblock[block_current]); + block_write_data = NULL; + asm("vmrs %0, fpscr\n" : "=r" (cpu_state.old_fp_control) ); @@ -380,10 +364,7 @@ void codegen_backend_epilogue(codeblock_t *block) host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - if (block_pos > ARM_LITERAL_POOL_OFFSET) - fatal("Over limit!\n"); - - __clear_cache(&block->data[0], &block->data[block_pos]); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index 67d18e6..f8b330b 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -9,17 +9,10 @@ #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ - #define BLOCK_GPF_OFFSET 0 #define BLOCK_EXIT_OFFSET 32 -#define ARM_LITERAL_POOL_OFFSET 0x10000 - -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 - +#define BLOCK_MAX 0x3c0 void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); @@ -30,6 +23,3 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm void host_arm_call(codeblock_t *block, void *dst_addr); void host_arm_nop(codeblock_t *block); - -void codegen_reset_literal_pool(codeblock_t *block); -int add_literal(codeblock_t *block, uint32_t data); diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 534df5c..ba08ca8 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -3,6 +3,7 @@ #include #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" #include "codegen_backend_arm64_ops.h" @@ -83,9 +84,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) LDP X29, X30, [SP, #-16] RET */ + codegen_alloc(block, 80); host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); - offset = add_literal_q(block, (uintptr_t)readlookup2); - host_arm64_LDR_LITERAL_X(block, REG_X2, offset); + host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2); host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); if (size != 1) { @@ -107,9 +108,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_MOVZ_IMM(block, REG_W1, 0); host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); if (size == 1) host_arm64_call(block, (uintptr_t)readmemb386l); @@ -128,8 +129,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); - - block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size, int is_float) @@ -154,9 +153,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) LDP X29, X30, [SP, #-16] RET */ + codegen_alloc(block, 80); host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); - offset = add_literal_q(block, (uintptr_t)writelookup2); - host_arm64_LDR_LITERAL_X(block, REG_X3, offset); + host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2); host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); if (size != 1) { @@ -178,9 +177,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm64_MOVZ_IMM(block, REG_X1, 0); host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); if (size == 4 && is_float) host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); @@ -199,36 +198,34 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); - - block_pos = (block_pos + 63) & ~63; } static void build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + codegen_mem_load_byte = &block_write_data[block_pos]; build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + codegen_mem_load_word = &block_write_data[block_pos]; build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + codegen_mem_load_long = &block_write_data[block_pos]; build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + codegen_mem_load_quad = &block_write_data[block_pos]; build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + codegen_mem_load_single = &block_write_data[block_pos]; build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + codegen_mem_load_double = &block_write_data[block_pos]; build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + codegen_mem_store_byte = &block_write_data[block_pos]; build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + codegen_mem_store_word = &block_write_data[block_pos]; build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + codegen_mem_store_long = &block_write_data[block_pos]; build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + codegen_mem_store_quad = &block_write_data[block_pos]; build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + codegen_mem_store_single = &block_write_data[block_pos]; build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + codegen_mem_store_double = &block_write_data[block_pos]; build_store_routine(block, 8, 1); } @@ -236,50 +233,47 @@ static void build_fp_round_routine(codeblock_t *block, int is_quad) { uint64_t *jump_table; + codegen_alloc(block, 80); host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); host_arm64_ADR(block, REG_TEMP2, 12); host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); host_arm64_BR(block, REG_TEMP2); - jump_table = &block->data[block_pos]; - addquad(0); - addquad(0); - addquad(0); - addquad(0); + jump_table = &block_write_data[block_pos]; + block_pos += 4*8; - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even + jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even if (is_quad) host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf + jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf if (is_quad) host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf + jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf if (is_quad) host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero + jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero if (is_quad) host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); else host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); host_arm64_RET(block, REG_X30); - - block_pos = (block_pos + 63) & ~63; } void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -288,13 +282,6 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE); -#endif - if (!codeblock_data) - fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE); codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -304,29 +291,24 @@ void codegen_backend_init() for (c = 0; c < BLOCK_SIZE; c++) { codeblock[c].pc = BLOCK_PC_INVALID; - codeblock[c].data = &codeblock_data[c * BLOCK_SIZE]; } -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock_data & pagemask); - len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; - codegen_reset_literal_pool(&codeblock[block_current]); - build_loadstore_routines(&codeblock[block_current]); + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); - codegen_fp_round = &codeblock[block_current].data[block_pos]; - build_fp_round_routine(&codeblock[block_current], 0); - codegen_fp_round_quad = &codeblock[block_current].data[block_pos]; - build_fp_round_routine(&codeblock[block_current], 1); + codegen_fp_round = &block_write_data[block_pos]; + build_fp_round_routine(block, 0); + codegen_fp_round_quad = &block_write_data[block_pos]; + build_fp_round_routine(block, 1); + + block_write_data = NULL; asm("mrs %0, fpcr\n" : "=r" (cpu_state.old_fp_control) @@ -340,14 +322,11 @@ void codegen_set_rounding_mode(int mode) cpu_state.new_fp_control = mode << 3; } -/*R11 - literal pool - R10 - cpu_state*/ +/*R10 - cpu_state*/ void codegen_backend_prologue(codeblock_t *block) { int offset; - codegen_reset_literal_pool(block); - block_pos = 0; block_pos = BLOCK_GPF_OFFSET; @@ -378,8 +357,7 @@ void codegen_backend_prologue(codeblock_t *block) host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -64); - offset = add_literal_q(block, (uintptr_t)&cpu_state); - host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset); + host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state); if (block->flags & CODEBLOCK_HAS_FPU) { @@ -399,12 +377,7 @@ void codegen_backend_epilogue(codeblock_t *block) host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); host_arm64_RET(block, REG_X30); - if (block_pos > ARM_LITERAL_POOL_OFFSET) - fatal("Over limit!\n"); - - - - __clear_cache(&block->data[0], &block->data[block_pos]); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h index 21bef6d..74586fb 100644 --- a/src/codegen_backend_arm64.h +++ b/src/codegen_backend_arm64.h @@ -9,16 +9,10 @@ #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ - #define BLOCK_GPF_OFFSET 0 #define BLOCK_EXIT_OFFSET 32 -#define ARM_LITERAL_POOL_OFFSET 0xf000 - -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 +#define BLOCK_MAX 0x3c0 void host_arm64_BLR(codeblock_t *block, int addr_reg); @@ -36,7 +30,3 @@ void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int o void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); - -void codegen_reset_literal_pool(codeblock_t *block); -int add_literal(codeblock_t *block, uint32_t data); -int add_literal_q(codeblock_t *block, uint64_t data); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 7d71d31..1184a0a 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -2,22 +2,12 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm64_defs.h" #include "codegen_backend_arm64_ops.h" -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - #define Rt(x) (x) #define Rd(x) (x) #define Rn(x) ((x) << 5) @@ -53,21 +43,23 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_B (0x14 << OPCODE_SHIFT) #define OPCODE_BCOND (0x54 << OPCODE_SHIFT) #define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) +#define OPCODE_CBZ (0xb4 << OPCODE_SHIFT) #define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) #define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) #define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) #define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) -#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT) -#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT) #define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) #define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) #define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) +#define OPCODE_TBZ (0x36 << OPCODE_SHIFT) #define OPCODE_AND_IMM (0x024 << 23) #define OPCODE_ANDS_IMM (0x0e4 << 23) #define OPCODE_EOR_IMM (0x0a4 << 23) #define OPCODE_MOVK_W (0x0e5 << 23) +#define OPCODE_MOVK_X (0x1e5 << 23) #define OPCODE_MOVZ_W (0x0a5 << 23) +#define OPCODE_MOVZ_X (0x1a5 << 23) #define OPCODE_ORR_IMM (0x064 << 23) #define OPCODE_BFI (0x0cc << 22) @@ -225,6 +217,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) +#define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) #define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) #define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5)) #define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) @@ -242,12 +235,6 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define DUP_ELEMENT(element) ((element) << 19) -static int literal_offset = 0; -void codegen_reset_literal_pool(codeblock_t *block) -{ - literal_offset = 0; -} - /*Returns true if offset fits into 19 bits*/ static int offset_is_19bit(int offset) { @@ -268,33 +255,6 @@ static int offset_is_26bit(int offset) return 1; } -int add_literal(codeblock_t *block, uint32_t data) -{ - if (literal_offset >= 4096) - fatal("add_literal - literal pool full\n"); - - *(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 4; - - return literal_offset - 4; -} - -int add_literal_q(codeblock_t *block, uint64_t data) -{ - if (literal_offset & 4) - literal_offset += 4; - - if (literal_offset >= 4096-4) - fatal("add_literal - literal pool full\n"); - - *(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data; - - literal_offset += 8; - - return literal_offset - 8; -} - static inline int imm_is_imm16(uint32_t imm_data) { if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) @@ -308,6 +268,39 @@ static inline int imm_is_imm12(uint32_t imm_data) return 0; } +static void codegen_allocate_new_block(codeblock_t *block); + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + if (block_pos >= (BLOCK_MAX-4)) + codegen_allocate_new_block(block); + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]; + + if (!offset_is_26bit(offset)) + fatal("codegen_allocate_new_block - offset out of range %x\n", offset); + /*Add a jump instruction to the new block*/ + *(uint32_t *)&block_write_data[block_pos] = OPCODE_B | OFFSET26(offset); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +void codegen_alloc(codeblock_t *block, int size) +{ + if (block_pos >= (BLOCK_MAX-size)) + codegen_allocate_new_block(block); +} + void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { if (!imm_data) @@ -462,7 +455,10 @@ void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re void host_arm64_B(codeblock_t *block, void *dest) { - int offset = (uintptr_t)dest - (uintptr_t)&block->data[block_pos]; + int offset; + + codegen_alloc(block, 4); + offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; if (!offset_is_26bit(offset)) fatal("host_arm64_B - offset out of range %x\n", offset); @@ -481,79 +477,107 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg) uint32_t *host_arm64_BCC_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_CC); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BCS_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_CS); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BEQ_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_EQ); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BGE_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_GE); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BGT_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_GT); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BHI_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_HI); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BLE_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_LE); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BLS_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_LS); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BLT_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_LT); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BMI_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_MI); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BNE_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_NE); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BPL_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_PL); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BVC_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_VC); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_arm64_BVS_(codeblock_t *block) { - codegen_addlong(block, OPCODE_BCOND | COND_VS); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) { int offset = (uintptr_t)dest - (uintptr_t)opcode; - *opcode |= OFFSET19(offset); + *opcode |= OFFSET26(offset); } void host_arm64_BR(codeblock_t *block, int addr_reg) @@ -574,10 +598,16 @@ void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) { - int offset = dest - (uintptr_t)&block->data[block_pos]; - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + int offset = dest - (uintptr_t)&block_write_data[block_pos]; + if (offset_is_19bit(offset)) + codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + else + { + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg)); + offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); + } } void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) @@ -880,24 +910,6 @@ void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int of codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset) -{ - int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; - - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - - codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg)); -} -void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset) -{ - int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos; - - if (!offset_is_19bit(offset)) - fatal("host_arm64_CBNZ - offset out of range %x\n", offset); - - codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg)); -} void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); @@ -977,6 +989,16 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) +{ + codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg)); + if ((imm_data >> 16) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg)); + if ((imm_data >> 32) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg)); + if ((imm_data >> 48) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg)); +} void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { if (dst_reg != src_m_reg) @@ -1265,8 +1287,10 @@ void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_ uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) { - codegen_addlong(block, OPCODE_TBNZ | Rt(reg) | BIT_TBxZ(bit)); - return (uint32_t *)&block->data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *)&block_write_data[block_pos-4]; } void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) @@ -1346,15 +1370,13 @@ void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src void host_arm64_call(codeblock_t *block, void *dst_addr) { - int offset = add_literal_q(block, (uintptr_t)dst_addr); - host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); host_arm64_BLR(block, REG_X16); } void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) { - int offset = add_literal_q(block, (uintptr_t)dst_addr); - host_arm64_LDR_LITERAL_X(block, REG_X16, offset); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); host_arm64_BR(block, REG_X16); } diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index a8c3fc2..42760dd 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -121,8 +121,6 @@ void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, in void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset); -void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset); -void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset); void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg); @@ -146,6 +144,7 @@ void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data); void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data); @@ -170,6 +169,8 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); @@ -253,4 +254,4 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); -int add_literal_q(codeblock_t *block, uint64_t data); +void codegen_alloc(codeblock_t *block, int size); \ No newline at end of file diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 703a7e5..c2c5033 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -779,7 +779,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_arm64_call(block, x86_int); host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); - host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); return 0; } @@ -876,12 +876,11 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) { int src_reg = HOST_REG_GET(uop->src_reg_a_real); int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - int offset = add_literal_q(block, (uintptr_t)uop->p); if (!REG_IS_W(src_size)) fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); - host_arm64_LDR_LITERAL_X(block, REG_ARG1, offset); + host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t)uop->p); host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); host_arm64_call(block, (void *)loadseg); host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); @@ -1229,8 +1228,7 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) { - int offset = add_literal_q(block, (uintptr_t)uop->p); - host_arm64_LDR_LITERAL_X(block, uop->dest_reg_a_real, offset); + host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); return 0; } @@ -1371,7 +1369,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) host_arm64_call(block, codegen_fp_round_quad); host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); - host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -3031,8 +3029,6 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - int offset = (uintptr_t)&block->data[block_pos] - (uintptr_t)p; - - *(uint32_t *)p |= OFFSET19(offset); + host_arm64_branch_set_offset(p, &block_write_data[block_pos]); } #endif diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 85ffd9d..3e17433 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -2,21 +2,11 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } -} - #define Rm(x) (x) #define Rs(x) ((x) << 8) #define Rd(x) ((x) << 12) @@ -207,6 +197,37 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define VDUP_32_IMM(imm) ((imm) << 19) +static void codegen_allocate_new_block(codeblock_t *block); + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + if (block_pos >= (BLOCK_MAX-4)) + codegen_allocate_new_block(block); + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = ((uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]) - 8; + + /*Add a jump instruction to the new block*/ + *(uint32_t *)&block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +static inline void codegen_alloc_4(codeblock_t *block) +{ + if (block_pos >= (BLOCK_MAX-4)) + codegen_allocate_new_block(block); +} + static inline uint32_t arm_data_offset(int offset) { if (offset < -0xffc || offset > 0xffc) @@ -321,7 +342,10 @@ void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_B(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { @@ -366,7 +390,10 @@ void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { @@ -378,7 +405,10 @@ void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) } void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { @@ -397,90 +427,93 @@ uint32_t *host_arm_BCC_(codeblock_t *block) { codegen_addlong(block, COND_CC | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BCS_(codeblock_t *block) { codegen_addlong(block, COND_CS | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BEQ_(codeblock_t *block) { codegen_addlong(block, COND_EQ | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BGE_(codeblock_t *block) { codegen_addlong(block, COND_GE | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BGT_(codeblock_t *block) { codegen_addlong(block, COND_GT | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BHI_(codeblock_t *block) { codegen_addlong(block, COND_HI | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BLE_(codeblock_t *block) { codegen_addlong(block, COND_LE | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BLS_(codeblock_t *block) { codegen_addlong(block, COND_LS | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BLT_(codeblock_t *block) { codegen_addlong(block, COND_LT | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BMI_(codeblock_t *block) { codegen_addlong(block, COND_MI | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BNE_(codeblock_t *block) { codegen_addlong(block, COND_NE | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BPL_(codeblock_t *block) { codegen_addlong(block, COND_PL | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BVC_(codeblock_t *block) { codegen_addlong(block, COND_VC | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } uint32_t *host_arm_BVS_(codeblock_t *block) { codegen_addlong(block, COND_VS | OPCODE_B); - return (uint32_t *)&block->data[block_pos - 4]; + return (uint32_t *)&block_write_data[block_pos - 4]; } void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); @@ -489,7 +522,10 @@ void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) } void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8; + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 3c2ae77..94d9a9b 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -94,6 +94,8 @@ void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift); +#define host_arm_NOP(block) host_arm_MOV_REG(block, REG_R0, REG_R0) + void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm); void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 1a5d4e2..e65816f 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -6,6 +6,7 @@ #include "x87.h" #include "386_common.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_arm_defs.h" #include "codegen_backend_arm_ops.h" @@ -849,7 +850,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_arm_call(block, x86_int); host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); - *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; return 0; } @@ -870,7 +871,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_arm_call(block, x86_int); host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); - *branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; host_arm_MOV_IMM(block, REG_TEMP, 0); host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); @@ -1489,7 +1490,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) host_arm_call(block, x87_fround64); host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); - *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -3165,6 +3166,6 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; + *(uint32_t *)p |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; } #endif diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 29ca83a..86ed609 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" @@ -101,9 +102,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; host_x86_PUSH(block, REG_RAX); host_x86_PUSH(block, REG_RDX); #if WIN64 @@ -145,7 +146,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_POP(block, REG_RAX); host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; } static void build_store_routine(codeblock_t *block, int size, int is_float) @@ -200,9 +200,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; host_x86_PUSH(block, REG_RAX); host_x86_PUSH(block, REG_RDX); #if WIN64 @@ -241,7 +241,6 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_POP(block, REG_RAX); host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; } static void build_loadstore_routines(codeblock_t *block) @@ -283,11 +282,6 @@ void codegen_backend_init() long pagemask = ~(pagesize - 1); #endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = mmap(0, BLOCK_SIZE * BLOCK_DATA_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0); -#endif codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -295,16 +289,17 @@ void codegen_backend_init() memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; - } + // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; + codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL); + codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); + block_write_data = codeblock[block_current].data; build_loadstore_routines(&codeblock[block_current]); -// fatal("Here\n"); + block_write_data = NULL; asm( "stmxcsr %0\n" @@ -318,47 +313,46 @@ void codegen_set_rounding_mode(int mode) cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); } -static inline void call(codeblock_t *block, uintptr_t func) -{ - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; - - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - addbyte(0xE8); /*CALL*/ - addlong((uint32_t)diff); - } - else - { - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); - } -} - void codegen_backend_prologue(codeblock_t *block) { - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH RBX*/ - addbyte(0x55); /*PUSH RBP*/ - addbyte(0x56); /*PUSH RSI*/ - addbyte(0x57); /*PUSH RDI*/ - addbyte(0x41); /*PUSH R12*/ - addbyte(0x54); - addbyte(0x41); /*PUSH R13*/ - addbyte(0x55); - addbyte(0x41); /*PUSH R14*/ - addbyte(0x56); - addbyte(0x41); /*PUSH R15*/ - addbyte(0x57); - addbyte(0x48); /*SUBL $40,%rsp*/ - addbyte(0x83); - addbyte(0xEC); - addbyte(0x38); - addbyte(0x48); /*MOVL RBP, &cpu_state*/ - addbyte(0xBD); - addquad(((uintptr_t)&cpu_state) + 128); + block_pos = BLOCK_GPF_OFFSET; +#if WIN64 + host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX, REG_ECX); + host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX, REG_EDX); +#else + host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI, REG_EDI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); +#endif + host_x86_CALL(block, (uintptr_t)x86gpf); + while (block_pos < BLOCK_EXIT_OFFSET) + host_x86_NOP(block); + if (block_pos > BLOCK_EXIT_OFFSET) + fatal("block_pos > BLOCK_EXIT_OFFSET\n"); + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); + if (block_pos > BLOCK_START) + fatal("block_pos > BLOCK_START\n"); + + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_RBX); + host_x86_PUSH(block, REG_RBP); + host_x86_PUSH(block, REG_RSI); + host_x86_PUSH(block, REG_RDI); + host_x86_PUSH(block, REG_R12); + host_x86_PUSH(block, REG_R13); + host_x86_PUSH(block, REG_R14); + host_x86_PUSH(block, REG_R15); + host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); @@ -369,62 +363,15 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x38); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - block_pos = BLOCK_GPF_OFFSET; -#if WIN64 - addbyte(0x48); /*XOR RCX, RCX*/ - addbyte(0x31); - addbyte(0xc9); - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); -#else - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); -#endif - call(block, (uintptr_t)x86gpf); - while (block_pos < BLOCK_EXIT_OFFSET) - addbyte(0x90); /*NOP*/ - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x38); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); } - #endif diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h index 4e9ec51..de52c3c 100644 --- a/src/codegen_backend_x86-64.h +++ b/src/codegen_backend_x86-64.h @@ -2,17 +2,14 @@ #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_START 40 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 32) -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +#define BLOCK_EXIT_OFFSET 20 +#define BLOCK_GPF_OFFSET 0 -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 +#define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 0992683..956f4eb 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" @@ -17,80 +18,100 @@ #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 +#define JMP_LEN_BYTES 5 + static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { - block->data[block_pos++] = val; if (block_pos >= BLOCK_MAX) { fatal("codegen_addbyte over! %i\n", block_pos); // CPU_BLOCK_END(); } + block_write_data[block_pos++] = val; } static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-2)) { fatal("codegen_addbyte2 over! %i\n", block_pos); CPU_BLOCK_END(); } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-3)) { fatal("codegen_addbyte3 over! %i\n", block_pos); CPU_BLOCK_END(); } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - block->data[block_pos++] = vald; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-4)) { fatal("codegen_addbyte4 over! %i\n", block_pos); CPU_BLOCK_END(); } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } static inline void codegen_addword(codeblock_t *block, uint16_t val) { - *(uint16_t *)&block->data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-2)) { fatal("codegen_addword over! %i\n", block_pos); CPU_BLOCK_END(); } + *(uint16_t *)&block_write_data[block_pos] = val; + block_pos += 2; } static inline void codegen_addlong(codeblock_t *block, uint32_t val) { - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-4)) { fatal("codegen_addlong over! %i\n", block_pos); CPU_BLOCK_END(); } + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; } static inline void codegen_addquad(codeblock_t *block, uint64_t val) { - *(uint64_t *)&block->data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) + if (block_pos > (BLOCK_MAX-8)) { fatal("codegen_addquad over! %i\n", block_pos); CPU_BLOCK_END(); } + *(uint64_t *)&block_write_data[block_pos] = val; + block_pos += 8; +} + +static inline void codegen_alloc_bytes(codeblock_t *block, int size) +{ + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + { + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; + } } static int is_imm8(uint32_t imm_data) @@ -102,7 +123,10 @@ static int is_imm8(uint32_t imm_data) static inline void call(codeblock_t *block, uintptr_t func) { - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + uintptr_t diff; + + codegen_alloc_bytes(block, 5); + diff = func - (uintptr_t)&block_write_data[block_pos + 5]; if (diff >= -0x80000000 && diff < 0x7fffffff) { @@ -111,6 +135,7 @@ static inline void call(codeblock_t *block, uintptr_t func) } else { + codegen_alloc_bytes(block, 13); codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ codegen_addquad(block, func); codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ @@ -119,7 +144,10 @@ static inline void call(codeblock_t *block, uintptr_t func) static inline void jmp(codeblock_t *block, uintptr_t func) { - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + uintptr_t diff; + + codegen_alloc_bytes(block, 5); + diff = func - (uintptr_t)&block_write_data[block_pos + 5]; if (diff >= -0x80000000 && diff < 0x7fffffff) { @@ -128,6 +156,7 @@ static inline void jmp(codeblock_t *block, uintptr_t func) } else { + codegen_alloc_bytes(block, 13); codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ codegen_addquad(block, func); codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ @@ -140,9 +169,15 @@ void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ + } } void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -150,14 +185,19 @@ void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -168,14 +208,19 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -186,7 +231,10 @@ void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); } @@ -195,6 +243,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -202,6 +251,7 @@ void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -209,15 +259,18 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } @@ -227,9 +280,15 @@ void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ + } } void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -237,14 +296,19 @@ void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -255,14 +319,19 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -272,6 +341,7 @@ void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -279,6 +349,7 @@ void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -286,6 +357,7 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ } @@ -297,14 +369,19 @@ void host_x86_CALL(codeblock_t *block, void *p) void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -312,14 +389,19 @@ void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -327,87 +409,107 @@ void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else fatal("CMP64_REG_IMM not 8-bit imm\n"); } void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ } void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ } void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ } void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ } void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ } @@ -418,118 +520,138 @@ void host_x86_JMP(codeblock_t *block, void *p) void host_x86_JNZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } void host_x86_JZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } uint8_t *host_x86_JNZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JS_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint32_t *host_x86_JNB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } void host_x86_LAHF(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x9f); /*LAHF*/ } @@ -539,10 +661,12 @@ void host_x86_LDMXCSR(codeblock_t *block, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ codegen_addlong(block, offset); } @@ -556,17 +680,22 @@ void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t { if (offset) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ codegen_addlong(block, offset); } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } } void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_LEA_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } @@ -575,12 +704,14 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ } @@ -590,6 +721,7 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ codegen_addbyte(block, imm_data); } @@ -597,6 +729,7 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { if ((uintptr_t)p >> 32) fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 8); codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); codegen_addbyte(block, imm_data); @@ -608,6 +741,7 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addlong(block, imm_data); } @@ -615,6 +749,7 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { if ((uintptr_t)p >> 32) fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 11); codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); codegen_addlong(block, imm_data); @@ -630,12 +765,14 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -650,10 +787,12 @@ void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ codegen_addlong(block, offset); } @@ -672,10 +811,12 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ codegen_addlong(block, offset); } @@ -683,6 +824,7 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { if ((uintptr_t)p >> 32) fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -697,12 +839,14 @@ void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ } else { if ((uintptr_t)p >> 32) fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)(uintptr_t)p); } @@ -714,10 +858,12 @@ void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -727,18 +873,21 @@ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_re { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ } void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ } void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ } @@ -751,10 +900,12 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } @@ -772,10 +923,12 @@ void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } @@ -793,16 +946,19 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } else { fatal("host_x86_MOV32_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -817,10 +973,12 @@ void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ codegen_addlong(block, offset); } @@ -834,10 +992,12 @@ void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -847,6 +1007,7 @@ void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ } @@ -854,6 +1015,7 @@ void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int ba { if ((dst_reg & 8) || (index_reg & 8)) fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + codegen_alloc_bytes(block, 4); if (base_reg & 8) codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ else @@ -869,11 +1031,15 @@ void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); @@ -887,10 +1053,14 @@ void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -904,11 +1074,15 @@ void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x48); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -923,10 +1097,14 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); @@ -940,11 +1118,15 @@ void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x48); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); @@ -954,12 +1136,14 @@ void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { if (reg >= 8) fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ } void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { if (reg & 8) fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addword(block, imm_data); } @@ -967,6 +1151,7 @@ void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { if (reg & 8) fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -975,11 +1160,13 @@ void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) { if (reg & 8) { + codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ codegen_addquad(block, imm_data); } else { + codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ codegen_addquad(block, imm_data); } @@ -990,6 +1177,7 @@ void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV8_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) @@ -997,6 +1185,7 @@ void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV16_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) @@ -1004,6 +1193,7 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV32_REG_REG - bad reg\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } @@ -1011,16 +1201,19 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d { if (!offset) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } else if (offset >= -80 || offset < 0x80) { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 11); codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, offset); codegen_addlong(block, imm_data); @@ -1029,20 +1222,24 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1055,6 +1252,7 @@ void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } @@ -1062,6 +1260,7 @@ void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) { if ((uintptr_t)p >> 32) fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addbyte(block, 0x25); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -1072,13 +1271,16 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } @@ -1086,6 +1288,7 @@ void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -1095,11 +1298,13 @@ void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ codegen_addbyte(block, offset); } @@ -1117,6 +1322,7 @@ void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } @@ -1124,6 +1330,7 @@ void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) { if ((uintptr_t)p >> 32) fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addbyte(block, 0x25); codegen_addlong(block, (uint32_t)(uintptr_t)p); @@ -1134,19 +1341,23 @@ void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint3 if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } } void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -1156,11 +1367,13 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ codegen_addbyte(block, offset); } @@ -1171,30 +1384,36 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } @@ -1202,12 +1421,16 @@ void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_re { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); } void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); } @@ -1215,18 +1438,24 @@ void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } @@ -1240,8 +1469,16 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { if (dst_reg & 8) + { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x44); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + else + { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } } else fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); @@ -1249,31 +1486,47 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ } void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ } void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ } void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } +void host_x86_NOP(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x90); /*NOP*/ +} + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) { if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ + } } void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1281,14 +1534,19 @@ void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_ fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1299,14 +1557,19 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1316,6 +1579,7 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1323,6 +1587,7 @@ void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1330,23 +1595,27 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); @@ -1354,210 +1623,267 @@ void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ } void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ } void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ } void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ } void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ } void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ } void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ } void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ } void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ } void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ } void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ } void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ } void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ } void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ } void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ } void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ } void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ } void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) - fatal("POP reg & 8\n"); - codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x41, 0x58 | (dst_reg & 7)); /*POP reg*/ + } + else + { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ + } } void host_x86_PUSH(codeblock_t *block, int src_reg) { if (src_reg & 8) - fatal("PUSH reg & 8\n"); - codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x41, 0x50 | (src_reg & 7)); /*PUSH reg*/ + } + else + { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + } } void host_x86_RET(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0xc3); /*RET*/ } @@ -1565,18 +1891,24 @@ void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SAR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SAR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SAR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } @@ -1584,18 +1916,23 @@ void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SAR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SAR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SAR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } @@ -1603,18 +1940,24 @@ void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHL8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHL16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHL32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } @@ -1622,18 +1965,24 @@ void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHL8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHL16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHL32 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } @@ -1641,18 +1990,24 @@ void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) fatal("SHR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } @@ -1660,27 +2015,34 @@ void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { if (dst_reg & 8) fatal("SHR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ } void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ } @@ -1690,9 +2052,15 @@ void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ + } } void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1700,14 +2068,19 @@ void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1718,14 +2091,19 @@ void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1736,7 +2114,10 @@ void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); } @@ -1745,6 +2126,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1752,6 +2134,7 @@ void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1759,15 +2142,18 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ } void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1775,16 +2161,20 @@ void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) { if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_TEST32_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) @@ -1793,11 +2183,13 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) fatal("TEST32_REG_IMM reg & 8\n"); if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1805,6 +2197,7 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1814,9 +2207,15 @@ void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ + } } void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1824,14 +2223,19 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1842,14 +2246,19 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1859,6 +2268,7 @@ void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1866,6 +2276,7 @@ void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1873,6 +2284,7 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ } diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index ea2eede..209e270 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -163,6 +163,8 @@ void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_NOP(codeblock_t *block); + void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index dd164d6..e49fe7f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -715,11 +715,11 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); #if WIN64 host_x86_MOV32_REG_IMM(block, REG_ECX, 7); @@ -728,17 +728,17 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) #endif host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; return 0; } static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); #if WIN64 host_x86_MOV32_REG_IMM(block, REG_ECX, 7); @@ -747,7 +747,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) #endif host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); @@ -1269,19 +1269,19 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { - uint8_t *branch_offset; + uint32_t *branch_offset; /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_short(block); + branch_offset = host_x86_JS_long(block); host_x86_LDMXCSR(block, &cpu_state.new_fp_control); host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); host_x86_LDMXCSR(block, &cpu_state.old_fp_control); host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -2763,7 +2763,7 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); } #endif diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 82c1d87..68d9a36 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -3,6 +3,7 @@ #include #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" @@ -100,9 +101,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; host_x86_PUSH(block, REG_EAX); host_x86_PUSH(block, REG_EDX); host_x86_PUSH(block, REG_ECX); @@ -190,9 +191,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1; + *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; if (size == 4 && is_float) host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); host_x86_PUSH(block, REG_EAX); @@ -254,6 +255,7 @@ static void build_loadstore_routines(codeblock_t *block) void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -283,48 +285,33 @@ pclog(" offsetof(codeblock_t, next)=%i\n", offsetof(codeblock_t, next)); pclog(" offsetof(codeblock_t, prev_2)=%i\n", offsetof(codeblock_t, prev_2)); pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); -#if defined WIN32 || defined _WIN32 || defined _WIN32 - codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else - codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE; -#endif codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE]; codeblock[c].pc = BLOCK_PC_INVALID; - } -#if defined(__linux__) || defined(__APPLE__) - start = (void *)((long)codeblock_data & pagemask); - len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask; - if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - { - perror("mprotect"); - exit(-1); - } -#endif // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); block_current = 0; block_pos = 0; - mem_abrt_rout = &codeblock[block_current].data[block_pos]; - addbyte(0x83); /*ADDL $16+4,%esp*/ - addbyte(0xC4); - addbyte(0x10+4); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + mem_abrt_rout = &block->data[block_pos]; + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x10+4); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); + block_pos = 64; - build_loadstore_routines(&codeblock[block_current]); - //fatal("Here\n"); + build_loadstore_routines(block); + block_write_data = NULL; cpu_state.old_fp_control = 0; asm( @@ -346,16 +333,25 @@ void codegen_set_rounding_mode(int mode) void codegen_backend_prologue(codeblock_t *block) { - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x55); /*PUSH EBP*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $64,%esp*/ - addbyte(0xEC); - addbyte(0x40); - addbyte(0xBD); /*MOVL EBP, &cpu_state*/ - addlong(((uintptr_t)&cpu_state) + 128); + block_pos = BLOCK_GPF_OFFSET; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); + host_x86_CALL(block, (void *)x86gpf); + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); + + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_EBX); + host_x86_PUSH(block, REG_EBP); + host_x86_PUSH(block, REG_ESI); + host_x86_PUSH(block, REG_EDI); + host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); @@ -366,39 +362,12 @@ void codegen_backend_prologue(codeblock_t *block) void codegen_backend_epilogue(codeblock_t *block) { - addbyte(0x83); /*ADDL $64,%esp*/ - addbyte(0xC4); - addbyte(0x40); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - block_pos = BLOCK_GPF_OFFSET; - addbyte(0xc7); /*MOV [ESP],0*/ - addbyte(0x04); - addbyte(0x24); - addlong(0); - addbyte(0xc7); /*MOV [ESP+4],0*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x04); - addlong(0); - addbyte(0xe8); /*CALL x86gpf*/ - addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $64,%esp*/ - addbyte(0xC4); - addbyte(0x40); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); } #endif diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h index 13ccfab..52df734 100644 --- a/src/codegen_backend_x86.h +++ b/src/codegen_backend_x86.h @@ -2,18 +2,14 @@ #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_START 32 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff #define HASH(l) ((l) & 0x1ffff) -/*Hack until better memory management written*/ -#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 16) -//#define BLOCK_EXIT_OFFSET 0xfff0 -/*#define BLOCK_EXIT_OFFSET 0x7f0*/ -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +#define BLOCK_EXIT_OFFSET 20 +#define BLOCK_GPF_OFFSET 0 -/*#define BLOCK_MAX 1720*/ -#define BLOCK_MAX 65208 +#define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 03b2a2e..0c9eb1d 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -39,4 +39,9 @@ extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; +#define STACK_ARG0 (0) +#define STACK_ARG1 (4) +#define STACK_ARG2 (8) +#define STACK_ARG3 (12) + #endif diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 97ba65f..56bd27a 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" @@ -17,80 +18,82 @@ #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 +#define JMP_LEN_BYTES 5 + static inline void codegen_addbyte(codeblock_t *block, uint8_t val) { - block->data[block_pos++] = val; if (block_pos >= BLOCK_MAX) - { fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } + block_write_data[block_pos++] = val; } static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-2)) fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-3)) fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - block->data[block_pos++] = vala; - block->data[block_pos++] = valb; - block->data[block_pos++] = valc; - block->data[block_pos++] = vald; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-4)) fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } static inline void codegen_addword(codeblock_t *block, uint16_t val) { - *(uint16_t *)&block->data[block_pos] = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-2)) fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } + *(uint16_t *)&block_write_data[block_pos] = val; + block_pos += 2; } static inline void codegen_addlong(codeblock_t *block, uint32_t val) { - *(uint32_t *)&block->data[block_pos] = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-4)) fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; } static inline void codegen_addquad(codeblock_t *block, uint64_t val) { - *(uint64_t *)&block->data[block_pos] = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { + if (block_pos > (BLOCK_MAX-8)) fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } + *(uint64_t *)&block_write_data[block_pos] = val; + block_pos += 8; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +static inline void codegen_alloc_bytes(codeblock_t *block, int size) +{ + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + codegen_allocate_new_block(block); } static int is_imm8(uint32_t imm_data) @@ -106,10 +109,12 @@ void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void * if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (dst_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -122,9 +127,15 @@ void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ + } } void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -132,14 +143,19 @@ void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -150,14 +166,19 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -168,6 +189,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -175,6 +197,7 @@ void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -182,15 +205,18 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ } void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } @@ -200,9 +226,15 @@ void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ + } } void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -210,14 +242,19 @@ void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -228,14 +265,19 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -246,6 +288,7 @@ void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -253,6 +296,7 @@ void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -260,26 +304,33 @@ void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_CALL(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xe8); /*CALL*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -287,14 +338,19 @@ void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -302,205 +358,243 @@ void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ } void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ } void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ } void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ } void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ } void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ } void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ } void host_x86_INC32_ABS(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ codegen_addlong(block, (uint32_t)p); } void host_x86_JMP(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } uint32_t *host_x86_JMP_long(codeblock_t *block) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xe9); /*JMP*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } void host_x86_JNZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } void host_x86_JZ(codeblock_t *block, void *p) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]); + codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); } uint8_t *host_x86_JNZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JS_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint8_t *host_x86_JZ_short(codeblock_t *block) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block->data[block_pos-1]; + return &block_write_data[block_pos-1]; } uint32_t *host_x86_JNB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JNZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JB_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JBE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JL_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JLE_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JO_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JS_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } uint32_t *host_x86_JZ_long(codeblock_t *block) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ codegen_addlong(block, 0); - return (uint32_t *)&block->data[block_pos-4]; + return (uint32_t *)&block_write_data[block_pos-4]; } void host_x86_LAHF(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x9f); /*LAHF*/ } @@ -510,10 +604,12 @@ void host_x86_LDMXCSR(codeblock_t *block, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -523,24 +619,31 @@ void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t { if (offset) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ codegen_addlong(block, offset); } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } } void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ } void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ } void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ } @@ -550,11 +653,13 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ codegen_addbyte(block, imm_data); } else { + codegen_alloc_bytes(block, 7); codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ codegen_addlong(block, (uint32_t)p); codegen_addbyte(block, imm_data); @@ -566,11 +671,13 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 10); codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ codegen_addlong(block, (uint32_t)p); codegen_addlong(block, imm_data); @@ -583,10 +690,12 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ codegen_addbyte(block, 0x05 | (src_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -598,10 +707,12 @@ void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } @@ -612,10 +723,12 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (src_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -626,10 +739,12 @@ void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int { if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -637,14 +752,17 @@ void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ } void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ } void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ } @@ -654,10 +772,12 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (dst_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -669,10 +789,12 @@ void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } @@ -683,10 +805,12 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ codegen_addbyte(block, 0x05 | (dst_reg << 3)); codegen_addlong(block, (uint32_t)p); @@ -695,6 +819,7 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ codegen_addlong(block, (uint32_t)p); } @@ -703,10 +828,12 @@ void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 { if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ codegen_addlong(block, addr); } @@ -714,6 +841,7 @@ void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32 void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } @@ -723,11 +851,15 @@ void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); @@ -738,10 +870,14 @@ void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } } else fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); @@ -753,11 +889,15 @@ void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x66); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); @@ -768,10 +908,14 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } } else fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); @@ -779,16 +923,19 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ } void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { if (!imm_data) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ codegen_addword(block, imm_data); } @@ -797,10 +944,12 @@ void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (!imm_data) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ } else { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -808,14 +957,17 @@ void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } @@ -823,16 +975,19 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d { if (!offset) { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } else if (offset >= -80 || offset < 0x80) { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 11); codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ codegen_addlong(block, offset); codegen_addlong(block, imm_data); @@ -841,20 +996,24 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); } void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } @@ -864,30 +1023,36 @@ void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } else { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } } void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } } void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -897,11 +1062,13 @@ void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ codegen_addbyte(block, offset); } @@ -913,16 +1080,19 @@ void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg { if (!offset) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ codegen_addbyte(block, 0x24); } else if (offset >= -80 || offset < 0x80) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ codegen_addbyte2(block, 0x24, offset & 0xff); } else { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ codegen_addbyte(block, 0x24); codegen_addlong(block, offset); @@ -936,30 +1106,36 @@ void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ codegen_addbyte(block, offset); } else { + codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ codegen_addlong(block, (uint32_t)p); } } void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) { - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); codegen_addlong(block, addr); } } void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ codegen_addbyte(block, base_reg | (idx_reg << 3)); } @@ -969,11 +1145,13 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re { if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ codegen_addbyte2(block, 0x24, offset); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ codegen_addbyte(block, offset); } @@ -983,19 +1161,23 @@ void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_re } void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } @@ -1005,10 +1187,12 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -1019,10 +1203,12 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -1030,41 +1216,50 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ } void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ } void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ } void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ } void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ } void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1073,6 +1268,7 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr if (dst_reg != src_reg_a) fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1080,6 +1276,7 @@ void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1087,6 +1284,7 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ } @@ -1096,9 +1294,15 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ + } } void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1106,14 +1310,19 @@ void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_ fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 7); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1124,14 +1333,19 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1139,18 +1353,21 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); } void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ codegen_addbyte(block, 0x88); @@ -1158,206 +1375,251 @@ void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ } void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ } void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ } void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ } void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ } void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ } void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ } void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ } void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ } void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ } void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ } void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 5); codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ codegen_addbyte(block, shift); } void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ } void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ } void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ } void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ } void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 9); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ codegen_addbyte(block, 0xee); } void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ } void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ } void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ } void host_x86_POP(codeblock_t *block, int src_reg) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ } void host_x86_PUSH(codeblock_t *block, int src_reg) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ } void host_x86_RET(codeblock_t *block) { + codegen_alloc_bytes(block, 1); codegen_addbyte(block, 0xc3); /*RET*/ } @@ -1365,88 +1627,108 @@ void host_x86_RET(codeblock_t *block) void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ } void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ } void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ } @@ -1456,9 +1738,15 @@ void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ + } } void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1466,14 +1754,19 @@ void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1484,14 +1777,19 @@ void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1502,6 +1800,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1509,6 +1808,7 @@ void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1516,39 +1816,47 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ } void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ } void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); } void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ } void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1556,6 +1864,7 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } @@ -1564,6 +1873,7 @@ void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s if (dst_reg != src_reg_a) fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1571,6 +1881,7 @@ void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) @@ -1578,6 +1889,7 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int if (dst_reg != src_reg_a) fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ } @@ -1587,9 +1899,15 @@ void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); if (dst_reg == REG_EAX) + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + } else + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ + } } void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) { @@ -1597,14 +1915,19 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ codegen_addword(block, imm_data); } else { + codegen_alloc_bytes(block, 5); codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ codegen_addword(block, imm_data); } @@ -1615,14 +1938,19 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); if (is_imm8(imm_data)) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ codegen_addlong(block, imm_data); } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ codegen_addlong(block, imm_data); } @@ -1631,16 +1959,28 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ + } } void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ + } } void host_x87_FLDCW(codeblock_t *block, void *p) { @@ -1648,10 +1988,12 @@ void host_x87_FLDCW(codeblock_t *block, void *p) if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ } else { + codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ codegen_addlong(block, (uint32_t)p); } @@ -1659,16 +2001,28 @@ void host_x87_FLDCW(codeblock_t *block, void *p) void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ + } } void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) { if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + } else + { + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ + } } #endif diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index aa1c885..b0a54af 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -5,16 +5,12 @@ #include "x87.h" #include "386_common.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" #include "codegen_ir_defs.h" -#define STACK_ARG0 (0) -#define STACK_ARG1 (4) -#define STACK_ARG2 (8) -#define STACK_ARG3 (12) - /*void codegen_debug() { pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX); @@ -726,32 +722,32 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; return 0; } static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint8_t *branch_offset; + uint32_t *branch_offset; host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_short(block); + branch_offset = host_x86_JZ_long(block); host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); host_x86_CALL(block, x86_int); host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); @@ -1268,12 +1264,12 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { - uint8_t *branch_offset; + uint32_t *branch_offset; /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_short(block); + branch_offset = host_x86_JS_long(block); /*There is no SSE instruction to convert a floating point value to a 64-bit integer. Instead we have to bounce through memory via x87.*/ @@ -1284,7 +1280,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); host_x87_FLDCW(block, &cpu_state.old_fp_control2); - *branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1; + *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; } else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); @@ -2769,7 +2765,7 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int void codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); } #endif diff --git a/src/codegen_ir.c b/src/codegen_ir.c index bd0e541..97a2dc1 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -1,5 +1,6 @@ #include "ibm.h" #include "codegen.h" +#include "codegen_allocator.h" #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_reg.h" @@ -20,6 +21,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) int jump_target_at_end = -1; int c; + block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); + block_pos = 0; codegen_backend_prologue(block); for (c = 0; c < ir->wr_pos; c++) @@ -114,7 +117,7 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) } codegen_backend_epilogue(block); - + block_write_data = NULL; // if (has_ea) // fatal("IR compilation complete\n"); } diff --git a/src/wx-sdl2-status.c b/src/wx-sdl2-status.c index 735fa44..71c01ac 100644 --- a/src/wx-sdl2-status.c +++ b/src/wx-sdl2-status.c @@ -14,6 +14,7 @@ #include "ide.h" #include "cdrom-image.h" #include "scsi_zip.h" +#include "codegen_allocator.h" #include "wx-common.h" drive_info_t drive_info[10]; @@ -135,7 +136,7 @@ int get_status(char* machine, char* device) "\n" "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" - "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS" + "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS\nMem blocks used : %i (%g MB)" // "\nFully recompiled ins %% : %f%%" ,mips, flops, @@ -158,7 +159,9 @@ int get_status(char* machine, char* device) cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, cpu_recomp_reuse_latched, cpu_recomp_removed_latched, - ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq) + ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq), + codegen_allocator_usage, + (double)(codegen_allocator_usage * MEM_BLOCK_SIZE) / (1024.0*1024.0) // ((double)cpu_recomp_full_ins_latched / (double)cpu_recomp_ins_latched) * 100.0 // cpu_reps_latched, cpu_notreps_latched ); From 68464d6e81b389920ac89dd9e5280634fa4e7a73 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 12 Jan 2019 15:16:03 +0000 Subject: [PATCH 095/181] Fix 3DNow build issues on ARM platforms. --- src/codegen_backend_arm64_ops.c | 6 ++++ src/codegen_backend_arm64_uops.c | 58 ++++++++++++++++---------------- src/codegen_backend_arm_ops.c | 14 ++++++-- src/codegen_backend_arm_ops.h | 3 ++ src/codegen_backend_arm_uops.c | 30 ++++++++--------- 5 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 1184a0a..f253a4c 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -167,6 +167,7 @@ #define OPCODE_SADDLP_V2S_4H (0x0e602800) #define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) +#define OPCODE_SCVTF_V2S (0x0e21d800) #define OPCODE_SQADD_V8B (0x0e200c00) #define OPCODE_SQADD_V4H (0x0e600c00) #define OPCODE_SQSUB_V8B (0x0e202c00) @@ -1105,6 +1106,11 @@ void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } +void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SCVTF_V2S | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { if (shift > 16) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index c2c5033..fd89d84 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1696,12 +1696,12 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) } static int codegen_PFADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1710,12 +1710,12 @@ static int codegen_PFADD(codeblock_t *block, uop_t *uop) } static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1724,12 +1724,12 @@ static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) } static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1738,12 +1738,12 @@ static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) } static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1752,12 +1752,12 @@ static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) } static int codegen_PFMAX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1766,12 +1766,12 @@ static int codegen_PFMAX(codeblock_t *block, uop_t *uop) } static int codegen_PFMIN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1780,12 +1780,12 @@ static int codegen_PFMIN(codeblock_t *block, uop_t *uop) } static int codegen_PFMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1800,9 +1800,9 @@ static int codegen_PFRCP(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { /*TODO: This could be improved (use VRECPE/VRECPS)*/ - host_arm_FMOV_S_ONE(block, REG_D_TEMP); - host_arm_FDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); - host_arm_DUP_V2S(block, dest_reg, dest_reg, 0); + host_arm64_FMOV_S_ONE(block, REG_V_TEMP); + host_arm64_FDIV_S(block, dest_reg, REG_V_TEMP, src_reg_a); + host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); } else fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); @@ -1817,10 +1817,10 @@ static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ - host_arm_FSQRT_S(block, REG_D_TEMP, src_reg_a); - host_arm_FMOV_S_ONE(block, REG_D_TEMP); - host_arm_FDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); - host_arm_DUP_V2S(block, dest_reg, dest_reg, 0); + host_arm64_FSQRT_S(block, REG_V_TEMP, src_reg_a); + host_arm64_FMOV_S_ONE(block, REG_V_TEMP); + host_arm64_FDIV_S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); } else fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); @@ -1834,7 +1834,7 @@ static int codegen_PFSUB(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); } else fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 3e17433..f402c49 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -96,8 +96,9 @@ #define OPCODE_VCMP_D 0xeeb40b40 #define OPCODE_VCVT_D_IS 0xeeb80bc0 #define OPCODE_VCVT_D_S 0xeeb70ac0 +#define OPCODE_VCVT_F32_S32 0xf3bb0700 #define OPCODE_VCVT_IS_D 0xeebd0bc0 -#define OPCODE_VCVT_S32_F32 0xf3bb0680 +#define OPCODE_VCVT_S32_F32 0xf3bb0600 #define OPCODE_VCVT_S_D 0xeeb70bc0 #define OPCODE_VCVTR_IS_D 0xeebd0b40 #define OPCODE_VDIV 0xee800b00 @@ -156,6 +157,7 @@ #define OPCODE_VSUB_I8 0xf3000800 #define OPCODE_VSUB_I16 0xf3100800 #define OPCODE_VSUB_I32 0xf3200800 +#define OPCODE_VSUB_F32 0xf3000d00 #define OPCODE_VZIP_D8 0xf3b20180 #define OPCODE_VZIP_D16 0xf3b60180 #define OPCODE_VZIP_D32 0xf3ba0080 @@ -932,6 +934,10 @@ void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VCVT_F32_S32 | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); @@ -1006,7 +1012,7 @@ void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) } void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(dst_reg)); } void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { @@ -1198,6 +1204,10 @@ void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, COND_AL | OPCODE_VSUB_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VSUB_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 94d9a9b..3e930df 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -166,12 +166,14 @@ void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm); void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); @@ -235,6 +237,7 @@ void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset); void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index e65816f..59efc56 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1823,8 +1823,8 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) } static int codegen_PFADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1837,8 +1837,8 @@ static int codegen_PFADD(codeblock_t *block, uop_t *uop) } static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1851,8 +1851,8 @@ static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) } static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1865,8 +1865,8 @@ static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) } static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1879,8 +1879,8 @@ static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) } static int codegen_PFMAX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1893,8 +1893,8 @@ static int codegen_PFMAX(codeblock_t *block, uop_t *uop) } static int codegen_PFMIN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1907,8 +1907,8 @@ static int codegen_PFMIN(codeblock_t *block, uop_t *uop) } static int codegen_PFMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { @@ -1975,7 +1975,7 @@ static int codegen_PI2FD(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { - host_arm_VCVT_Q_F32_IS(block, dest_reg, src_reg_a); + host_arm_VCVT_F32_S32(block, dest_reg, src_reg_a); } else fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); From 966e74261b4aefae1ec18c6c49112aeb67b4e378 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 12 Jan 2019 15:17:11 +0000 Subject: [PATCH 096/181] Update Makefile.am. --- src/Makefile.am | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d465e30..f098a4d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,12 +24,12 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_accumulate.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_arith.c codegen_ops_jump.c codegen_ops_logic.c \ -codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \ +cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \ +codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ -hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ +hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c ide_sff8038i.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ -laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \ +laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c mvp3.c neat.c nmi.c nvr.c olivetti_m24.c \ opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \ serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c sound_emu8k.c sound_gus.c \ sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ @@ -40,8 +40,9 @@ vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vi vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c \ vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c \ vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \ -vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c \ -x86seg.c x87.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc +vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c vt82c586b.c \ +w83877tf.c x86seg.c x87.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc \ +codegen_ops_mmx_arith.c codegen_ops_mmx_cmp.c codegen_ops_mmx_loadstore.c codegen_ops_mmx_logic.c codegen_ops_mmx_pack.c codegen_ops_mmx_shift.c # DOSBox pcem_SOURCES += dosbox/cdrom_image.cpp dosbox/dbopl.cpp dosbox/nukedopl.cpp dosbox/vid_cga_comp.c From 8998024225b4e122d42d81c46396e1d309932ea9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 13 Jan 2019 12:57:32 +0000 Subject: [PATCH 097/181] Move GPF and early exit routines out of individual code blocks and into the common helper block. --- src/codegen.c | 4 +- src/codegen_backend_arm.c | 84 +++++++++++++++---------------- src/codegen_backend_arm.h | 5 +- src/codegen_backend_arm64.c | 43 ++++++++-------- src/codegen_backend_arm64.h | 3 -- src/codegen_backend_arm64_defs.h | 5 +- src/codegen_backend_arm64_ops.c | 7 ++- src/codegen_backend_arm64_uops.c | 30 +++++------ src/codegen_backend_arm_defs.h | 5 +- src/codegen_backend_arm_ops.c | 6 +++ src/codegen_backend_arm_uops.c | 30 +++++------ src/codegen_backend_x86-64.c | 56 ++++++++++----------- src/codegen_backend_x86-64.h | 5 +- src/codegen_backend_x86-64_defs.h | 3 ++ src/codegen_backend_x86-64_uops.c | 30 +++++------ src/codegen_backend_x86.c | 30 ++++------- src/codegen_backend_x86.h | 5 +- src/codegen_backend_x86_defs.h | 3 ++ src/codegen_backend_x86_uops.c | 30 +++++------ src/codegen_ops_branch.c | 44 ++++++++-------- src/codegen_ops_shift.c | 6 +-- 21 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 5e3bc13..3db8d60 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -61,7 +61,7 @@ void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg) if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) return; - uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, &block->data[BLOCK_GPF_OFFSET]); + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout); seg->checked = 1; } @@ -78,7 +78,7 @@ void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) return; - uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, &block->data[BLOCK_GPF_OFFSET]); + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout); seg->checked = 1; } diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index bb861ae..fc77eba 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -35,6 +35,9 @@ void *codegen_mem_store_double; void *codegen_fp_round; +void *codegen_gpf_rout; +void *codegen_exit_rout; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_R4, @@ -78,6 +81,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) LDRB R1, cpu_state.abrt LDR PC, [SP], #4 */ + codegen_alloc(block, 80); host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12); host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2); host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2); @@ -107,9 +111,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm_MOV_IMM(block, REG_R1, 0); host_arm_MOV_REG(block, REG_PC, REG_LR); - *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; if (size != 1) - *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; + *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); if (size == 1) host_arm_BL(block, (uintptr_t)readmemb386l); @@ -149,6 +153,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) LDRB R1, cpu_state.abrt LDR PC, [SP], #4 */ + codegen_alloc(block, 80); host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12); host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2); host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2); @@ -178,9 +183,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm_MOV_IMM(block, REG_R1, 0); host_arm_MOV_REG(block, REG_PC, REG_LR); - *branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; if (size != 1) - *misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; + *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); if (size == 4 && is_float) host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); @@ -202,30 +207,30 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) static void build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + codegen_mem_load_byte = &block_write_data[block_pos]; build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + codegen_mem_load_word = &block_write_data[block_pos]; build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + codegen_mem_load_long = &block_write_data[block_pos]; build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + codegen_mem_load_quad = &block_write_data[block_pos]; build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + codegen_mem_load_single = &block_write_data[block_pos]; build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + codegen_mem_load_double = &block_write_data[block_pos]; build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + codegen_mem_store_byte = &block_write_data[block_pos]; build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + codegen_mem_store_word = &block_write_data[block_pos]; build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + codegen_mem_store_long = &block_write_data[block_pos]; build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + codegen_mem_store_quad = &block_write_data[block_pos]; build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + codegen_mem_store_single = &block_write_data[block_pos]; build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + codegen_mem_store_double = &block_write_data[block_pos]; build_store_routine(block, 8, 1); } @@ -239,23 +244,25 @@ static void build_fp_round_routine(codeblock_t *block) { uint32_t *jump_table; + codegen_alloc(block, 80); + host_arm_MOV_REG(block, REG_TEMP2, REG_LR); host_arm_MOV_REG(block, REG_LR, REG_TEMP2); host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); host_arm_NOP(block); - jump_table = (uint32_t *)&block->data[block_pos]; + jump_table = (uint32_t *)&block_write_data[block_pos]; host_arm_NOP(block); host_arm_NOP(block); host_arm_NOP(block); host_arm_NOP(block); - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even + jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf + jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP); @@ -264,7 +271,7 @@ static void build_fp_round_routine(codeblock_t *block) host_arm_VMSR_FPSCR(block, REG_TEMP); host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf + jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN); @@ -273,7 +280,7 @@ static void build_fp_round_routine(codeblock_t *block) host_arm_VMSR_FPSCR(block, REG_TEMP); host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero + jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); host_arm_MOV_REG(block, REG_PC, REG_LR); } @@ -282,12 +289,6 @@ void codegen_backend_init() { codeblock_t *block; int c; -#if defined(__linux__) || defined(__APPLE__) - void *start; - size_t len; - long pagesize = sysconf(_SC_PAGESIZE); - long pagemask = ~(pagesize - 1); -#endif codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); @@ -309,11 +310,21 @@ void codegen_backend_init() build_loadstore_routines(&codeblock[block_current]); printf("block_pos=%i\n", block_pos); - codegen_fp_round = &codeblock[block_current].data[block_pos]; + codegen_fp_round = &block_write_data[block_pos]; build_fp_round_routine(&codeblock[block_current]); - block_write_data = NULL; + codegen_alloc(block, 80); + codegen_gpf_rout = &block_write_data[block_pos]; + host_arm_MOV_IMM(block, REG_R0, 0); + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_call(block, x86gpf); + codegen_exit_rout = &block_write_data[block_pos]; + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); + + block_write_data = NULL; +//fatal("block_pos=%i\n", block_pos); asm("vmrs %0, fpscr\n" : "=r" (cpu_state.old_fp_control) ); @@ -331,20 +342,7 @@ void codegen_set_rounding_mode(int mode) /*R10 - cpu_state*/ void codegen_backend_prologue(codeblock_t *block) { - block_pos = 0; - - block_pos = BLOCK_GPF_OFFSET; - host_arm_MOV_IMM(block, REG_R0, 0); - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_call(block, x86gpf); - while (block_pos != BLOCK_EXIT_OFFSET) - host_arm_nop(block); - - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - while (block_pos != BLOCK_START) - host_arm_nop(block); + block_pos = BLOCK_START; /*Entry code*/ diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index f8b330b..cc4a642 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -9,9 +9,6 @@ #define HASH(l) ((l) & 0x1ffff) -#define BLOCK_GPF_OFFSET 0 -#define BLOCK_EXIT_OFFSET 32 - #define BLOCK_MAX 0x3c0 void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); @@ -23,3 +20,5 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm void host_arm_call(codeblock_t *block, void *dst_addr); void host_arm_nop(codeblock_t *block); + +void codegen_alloc(codeblock_t *block, int size); \ No newline at end of file diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index ba08ca8..4a2885a 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -36,6 +36,9 @@ void *codegen_mem_store_double; void *codegen_fp_round; void *codegen_fp_round_quad; +void *codegen_gpf_rout; +void *codegen_exit_rout; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_X19, @@ -308,8 +311,25 @@ void codegen_backend_init() codegen_fp_round_quad = &block_write_data[block_pos]; build_fp_round_routine(block, 1); + codegen_alloc(block, 80); + codegen_gpf_rout = &block_write_data[block_pos]; + host_arm64_mov_imm(block, REG_ARG0, 0); + host_arm64_mov_imm(block, REG_ARG1, 0); + host_arm64_call(block, x86gpf); + + codegen_exit_rout = &block_write_data[block_pos]; + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_RET(block, REG_X30); + block_write_data = NULL; + codegen_allocator_clean_blocks(block->head_mem_block); + asm("mrs %0, fpcr\n" : "=r" (cpu_state.old_fp_control) ); @@ -325,28 +345,7 @@ void codegen_set_rounding_mode(int mode) /*R10 - cpu_state*/ void codegen_backend_prologue(codeblock_t *block) { - int offset; - - block_pos = 0; - - block_pos = BLOCK_GPF_OFFSET; - host_arm64_mov_imm(block, REG_ARG0, 0); - host_arm64_mov_imm(block, REG_ARG1, 0); - host_arm64_call(block, x86gpf); - while (block_pos != BLOCK_EXIT_OFFSET) - host_arm64_NOP(block); - - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); - host_arm64_RET(block, REG_X30); - - while (block_pos != BLOCK_START) - host_arm64_NOP(block); + block_pos = BLOCK_START; /*Entry code*/ diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h index 74586fb..cd506e1 100644 --- a/src/codegen_backend_arm64.h +++ b/src/codegen_backend_arm64.h @@ -9,9 +9,6 @@ #define HASH(l) ((l) & 0x1ffff) -#define BLOCK_GPF_OFFSET 0 -#define BLOCK_EXIT_OFFSET 32 - #define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index cd771cb..a265016 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -129,4 +129,7 @@ extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; extern void *codegen_fp_round; -extern void *codegen_fp_round_quad; \ No newline at end of file +extern void *codegen_fp_round_quad; + +extern void *codegen_gpf_rout; +extern void *codegen_exit_rout; \ No newline at end of file diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index f253a4c..0a7e24d 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -599,9 +599,14 @@ void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) { - int offset = dest - (uintptr_t)&block_write_data[block_pos]; + int offset; + + codegen_alloc(block, 4); + offset = dest - (uintptr_t)&block_write_data[block_pos]; if (offset_is_19bit(offset)) + { codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + } else { codegen_alloc(block, 12); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index fd89d84..48f748b 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -242,7 +242,7 @@ static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_arm64_call(block, uop->p); - host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); return 0; } @@ -777,7 +777,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); host_arm64_mov_imm(block, REG_ARG0, 7); host_arm64_call(block, x86_int); - host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm64_B(block, codegen_exit_rout); host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); @@ -798,7 +798,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); host_arm64_mov_imm(block, REG_ARG0, 7); host_arm64_call(block, x86_int); - host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]); + host_arm64_B(block, codegen_exit_rout); host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); @@ -883,7 +883,7 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t)uop->p); host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); host_arm64_call(block, (void *)loadseg); - host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); return 0; } @@ -908,7 +908,7 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) } else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); if (REG_IS_B(dest_size)) { host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); @@ -954,7 +954,7 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) } else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); if (REG_IS_B(dest_size)) { host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); @@ -990,7 +990,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) if (uop->imm_data) host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); host_arm64_call(block, codegen_mem_load_double); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); return 0; @@ -1007,7 +1007,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) if (uop->imm_data) host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); host_arm64_call(block, codegen_mem_load_single); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); host_arm64_FCVT_D_S(block, dest_reg, REG_V_TEMP); return 0; @@ -1041,7 +1041,7 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) } else fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } @@ -1080,7 +1080,7 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) } else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } @@ -1092,7 +1092,7 @@ static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); host_arm64_mov_imm(block, REG_W1, uop->imm_data); host_arm64_call(block, codegen_mem_store_byte); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } @@ -1103,7 +1103,7 @@ static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); host_arm64_mov_imm(block, REG_W1, uop->imm_data); host_arm64_call(block, codegen_mem_store_word); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } @@ -1114,7 +1114,7 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); host_arm64_mov_imm(block, REG_W1, uop->imm_data); host_arm64_call(block, codegen_mem_store_long); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } @@ -1132,7 +1132,7 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); host_arm64_FCVT_S_D(block, REG_V_TEMP, src_reg); host_arm64_call(block, codegen_mem_store_single); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } @@ -1149,7 +1149,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); host_arm64_call(block, codegen_mem_store_double); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); return 0; } diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index def8970..2f50129 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -83,4 +83,7 @@ extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; -extern void *codegen_fp_round; \ No newline at end of file +extern void *codegen_fp_round; + +extern void *codegen_gpf_rout; +extern void *codegen_exit_rout; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index f402c49..17355cc 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -230,6 +230,12 @@ static inline void codegen_alloc_4(codeblock_t *block) codegen_allocate_new_block(block); } +void codegen_alloc(codeblock_t *block, int size) +{ + if (block_pos >= (BLOCK_MAX-size)) + codegen_allocate_new_block(block); +} + static inline uint32_t arm_data_offset(int offset) { if (offset < -0xffc || offset > 0xffc) diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 59efc56..5160511 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -317,7 +317,7 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_arm_call(block, uop->p); host_arm_TST_REG(block, REG_R0, REG_R0); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -848,7 +848,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); host_arm_MOV_IMM(block, REG_ARG0, 7); host_arm_call(block, x86_int); - host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_B(block, (uintptr_t)codegen_exit_rout); *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; @@ -869,7 +869,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); host_arm_MOV_IMM(block, REG_ARG0, 7); host_arm_call(block, x86_int); - host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_B(block, (uintptr_t)codegen_exit_rout); *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; @@ -951,7 +951,7 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) host_arm_MOV_IMM(block, REG_ARG1, (uint32_t)uop->p); host_arm_call(block, loadseg); host_arm_TST_REG(block, REG_R0, REG_R0); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -977,7 +977,7 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); if (REG_IS_B(dest_size)) { host_arm_BFI(block, dest_reg, REG_R0, 0, 8); @@ -1025,7 +1025,7 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); if (REG_IS_B(dest_size)) { host_arm_BFI(block, dest_reg, REG_R0, 0, 8); @@ -1062,7 +1062,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); host_arm_BL(block, (uintptr_t)codegen_mem_load_single); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); host_arm_VCVT_D_S(block, dest_reg, REG_D_TEMP); return 0; @@ -1080,7 +1080,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); host_arm_BL(block, (uintptr_t)codegen_mem_load_double); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); return 0; @@ -1110,7 +1110,7 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) else fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -1151,7 +1151,7 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -1164,7 +1164,7 @@ static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) host_arm_MOV_IMM(block, REG_R1, uop->imm_data); host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -1176,7 +1176,7 @@ static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) host_arm_MOV_IMM(block, REG_R1, uop->imm_data); host_arm_BL(block, (uintptr_t)codegen_mem_store_word); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -1188,7 +1188,7 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) host_arm_MOV_IMM(block, REG_R1, uop->imm_data); host_arm_BL(block, (uintptr_t)codegen_mem_store_long); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -1206,7 +1206,7 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) host_arm_VCVT_S_D(block, REG_D_TEMP, src_reg); host_arm_BL(block, (uintptr_t)codegen_mem_store_single); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } @@ -1224,7 +1224,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); host_arm_BL(block, (uintptr_t)codegen_mem_store_double); host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); return 0; } diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 86ed609..fff5942 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -31,6 +31,9 @@ void *codegen_mem_store_quad; void *codegen_mem_store_single; void *codegen_mem_store_double; +void *codegen_gpf_rout; +void *codegen_exit_rout; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_EAX, @@ -49,8 +52,6 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = REG_XMM6 }; -static void *mem_abrt_rout; - static void build_load_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; @@ -274,6 +275,7 @@ static void build_loadstore_routines(codeblock_t *block) void codegen_backend_init() { + codeblock_t *block; int c; #if defined(__linux__) || defined(__APPLE__) void *start; @@ -295,10 +297,33 @@ void codegen_backend_init() block_current = 0; block_pos = 0; + block = &codeblock[block_current]; codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL); codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); block_write_data = codeblock[block_current].data; build_loadstore_routines(&codeblock[block_current]); + + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; +#if WIN64 + host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX, REG_ECX); + host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX, REG_EDX); +#else + host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI, REG_EDI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); +#endif + host_x86_CALL(block, (uintptr_t)x86gpf); + codegen_exit_rout = &codeblock[block_current].data[block_pos]; + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); + block_write_data = NULL; asm( @@ -315,33 +340,6 @@ void codegen_set_rounding_mode(int mode) void codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_GPF_OFFSET; -#if WIN64 - host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX, REG_ECX); - host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX, REG_EDX); -#else - host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI, REG_EDI); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); -#endif - host_x86_CALL(block, (uintptr_t)x86gpf); - while (block_pos < BLOCK_EXIT_OFFSET) - host_x86_NOP(block); - if (block_pos > BLOCK_EXIT_OFFSET) - fatal("block_pos > BLOCK_EXIT_OFFSET\n"); - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); - host_x86_POP(block, REG_R15); - host_x86_POP(block, REG_R14); - host_x86_POP(block, REG_R13); - host_x86_POP(block, REG_R12); - host_x86_POP(block, REG_RDI); - host_x86_POP(block, REG_RSI); - host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); - host_x86_RET(block); - if (block_pos > BLOCK_START) - fatal("block_pos > BLOCK_START\n"); - block_pos = BLOCK_START; /*Entry code*/ host_x86_PUSH(block, REG_RBX); host_x86_PUSH(block, REG_RBP); diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h index de52c3c..150c8c8 100644 --- a/src/codegen_backend_x86-64.h +++ b/src/codegen_backend_x86-64.h @@ -2,14 +2,11 @@ #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff -#define BLOCK_START 40 +#define BLOCK_START 0 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff #define HASH(l) ((l) & 0x1ffff) -#define BLOCK_EXIT_OFFSET 20 -#define BLOCK_GPF_OFFSET 0 - #define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h index 7f93633..95a5294 100644 --- a/src/codegen_backend_x86-64_defs.h +++ b/src/codegen_backend_x86-64_defs.h @@ -60,3 +60,6 @@ extern void *codegen_mem_store_long; extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; + +extern void *codegen_gpf_rout; +extern void *codegen_exit_rout; diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index e49fe7f..79bfed3 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -197,7 +197,7 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -727,7 +727,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, REG_EDI, 7); #endif host_x86_CALL(block, x86_int); - host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JMP(block, codegen_exit_rout); *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; return 0; @@ -746,7 +746,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, REG_EDI, 7); #endif host_x86_CALL(block, x86_int); - host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JMP(block, codegen_exit_rout); *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); @@ -842,7 +842,7 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) #endif host_x86_CALL(block, (void *)loadseg); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -868,7 +868,7 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) { host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); @@ -911,7 +911,7 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) { host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); @@ -944,7 +944,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); return 0; @@ -962,7 +962,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); return 0; @@ -992,7 +992,7 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) else fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1005,7 +1005,7 @@ static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); host_x86_CALL(block, codegen_mem_store_byte); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1017,7 +1017,7 @@ static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); host_x86_CALL(block, codegen_mem_store_word); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1029,7 +1029,7 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); host_x86_CALL(block, codegen_mem_store_long); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1065,7 +1065,7 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1084,7 +1084,7 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1102,7 +1102,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 68d9a36..982f69d 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -32,6 +32,9 @@ void *codegen_mem_store_quad; void *codegen_mem_store_single; void *codegen_mem_store_double; +void *codegen_gpf_rout; +void *codegen_exit_rout; + int codegen_host_reg_list[CODEGEN_HOST_REGS] = { REG_EAX, @@ -49,8 +52,6 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = REG_XMM5 }; -static void *mem_abrt_rout; - static void build_load_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; @@ -301,16 +302,19 @@ pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); block->head_mem_block = codegen_allocator_allocate(NULL); block->data = codeblock_allocator_get_ptr(block->head_mem_block); block_write_data = block->data; - mem_abrt_rout = &block->data[block_pos]; - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x10+4); + build_loadstore_routines(block); + + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); + host_x86_CALL(block, (void *)x86gpf); + codegen_exit_rout = &codeblock[block_current].data[block_pos]; + host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); host_x86_POP(block, REG_EDI); host_x86_POP(block, REG_ESI); host_x86_POP(block, REG_EBP); host_x86_POP(block, REG_EDX); host_x86_RET(block); - - block_pos = 64; - build_loadstore_routines(block); block_write_data = NULL; cpu_state.old_fp_control = 0; @@ -333,18 +337,6 @@ void codegen_set_rounding_mode(int mode) void codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_GPF_OFFSET; - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); - host_x86_CALL(block, (void *)x86gpf); - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); - host_x86_POP(block, REG_EDI); - host_x86_POP(block, REG_ESI); - host_x86_POP(block, REG_EBP); - host_x86_POP(block, REG_EDX); - host_x86_RET(block); - block_pos = BLOCK_START; /*Entry code*/ host_x86_PUSH(block, REG_EBX); host_x86_PUSH(block, REG_EBP); diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h index 52df734..7e32927 100644 --- a/src/codegen_backend_x86.h +++ b/src/codegen_backend_x86.h @@ -2,14 +2,11 @@ #define BLOCK_SIZE 0x4000 #define BLOCK_MASK 0x3fff -#define BLOCK_START 32 +#define BLOCK_START 0 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff #define HASH(l) ((l) & 0x1ffff) -#define BLOCK_EXIT_OFFSET 20 -#define BLOCK_GPF_OFFSET 0 - #define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h index 0c9eb1d..8999ca3 100644 --- a/src/codegen_backend_x86_defs.h +++ b/src/codegen_backend_x86_defs.h @@ -39,6 +39,9 @@ extern void *codegen_mem_store_quad; extern void *codegen_mem_store_single; extern void *codegen_mem_store_double; +extern void *codegen_gpf_rout; +extern void *codegen_exit_rout; + #define STACK_ARG0 (0) #define STACK_ARG1 (4) #define STACK_ARG2 (8) diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index b0a54af..9882f82 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -203,7 +203,7 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, uop->p); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); // host_x86_CALL(block, codegen_debug); return 0; @@ -730,7 +730,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); host_x86_CALL(block, x86_int); - host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JMP(block, codegen_exit_rout); *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; return 0; @@ -746,7 +746,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); host_x86_CALL(block, x86_int); - host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JMP(block, codegen_exit_rout); *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0); host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0); @@ -831,7 +831,7 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t)uop->p); host_x86_CALL(block, loadseg); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -857,7 +857,7 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) { host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); @@ -900,7 +900,7 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) { host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); @@ -933,7 +933,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); return 0; @@ -952,7 +952,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); return 0; @@ -982,7 +982,7 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) else fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1018,7 +1018,7 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1031,7 +1031,7 @@ static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); host_x86_CALL(block, codegen_mem_store_byte); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1043,7 +1043,7 @@ static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); host_x86_CALL(block, codegen_mem_store_word); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1055,7 +1055,7 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); host_x86_CALL(block, codegen_mem_store_long); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1074,7 +1074,7 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } @@ -1092,7 +1092,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]); + host_x86_JNZ(block, codegen_exit_rout); return 0; } diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index d62e1e5..e5a34fd 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -48,7 +48,7 @@ static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -60,7 +60,7 @@ static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Overflow is always zero*/ uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); return; case FLAGS_SUB8: case FLAGS_DEC8: @@ -82,7 +82,7 @@ static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } @@ -115,7 +115,7 @@ static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -127,7 +127,7 @@ static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Carry is always zero*/ uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); return; case FLAGS_SUB8: @@ -149,7 +149,7 @@ static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } @@ -167,7 +167,7 @@ static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -184,7 +184,7 @@ void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } @@ -220,7 +220,7 @@ static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -253,7 +253,7 @@ static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); @@ -305,7 +305,7 @@ static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -354,7 +354,7 @@ static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } @@ -365,7 +365,7 @@ static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -375,7 +375,7 @@ static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } @@ -414,7 +414,7 @@ static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -452,7 +452,7 @@ static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } @@ -484,7 +484,7 @@ static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) @@ -513,7 +513,7 @@ static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, break; } uop_MOV_IMM(ir, IREG_pc, base_pc + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); @@ -570,7 +570,7 @@ uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet else jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); return op_pc+1; @@ -592,7 +592,7 @@ uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); return op_pc+1; @@ -623,7 +623,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); } uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); @@ -654,7 +654,7 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); } uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); - uop_JMP(ir, &block->data[BLOCK_EXIT_OFFSET]); + uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); diff --git a/src/codegen_ops_shift.c b/src/codegen_ops_shift.c index 90547d1..d4b5b56 100644 --- a/src/codegen_ops_shift.c +++ b/src/codegen_ops_shift.c @@ -362,7 +362,7 @@ uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch return 0; uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); if ((fetchdat & 0xc0) == 0xc0) { @@ -453,7 +453,7 @@ uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet return 0; uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); if ((fetchdat & 0xc0) == 0xc0) { @@ -544,7 +544,7 @@ uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet return 0; uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, &block->data[BLOCK_EXIT_OFFSET]); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); if ((fetchdat & 0xc0) == 0xc0) { From ac886c420f720725e7eac60db207ccbe0d3377e3 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 13 Jan 2019 12:58:07 +0000 Subject: [PATCH 098/181] Increase ARMv7 and v8 code block count to the normal default of 16384, now that this no longer leads to a massive increase in memory usage. --- src/codegen_backend_arm.h | 6 +++--- src/codegen_backend_arm64.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h index cc4a642..bfd5206 100644 --- a/src/codegen_backend_arm.h +++ b/src/codegen_backend_arm.h @@ -1,8 +1,8 @@ #include "codegen_backend_arm_defs.h" -#define BLOCK_SIZE 0x1000 -#define BLOCK_MASK 0x0fff -#define BLOCK_START 64 +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h index cd506e1..1fb0cfb 100644 --- a/src/codegen_backend_arm64.h +++ b/src/codegen_backend_arm64.h @@ -1,8 +1,8 @@ #include "codegen_backend_arm64_defs.h" -#define BLOCK_SIZE 0x1000 -#define BLOCK_MASK 0x0fff -#define BLOCK_START 64 +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 #define HASH_SIZE 0x20000 #define HASH_MASK 0x1ffff From 178c9d5c1549ba8b8d56d64e13f9c6089f583445 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 16 Jan 2019 21:54:10 +0000 Subject: [PATCH 099/181] Don't write back temporary registers if they won't be read again. --- src/codegen_reg.c | 170 +++++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 77 deletions(-) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index c222d04..7c74153 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -45,109 +45,120 @@ enum REG_FP }; +enum +{ + /*Register may be accessed outside of code block, and must be written + back before any control transfers*/ + REG_PERMANENT = 0, + /*Register will not be accessed outside of code block, and does not need + to be written back if there are no readers remaining*/ + REG_VOLATILE = 1 +}; + struct { int native_size; void *p; int type; + int is_volatile; } ireg_data[IREG_COUNT] = { - [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER}, - [IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER}, - [IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER}, - [IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER}, - [IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER}, - [IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER}, - [IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER}, - [IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER}, + [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT}, + [IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT}, + [IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT}, + [IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT}, + [IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT}, + [IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT}, + [IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT}, + [IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER}, - [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER}, - [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER}, - [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER}, + [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT}, - [IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER}, - [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER}, + [IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT}, + [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT}, - [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER}, - [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER}, + [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, + [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT}, - [IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER}, - [IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER}, + [IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT}, + [IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT}, - [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER}, + [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT}, - [IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER}, - [IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER}, + [IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER, REG_PERMANENT}, + [IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER}, - [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER}, - [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER}, - [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER}, - [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER}, - [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER}, + [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER}, - [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER}, - [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER}, - [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER}, - [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER}, - [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER}, + [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER}, + [IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT}, - [IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, - [IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP}, + [IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, - [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER}, + [IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP}, + [IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP}, - [IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP}, - [IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP}, - [IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP}, - [IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP}, - [IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP}, - [IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP}, - [IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP}, + [IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT}, + [IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT}, + [IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT}, + [IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT}, + [IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT}, + [IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT}, + [IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT}, - [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER}, - [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER}, + [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT}, + [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT}, - [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER}, - [IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER}, + [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT}, + [IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT}, /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ - [IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER}, - [IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER}, - [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER}, - [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER}, + [IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER, REG_VOLATILE}, + [IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER, REG_VOLATILE}, + [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER, REG_VOLATILE}, + [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER, REG_VOLATILE}, - [IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP}, - [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP}, + [IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP, REG_VOLATILE}, + [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE}, }; static int reg_is_native_size(ir_reg_t ir_reg) @@ -317,6 +328,10 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); void *p = ireg_data[ir_reg].p; + if (!reg_version_refcount[ir_reg][reg_set->regs[c].version] && + ireg_data[ir_reg].is_volatile) + return; + switch (ireg_data[ir_reg].native_size) { case REG_BYTE: @@ -520,7 +535,7 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in // pclog(" already loaded %i\n", c); reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]--; - if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] < 0) + if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == (uint8_t)-1) fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); if (host_reg_idx) @@ -541,6 +556,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; parent_reg.version = ir_reg.version - 1; + reg_version_refcount[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1]++; codegen_reg_alloc_read_reg(block, parent_reg, &c); From 13087d0031d17752c8a8cdca9d066c9b81755a83 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 17 Jan 2019 18:05:27 +0000 Subject: [PATCH 100/181] Added missing codegen allocator files --- src/codegen_allocator.c | 117 ++++++++++++++++++++++++++++++++++++++++ src/codegen_allocator.h | 38 +++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 src/codegen_allocator.c create mode 100644 src/codegen_allocator.h diff --git a/src/codegen_allocator.c b/src/codegen_allocator.c new file mode 100644 index 0000000..3dba230 --- /dev/null +++ b/src/codegen_allocator.c @@ -0,0 +1,117 @@ +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +#include "ibm.h" +#include "codegen.h" +#include "codegen_allocator.h" + +typedef struct mem_block_t +{ + uint32_t offset; /*Offset into mem_block_alloc*/ + uint32_t next; +} mem_block_t; + +static mem_block_t mem_blocks[MEM_BLOCK_NR]; +static uint32_t mem_block_free_list; +static uint8_t *mem_block_alloc = NULL; + +int codegen_allocator_usage = 0; + +void codegen_allocator_init() +{ + int c; + +#if defined WIN32 || defined _WIN32 || defined _WIN32 + mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0); +#endif + + for (c = 0; c < MEM_BLOCK_NR; c++) + { + mem_blocks[c].offset = c * MEM_BLOCK_SIZE; + if (c < MEM_BLOCK_NR-1) + mem_blocks[c].next = c+2; + else + mem_blocks[c].next = 0; + } + mem_block_free_list = 1; +} + +mem_block_t *codegen_allocator_allocate(mem_block_t *parent) +{ + mem_block_t *block; + uint32_t block_nr; + + while (!mem_block_free_list) + { + codegen_delete_random_block(); + } +// fatal("codegen_allocator_allocate: free list empty!\n"); + + /*Remove from free list*/ + block_nr = mem_block_free_list; + block = &mem_blocks[block_nr-1]; + mem_block_free_list = block->next; + + if (parent) + { + /*Add to parent list*/ + block->next = parent->next; + parent->next = block_nr; + } + else + block->next = 0; + + codegen_allocator_usage++; +/* if (parent) + pclog("codegen_allocator_allocate with parent: %p %i %i %p\n", block, block_nr, codegen_allocator_usage, parent); + else + pclog("codegen_allocator_allocate: %p %i %i\n", block, block_nr, codegen_allocator_usage);*/ + return block; +} +void codegen_allocator_free(mem_block_t *block) +{ + int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1; + +// pclog("codegen_allocator_free: %p %i %i %i\n", block, block_nr, codegen_allocator_usage, block->next); + while (1) + { + int next_block_nr = block->next; +// pclog(" free next=%i\n", next_block_nr); + codegen_allocator_usage--; + + block->next = mem_block_free_list; + mem_block_free_list = block_nr; + block_nr = next_block_nr; + + if (block_nr) + block = &mem_blocks[block_nr - 1]; + else + break; + } +} + +uint8_t *codeblock_allocator_get_ptr(mem_block_t *block) +{ + return &mem_block_alloc[block->offset]; +} + +void codegen_allocator_clean_blocks(struct mem_block_t *block) +{ +#if defined __ARM_EABI__ || defined __aarch64__ + while (1) + { + __clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]); + if (block->next) + block = &mem_blocks[block->next - 1]; + else + break; + } +#endif +} diff --git a/src/codegen_allocator.h b/src/codegen_allocator.h new file mode 100644 index 0000000..22504bf --- /dev/null +++ b/src/codegen_allocator.h @@ -0,0 +1,38 @@ +#ifndef _CODEGEN_ALLOCATOR_H_ +#define _CODEGEN_ALLOCATOR_H_ + +/*The allocator handles all allocation of executable memory. Since the two-pass + recompiler design makes applying hard limits to codeblock size difficult, the + allocator allows memory to be provided as and when required. + + The allocator provides a block size of a little under 1 kB (slightly lower to + limit cache aliasing). Each generated codeblock is allocated one block by default, + and will allocate additional block(s) once the existing memory is sorted. Blocks + are chained together by jump instructions. + + Due to the chaining, the total memory size is limited by the range of a jump + instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to + +/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/ +#ifdef __ARM_EABI__ +#define MEM_BLOCK_NR 32768 +#else +#define MEM_BLOCK_NR 65536 +#endif + +#define MEM_BLOCK_SIZE 0x3c0 + +void codegen_allocator_init(); +/*Allocate a mem_block_t, and the associated backing memory. + If parent is non-NULL, then the new block will be added to the list in + parent->next*/ +struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent); +/*Free a mem_block_t, and any subsequent blocks in the list at block->next*/ +void codegen_allocator_free(struct mem_block_t *block); +/*Get a pointer to the backing memory associated with block*/ +uint8_t *codeblock_allocator_get_ptr(struct mem_block_t *block); +/*Cache clean memory block list*/ +void codegen_allocator_clean_blocks(struct mem_block_t *block); + +extern int codegen_allocator_usage; + +#endif From 57579cdd0762f53d22bf6abe8fb52970df5f964f Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 19 Jan 2019 18:05:27 +0000 Subject: [PATCH 101/181] Add dummy USB and ACPI implementations to VT82C586B. Windows 2000 and XP now work on FIC VA-503+. --- src/vt82c586b.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/vt82c586b.c b/src/vt82c586b.c index 34a064b..2540d5c 100644 --- a/src/vt82c586b.c +++ b/src/vt82c586b.c @@ -20,8 +20,22 @@ static struct uint8_t sysctrl; sff_busmaster_t busmaster[2]; + + struct + { + uint16_t io_base; + } usb; + struct + { + uint16_t io_base; + } power; } vt82c586b; +#define ACPI_TIMER_FREQ 3579545 + +#define ACPI_IO_ENABLE (1 << 7) +#define ACPI_TIMER_32BIT (1 << 3) + static uint8_t vt82c586b_read(int func, int addr, void *priv) { switch (func) @@ -157,6 +171,28 @@ static void vt82c586b_ide_write(int addr, uint8_t val) } } } + +static uint8_t usb_reg_read(uint16_t addr, void *p) +{ +// pclog("usb_reg_read: addr=%04x\n", addr); + switch (addr & 0x1f) + { + case 0x10: case 0x11: case 0x12: case 0x13: /*Port status*/ + return 0; + } + return 0xff; +} +static void usb_reg_write(uint16_t addr, uint8_t val, void *p) +{ +// pclog("usb_reg_write: addr=%04x val=%02x\n", addr, val); +} +static void usb_update_io_mapping() +{ + io_removehandler(vt82c586b.usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, NULL); + vt82c586b.usb.io_base = (vt82c586b.usb_regs[0x20] & ~0x1f) | (vt82c586b.usb_regs[0x21] << 8); + if (vt82c586b.usb_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + io_sethandler(vt82c586b.usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, NULL); +} static void vt82c586b_usb_write(int addr, uint8_t val) { /*Read-only addresses*/ @@ -174,6 +210,7 @@ static void vt82c586b_usb_write(int addr, uint8_t val) { case 4: vt82c586b.usb_regs[4] = val & 0x97; + usb_update_io_mapping(); break; case 7: vt82c586b.usb_regs[7] = val & 0x7f; @@ -181,12 +218,38 @@ static void vt82c586b_usb_write(int addr, uint8_t val) case 0x20: vt82c586b.usb_regs[0x20] = (val & ~0x1f) | 1; + usb_update_io_mapping(); + break; + case 0x21: + vt82c586b.usb_regs[0x21] = val; + usb_update_io_mapping(); break; default: vt82c586b.usb_regs[addr] = val; break; } +// pclog(" USB write %02x %02x\n", addr, val); +} + +static uint8_t power_reg_read(uint16_t addr, void *p) +{ + uint32_t timer; + + switch (addr & 0xff) + { + case 0x08: case 0x09: case 0x0a: case 0x0b: /*ACPI timer*/ + timer = (tsc * ACPI_TIMER_FREQ) / cpu_get_speed(); + if (!(vt82c586b.power_regs[0x41] & ACPI_TIMER_32BIT)) + timer &= 0x00ffffff; + return (timer >> (8 * (addr & 3))) & 0xff; + } +// pclog("power_reg_read: addr=%04x\n", addr); + return 0xff; +} +static void power_reg_write(uint16_t addr, uint8_t val, void *p) +{ +// pclog("power_reg_write: addr=%04x val=%02x\n", addr, val); } static void vt82c586b_power_write(int addr, uint8_t val) { @@ -200,6 +263,21 @@ static void vt82c586b_power_write(int addr, uint8_t val) switch (addr) { + case 0x41: + io_removehandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL); + vt82c586b.power_regs[addr] = val; + if (vt82c586b.power_regs[0x41] & ACPI_IO_ENABLE) + io_sethandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL); + break; + + case 0x49: + io_removehandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL); + vt82c586b.power_regs[addr] = val; + vt82c586b.power.io_base = val << 8; + if (vt82c586b.power_regs[0x41] & ACPI_IO_ENABLE) + io_sethandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL); + break; + default: vt82c586b.power_regs[addr] = val; break; From 9c595f4b9b63b4960295d0a18afc554922f4615f Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 19 Jan 2019 18:06:14 +0000 Subject: [PATCH 102/181] Add CMPXCHG8B to the K6 timing model. --- src/codegen_timing_k6.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c index 590e605..8499cfa 100644 --- a/src/codegen_timing_k6.c +++ b/src/codegen_timing_k6.c @@ -1204,7 +1204,7 @@ static const risc86_instruction_t *opcode_timings_0f[256] = &vector_bsx_op, &vector_bsx_op, &load_alux_op, &load_alu_op, /*c0*/ &vector_alux_store_op, &vector_alu_store_op, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, &vector_cmpxchg_op, &bswap_op, &bswap_op, &bswap_op, &bswap_op, &bswap_op, &bswap_op, &bswap_op, &bswap_op, @@ -2330,6 +2330,8 @@ void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint } } + if (!ins_table[opcode]) + fatal("!ins_table opcode=%02x last_prefix=%02x\n", opcode, last_prefix); decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); } From c07a3b5311cc95cc59a434df07110fa9b2be4643 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 19 Jan 2019 18:08:45 +0000 Subject: [PATCH 103/181] Free currently allocated memory blocks on CPU reset. Prevents memory leaks when resetting. --- src/codegen_backend.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/codegen_backend.c b/src/codegen_backend.c index db786b2..8dca3b2 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -94,7 +94,15 @@ void codegen_close() void codegen_reset() { int c; - + + for (c = 1; c < BLOCK_SIZE; c++) + { + codeblock_t *block = &codeblock[c]; + + if (block->pc != BLOCK_PC_INVALID) + delete_block(block); + } + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); mem_reset_page_blocks(); From bf392ffd3a19f4308f54069a897ebf39af57ec79 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 19 Jan 2019 21:54:14 +0000 Subject: [PATCH 104/181] Maintain a list of free code blocks, and allocate new blocks from the list rather than evicting at random. Also maintain a list of memory pages with dirty code blocks that can be evicted. This allows the recompiler to evict dirty blocks in preference to freeing usable blocks when the free list is empty. Increase the number of available code blocks on x86. Increase the non-ARM code allocator memory to 128 MB. This reduces the amount of code block churning when running software with a lot of code, eg Windows XP. --- src/codegen.h | 13 ++-- src/codegen_allocator.c | 3 +- src/codegen_allocator.h | 2 +- src/codegen_backend.c | 124 ++++++++++++++++++++++++++++++-------- src/codegen_backend_x86.h | 4 +- src/mem.c | 74 ++++++++++++++++++++--- src/mem.h | 13 ++++ 7 files changed, 189 insertions(+), 44 deletions(-) diff --git a/src/codegen.h b/src/codegen.h index e76391b..39c101f 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -29,12 +29,6 @@ same page). */ -/*Hack until better memory management written*/ -/*This is deliberately _not_ a power of two, to avoid cache aliasing problems. - Try changing this to a power of two, and watch the performance plummet :) - It's probably best for this to be a multiple of the cache line size though*/ -#define BLOCK_DATA_SIZE 0xff80 - typedef struct codeblock_t { uint32_t pc; @@ -59,7 +53,7 @@ typedef struct codeblock_t present in two pages.*/ uint16_t prev, next; uint16_t prev_2, next_2; - + /*First mem_block_t used by this block. Any subsequent mem_block_ts will be in the list starting at head_mem_block->next.*/ struct mem_block_t *head_mem_block; @@ -77,6 +71,8 @@ extern uint8_t *block_write_data; #define CODEBLOCK_STATIC_TOP 2 /*Code block has been compiled*/ #define CODEBLOCK_WAS_RECOMPILED 4 +/*Code block is in free list and is not valid*/ +#define CODEBLOCK_IN_FREE_LIST 8 #define BLOCK_PC_INVALID 0xffffffff @@ -304,9 +300,10 @@ x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fe void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +int codegen_purge_purgable_list(); /*Delete a random code block to free memory. This is obviously quite expensive, and will only be called when the allocator is out of memory*/ -void codegen_delete_random_block(); +void codegen_delete_random_block(int required_mem_block); extern int cpu_block_end; extern uint32_t codegen_endpc; diff --git a/src/codegen_allocator.c b/src/codegen_allocator.c index 3dba230..b6b8273 100644 --- a/src/codegen_allocator.c +++ b/src/codegen_allocator.c @@ -50,7 +50,8 @@ mem_block_t *codegen_allocator_allocate(mem_block_t *parent) while (!mem_block_free_list) { - codegen_delete_random_block(); + if (!codegen_purge_purgable_list()) + codegen_delete_random_block(1); } // fatal("codegen_allocator_allocate: free list empty!\n"); diff --git a/src/codegen_allocator.h b/src/codegen_allocator.h index 22504bf..ffe633c 100644 --- a/src/codegen_allocator.h +++ b/src/codegen_allocator.h @@ -16,7 +16,7 @@ #ifdef __ARM_EABI__ #define MEM_BLOCK_NR 32768 #else -#define MEM_BLOCK_NR 65536 +#define MEM_BLOCK_NR 131072 #endif #define MEM_BLOCK_SIZE 0x3c0 diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 8dca3b2..034ad61 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -53,10 +53,71 @@ static int last_ssegs; uint32_t instr_counts[256*256]; #endif +static uint16_t block_free_list; +static void delete_block(codeblock_t *block); + +static void block_free_list_add(codeblock_t *block) +{ + if (block_free_list) + block->next = block_free_list; + else + block->next = 0; + block_free_list = get_block_nr(block); + block->flags = CODEBLOCK_IN_FREE_LIST; +// pclog("block_free_list_add: %p %p\n", block, block->next); +} + +int codegen_purge_purgable_list() +{ + if (purgable_page_list_head) + { + page_t *page = &pages[purgable_page_list_head]; + int c; +// pclog("Purge page %08x\n", purgable_page_list_head); + for (c = 0; c < 4; c++) + { +// pclog(" Check %016llx %016llx\n", page->code_present_mask[c], page->dirty_mask[c]); + if (page->code_present_mask[c] & page->dirty_mask[c]) + { + codegen_check_flush(page, page->dirty_mask[c], (purgable_page_list_head << 12) + (c << 10)); +// pclog(" Check %08x %i\n", (purgable_page_list_head << 12) + (c << 10), block_free_list); + if (block_free_list) + return 1; + } + } + } + return 0; +} + +static codeblock_t *block_free_list_get() +{ + codeblock_t *block = NULL; + + while (!block_free_list) + { + /*Free list is empty - free up a block*/ + if (!codegen_purge_purgable_list()) + codegen_delete_random_block(0); + } + + block = &codeblock[block_free_list]; + block_free_list = block->next; + block->flags &= ~CODEBLOCK_IN_FREE_LIST; + block->next = 0; +// pclog("block_free_list_get: %p %p\n", block, block_free_list); + return block; +} + void codegen_init() { + int c; + codegen_allocator_init(); + codegen_backend_init(); + block_free_list = 0; + for (c = 0; c < BLOCK_SIZE; c++) + block_free_list_add(&codeblock[c]); #ifdef DEBUG_EXTRA memset(instr_counts, 0, sizeof(instr_counts)); #endif @@ -106,9 +167,13 @@ void codegen_reset() memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); mem_reset_page_blocks(); - + + block_free_list = 0; for (c = 0; c < BLOCK_SIZE; c++) + { codeblock[c].pc = BLOCK_PC_INVALID; + block_free_list_add(&codeblock[c]); + } } void dump_block() @@ -232,24 +297,26 @@ static void delete_block(codeblock_t *block) if (block->head_mem_block) codegen_allocator_free(block->head_mem_block); block->head_mem_block = NULL; + block_free_list_add(block); } -void codegen_delete_random_block() +void codegen_delete_random_block(int required_mem_block) { + int block_nr = rand() & BLOCK_MASK; + while (1) { - int block_nr = rand() & BLOCK_MASK; - if (block_nr && block_nr != block_current) { codeblock_t *block = &codeblock[block_nr]; - - if (block->pc != BLOCK_PC_INVALID && block->head_mem_block) + + if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block)) { delete_block(block); return; } } + block_nr = (block_nr + 1) & BLOCK_MASK; } } @@ -260,15 +327,16 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) while (block_nr) { codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next; if (mask & block->page_mask) { delete_block(block); cpu_recomp_evicted++; } - if (block == &codeblock[block->next]) + if (block_nr == next_block) fatal("Broken 1\n"); - block_nr = block->next; + block_nr = next_block; } block_nr = page->block_2[(phys_addr >> 10) & 3]; @@ -276,16 +344,26 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) while (block_nr) { codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next_2; if (mask & block->page_mask2) { delete_block(block); cpu_recomp_evicted++; } - if (block == &codeblock[block->next_2]) + if (block_nr == next_block) fatal("Broken 2\n"); - block_nr = block->next_2; + block_nr = next_block; } + + page->code_present_mask[(phys_addr >> 10) & 3] &= ~mask; + page->dirty_mask[(phys_addr >> 10) & 3] &= ~mask; + + if (!(page->code_present_mask[0] & page->dirty_mask[0]) && + !(page->code_present_mask[1] & page->dirty_mask[1]) && + !(page->code_present_mask[2] & page->dirty_mask[2]) && + !(page->code_present_mask[3] & page->dirty_mask[3])) + page_remove_from_evict_list(page); } void codegen_block_init(uint32_t phys_addr) @@ -296,19 +374,11 @@ void codegen_block_init(uint32_t phys_addr) if (!page->block[(phys_addr >> 10) & 3]) mem_flush_write_page(phys_addr, cs+cpu_state.pc); - block_current = (block_current + 1) & BLOCK_MASK; - if (!block_current) - block_current++; - block = &codeblock[block_current]; + block = block_free_list_get(); + if (!block) + fatal("codegen_block_init: block_free_list_get() returned NULL\n"); + block_current = get_block_nr(block); -// if (block->pc == 0xb00b4ff5) -// pclog("Init target block\n"); - if (block->pc != BLOCK_PC_INVALID) - { -// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); - delete_block(block); - cpu_recomp_reuse++; - } block_num = HASH(phys_addr); codeblock_hash[block_num] = block_current; @@ -407,6 +477,7 @@ void codegen_block_generate_end_mask() codeblock_t *block = &codeblock[block_current]; uint32_t start_pc; uint32_t end_pc; + page_t *p; block->page_mask = 0; start_pc = (block->pc & 0x3ff) & ~15; @@ -426,7 +497,10 @@ void codegen_block_generate_end_mask() // pclog(" %08x %llx\n", start_pc, block->page_mask); } - pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + p = &pages[block->phys >> 12]; + p->code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + if ((p->dirty_mask[(block->phys >> 10) & 3] & block->page_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); block->phys_2 = -1; block->page_mask2 = 0; @@ -443,7 +517,9 @@ void codegen_block_generate_end_mask() for (; start_pc <= end_pc; start_pc++) block->page_mask2 |= ((uint64_t)1 << start_pc); page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - + if ((page_2->dirty_mask[(block->phys_2 >> 10) & 3] & block->page_mask2) && !page_in_evict_list(page_2)) + page_add_to_evict_list(page_2); + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) mem_flush_write_page(block->phys_2, codegen_endpc); diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h index 7e32927..db521a7 100644 --- a/src/codegen_backend_x86.h +++ b/src/codegen_backend_x86.h @@ -1,7 +1,7 @@ #include "codegen_backend_x86_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x10000 +#define BLOCK_MASK 0xffff #define BLOCK_START 0 #define HASH_SIZE 0x20000 diff --git a/src/mem.c b/src/mem.c index ad095a3..cc253d8 100644 --- a/src/mem.c +++ b/src/mem.c @@ -924,14 +924,51 @@ uint32_t mem_read_raml(uint32_t addr, void *priv) return *(uint32_t *)&ram[addr]; } +uint32_t purgable_page_list_head = 0; +int purgeable_page_count = 0; + +static inline int page_index(page_t *p) +{ + return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t); +} +void page_add_to_evict_list(page_t *p) +{ +// pclog("page_add_to_evict_list: %08x %i\n", page_index(p), purgeable_page_count); + pages[purgable_page_list_head].evict_prev = page_index(p); + p->evict_next = purgable_page_list_head; + p->evict_prev = 0; + purgable_page_list_head = pages[purgable_page_list_head].evict_prev; + purgeable_page_count++; +} +void page_remove_from_evict_list(page_t *p) +{ +// pclog("page_remove_from_evict_list: %08x %i\n", page_index(p), purgeable_page_count); + if (!page_in_evict_list(p)) + fatal("page_remove_from_evict_list: not in evict list!\n"); + if (p->evict_prev) + pages[p->evict_prev].evict_next = p->evict_next; + else + purgable_page_list_head = p->evict_next; + if (p->evict_next) + pages[p->evict_next].evict_prev = p->evict_prev; + p->evict_prev = EVICT_NOT_IN_LIST; + purgeable_page_count--; +} + void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) { if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); -// pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+pc, p->dirty_mask, mask); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; +// pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask, mask); p->mem[addr & 0xfff] = val; + p->dirty_mask[index] |= mask; + if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + { +// pclog("ramb add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } } } void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) @@ -939,11 +976,17 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; if ((addr & 0xf) == 0xf) mask |= (mask << 1); -// pclog("mem_write_ramw_page: %08x %04x %08x\n", addr, val, cs+pc); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; +// pclog("mem_write_ramw_page: %08x %04x %08x %016llx %016llx %016llx %08x %08x %p\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask, p->evict_prev, p->evict_next, p); *(uint16_t *)&p->mem[addr & 0xfff] = val; + p->dirty_mask[index] |= mask; + if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + { +// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } } } void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) @@ -951,11 +994,17 @@ void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; if ((addr & 0xf) >= 0xd) mask |= (mask << 1); -// pclog("mem_write_raml_page: %08x %08x %08x\n", addr, val, cs+pc); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; +// pclog("mem_write_raml_page: %08x %08x %08x %016llx %016llx %016llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask); *(uint32_t *)&p->mem[addr & 0xfff] = val; + p->dirty_mask[index] |= mask; + if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + { +// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } } } @@ -1066,8 +1115,15 @@ void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - pages[start_addr >> 12].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + page_t *p = &pages[start_addr >> 12]; + int index = (start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; +//pclog("mem_invalidate: %08x\n", start_addr); + p->dirty_mask[index] |= mask; + if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + { +// pclog("invalidate add %08x %016llx %016llx\n", start_addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } } } @@ -1330,6 +1386,7 @@ void mem_init() pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; + pages[c].evict_prev = EVICT_NOT_IN_LIST; } memset(isram, 0, sizeof(isram)); @@ -1439,6 +1496,7 @@ void mem_resize() pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; + pages[c].evict_prev = EVICT_NOT_IN_LIST; } memset(isram, 0, sizeof(isram)); diff --git a/src/mem.h b/src/mem.h index a015acc..3a27a92 100644 --- a/src/mem.h +++ b/src/mem.h @@ -111,6 +111,7 @@ mem_mapping_t bios_high_mapping[8]; extern mem_mapping_t ram_high_mapping; extern mem_mapping_t ram_remapped_mapping; +#define EVICT_NOT_IN_LIST ((uint32_t)-1) typedef struct page_t { void (*write_b)(uint32_t addr, uint8_t val, struct page_t *p); @@ -125,12 +126,22 @@ typedef struct page_t uint16_t head; uint64_t code_present_mask[4], dirty_mask[4]; + + uint32_t evict_prev, evict_next; } page_t; extern page_t *pages; extern page_t **page_lookup; +extern uint32_t purgable_page_list_head; +static inline int page_in_evict_list(page_t *p) +{ + return (p->evict_prev != EVICT_NOT_IN_LIST); +} +void page_remove_from_evict_list(page_t *p); +void page_add_to_evict_list(page_t *p); + uint32_t mmutranslate_noabrt(uint32_t addr, int rw); extern uint32_t get_phys_virt,get_phys_phys; static inline uint32_t get_phys(uint32_t addr) @@ -195,4 +206,6 @@ void mmu_invalidate(uint32_t addr); int loadbios(); extern unsigned char isram[0x10000]; + +extern int purgeable_page_count; #endif From ec18c8a2fbb6a89a268b772fded2a95c7b25b92e Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 21 Jan 2019 21:52:32 +0000 Subject: [PATCH 105/181] Implement more intelligent out-of-memory algorithm. --- src/codegen.h | 1 + src/codegen_allocator.c | 14 +++++++++++--- src/codegen_allocator.h | 3 ++- src/codegen_backend.c | 8 +++++++- src/codegen_backend_x86-64.c | 2 +- src/codegen_backend_x86-64_ops.c | 2 +- src/codegen_backend_x86.c | 2 +- src/codegen_backend_x86_ops.c | 2 +- 8 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/codegen.h b/src/codegen.h index 39c101f..1438dab 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -290,6 +290,7 @@ void codegen_block_remove(); void codegen_block_start_recompile(codeblock_t *block); void codegen_block_end_recompile(codeblock_t *block); void codegen_block_end(); +void codegen_delete_block(codeblock_t *block); void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); void codegen_generate_seg_restore(); void codegen_set_op32(); diff --git a/src/codegen_allocator.c b/src/codegen_allocator.c index b6b8273..4b4ffd7 100644 --- a/src/codegen_allocator.c +++ b/src/codegen_allocator.c @@ -14,6 +14,7 @@ typedef struct mem_block_t { uint32_t offset; /*Offset into mem_block_alloc*/ uint32_t next; + uint16_t code_block; } mem_block_t; static mem_block_t mem_blocks[MEM_BLOCK_NR]; @@ -35,6 +36,7 @@ void codegen_allocator_init() for (c = 0; c < MEM_BLOCK_NR; c++) { mem_blocks[c].offset = c * MEM_BLOCK_SIZE; + mem_blocks[c].code_block = BLOCK_INVALID; if (c < MEM_BLOCK_NR-1) mem_blocks[c].next = c+2; else @@ -43,15 +45,19 @@ void codegen_allocator_init() mem_block_free_list = 1; } -mem_block_t *codegen_allocator_allocate(mem_block_t *parent) +mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block) { mem_block_t *block; uint32_t block_nr; while (!mem_block_free_list) { - if (!codegen_purge_purgable_list()) - codegen_delete_random_block(1); + /*Pick a random memory block and free the owning code block*/ + block_nr = rand() & MEM_BLOCK_MASK; + block = &mem_blocks[block_nr]; + + if (block->code_block && block->code_block != code_block) + codegen_delete_block(&codeblock[block->code_block]); } // fatal("codegen_allocator_allocate: free list empty!\n"); @@ -60,6 +66,7 @@ mem_block_t *codegen_allocator_allocate(mem_block_t *parent) block = &mem_blocks[block_nr-1]; mem_block_free_list = block->next; + block->code_block = code_block; if (parent) { /*Add to parent list*/ @@ -88,6 +95,7 @@ void codegen_allocator_free(mem_block_t *block) codegen_allocator_usage--; block->next = mem_block_free_list; + block->code_block = BLOCK_INVALID; mem_block_free_list = block_nr; block_nr = next_block_nr; diff --git a/src/codegen_allocator.h b/src/codegen_allocator.h index ffe633c..1adb243 100644 --- a/src/codegen_allocator.h +++ b/src/codegen_allocator.h @@ -19,13 +19,14 @@ #define MEM_BLOCK_NR 131072 #endif +#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1) #define MEM_BLOCK_SIZE 0x3c0 void codegen_allocator_init(); /*Allocate a mem_block_t, and the associated backing memory. If parent is non-NULL, then the new block will be added to the list in parent->next*/ -struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent); +struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent, int code_block); /*Free a mem_block_t, and any subsequent blocks in the list at block->next*/ void codegen_allocator_free(struct mem_block_t *block); /*Get a pointer to the backing memory associated with block*/ diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 034ad61..c047ba3 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -300,6 +300,12 @@ static void delete_block(codeblock_t *block) block_free_list_add(block); } +void codegen_delete_block(codeblock_t *block) +{ + if (block->pc != BLOCK_PC_INVALID) + delete_block(block); +} + void codegen_delete_random_block(int required_mem_block) { int block_nr = rand() & BLOCK_MASK; @@ -419,7 +425,7 @@ void codegen_block_start_recompile(codeblock_t *block) if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) fatal("Recompile to used block!\n"); - block->head_mem_block = codegen_allocator_allocate(NULL); + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); block->data = codeblock_allocator_get_ptr(block->head_mem_block); block->status = cpu_cur_status; diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index fff5942..2c1d970 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -298,7 +298,7 @@ void codegen_backend_init() block_current = 0; block_pos = 0; block = &codeblock[block_current]; - codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL); + codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current); codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); block_write_data = codeblock[block_current].data; build_loadstore_routines(&codeblock[block_current]); diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 956f4eb..90700fe 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -101,7 +101,7 @@ static inline void codegen_alloc_bytes(codeblock_t *block, int size) if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) { /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); /*Add a jump instruction to the new block*/ diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 982f69d..6119ea2 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -299,7 +299,7 @@ pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); block_current = 0; block_pos = 0; block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL); + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); block->data = codeblock_allocator_get_ptr(block->head_mem_block); block_write_data = block->data; build_loadstore_routines(block); diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 56bd27a..2d9ef2c 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -78,7 +78,7 @@ static inline void codegen_addquad(codeblock_t *block, uint64_t val) static void codegen_allocate_new_block(codeblock_t *block) { /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); /*Add a jump instruction to the new block*/ From c1f0b7c35d401c5c5811e60b892f49713ea87abf Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 22 Jan 2019 21:41:00 +0000 Subject: [PATCH 106/181] Use readlookup cache in get_phys(). --- src/mem.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/mem.h b/src/mem.h index 3a27a92..790d999 100644 --- a/src/mem.h +++ b/src/mem.h @@ -157,17 +157,34 @@ static inline uint32_t get_phys(uint32_t addr) return addr & rammask; } - get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff; + if (readlookup2[addr >> 12] != -1) + get_phys_phys = ((uintptr_t)readlookup2[addr >> 12] + (addr & ~0xfff)) - (uintptr_t)ram; + else + { + get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff; + if (!cpu_state.abrt) + addreadlookup(get_phys_virt, get_phys_phys); + } + return get_phys_phys | (addr & 0xfff); // return mmutranslatereal(addr, 0) & rammask; } static inline uint32_t get_phys_noabrt(uint32_t addr) { + uint32_t phys_addr; + if (!(cr0 >> 31)) return addr & rammask; - return mmutranslate_noabrt(addr, 0) & rammask; + if (readlookup2[addr >> 12] != -1) + return ((uintptr_t)readlookup2[addr >> 12] + addr) - (uintptr_t)ram; + + phys_addr = mmutranslate_noabrt(addr, 0) & rammask; + if (!cpu_state.abrt) + addreadlookup(addr, phys_addr); + + return phys_addr; } void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr); From d461bc7cdaef0d6f6a35cd8066d98c1166ea06c2 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 24 Jan 2019 20:36:20 +0000 Subject: [PATCH 107/181] Fix invalid page check in get_phys_noabrt(). --- src/mem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem.h b/src/mem.h index 790d999..4b640ea 100644 --- a/src/mem.h +++ b/src/mem.h @@ -181,7 +181,7 @@ static inline uint32_t get_phys_noabrt(uint32_t addr) return ((uintptr_t)readlookup2[addr >> 12] + addr) - (uintptr_t)ram; phys_addr = mmutranslate_noabrt(addr, 0) & rammask; - if (!cpu_state.abrt) + if (phys_addr != 0xffffffff) addreadlookup(addr, phys_addr); return phys_addr; From c3250ca63ee84011b5ef9005baa4a84c62843010 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 20:51:13 +0000 Subject: [PATCH 108/181] Don't set oldcpl at the start of each instruction; instead, only set it following a successful CS load. --- src/386.c | 1 - src/386_dynarec.c | 4 ---- src/x86_ops_misc.h | 1 + src/x86seg.c | 17 +++++++++++++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/386.c b/src/386.c index e7032d1..8d18d9a 100644 --- a/src/386.c +++ b/src/386.c @@ -238,7 +238,6 @@ void exec386(int cycs) oldcs=CS; cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; cpu_state.op32 = use32; dontprint=0; diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 1238cc0..77bba42 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -533,7 +533,6 @@ void exec386_dynarec(int cycs) { oldcs = CS; cpu_state.oldpc = cpu_state.pc; - oldcpl = CPL; cpu_state.op32 = use32; @@ -549,7 +548,6 @@ void exec386_dynarec(int cycs) { oldcs=CS; cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; cpu_state.op32 = use32; cpu_state.ea_seg = &cpu_state.seg_ds; @@ -708,7 +706,6 @@ inrecomp=0; { oldcs=CS; cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; cpu_state.op32 = use32; cpu_state.ea_seg = &cpu_state.seg_ds; @@ -790,7 +787,6 @@ inrecomp=0; { oldcs=CS; cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; cpu_state.op32 = use32; cpu_state.ea_seg = &cpu_state.seg_ds; diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index ee6c632..ca11638 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -925,6 +925,7 @@ static int opLOADALL386(uint32_t fetchdat) loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; CLOCK_CYCLES(350); return 0; diff --git a/src/x86seg.c b/src/x86seg.c index 547ed1b..012e930 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -573,6 +573,7 @@ void loadcs(uint16_t seg) do_seg_load(&cpu_state.seg_cs, segdat); use32=(segdat[3]&0x40)?0x300:0; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; #ifdef CS_ACCESSED cpl_override = 1; @@ -611,6 +612,7 @@ void loadcs(uint16_t seg) if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; } } @@ -697,6 +699,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; /* if (segdat[3]&0x40) { use32=0x300; @@ -801,6 +804,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -856,6 +860,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; cycles -= timing_jmp_rm; } } @@ -1032,6 +1037,7 @@ void loadcscall(uint16_t seg) CS=seg; do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; /* if (segdat[3]&0x40) { use32=0x300; @@ -1220,6 +1226,7 @@ void loadcscall(uint16_t seg) CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -1324,6 +1331,7 @@ void loadcscall(uint16_t seg) CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -1373,6 +1381,7 @@ void loadcscall(uint16_t seg) if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2; else cpu_state.seg_cs.access=(0<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; } } @@ -1500,6 +1509,7 @@ void pmoderetf(int is32, uint16_t off) do_seg_load(&cpu_state.seg_cs, segdat); cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3] & 0x40); // pclog("CPL=RPL return to %04X:%08X\n",CS,pc); @@ -1651,6 +1661,7 @@ void pmoderetf(int is32, uint16_t off) CS=seg; do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3] & 0x40); if (stack32) ESP+=off; @@ -1982,6 +1993,7 @@ void pmodeint(int num, int soft) cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | (new_cpl << 5); // pclog("New CS = %04X\n",CS); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; if (type>0x800) cpu_state.pc=segdat[0]|(segdat[3]<<16); else cpu_state.pc=segdat[0]; set_use32(segdat2[3]&0x40); @@ -2178,6 +2190,7 @@ void pmodeiret(int is32) CS=seg; cpu_state.seg_cs.access=(3<<5) | 2; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; ESP=newsp; loadseg(newss,&cpu_state.seg_ss); @@ -2297,6 +2310,7 @@ void pmodeiret(int is32) do_seg_load(&cpu_state.seg_cs, segdat); cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3]&0x40); #ifdef CS_ACCESSED @@ -2413,6 +2427,7 @@ void pmodeiret(int is32) do_seg_load(&cpu_state.seg_cs, segdat); cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat[3] & 0x40); check_seg_valid(&cpu_state.seg_ds); @@ -2647,6 +2662,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) CS=new_cs; do_seg_load(&cpu_state.seg_cs, segdat2); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(segdat2[3] & 0x40); cpu_cur_status &= ~CPU_STATUS_V86; } @@ -2847,6 +2863,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) CS=new_cs; do_seg_load(&cpu_state.seg_cs, segdat2); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; set_use32(0); EAX=new_eax | 0xFFFF0000; From 93b42d43d5690bfd1489ffcc6e93f011efdd8b21 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 20:52:02 +0000 Subject: [PATCH 109/181] Remove pointless setting of cpu_state.op32 and cycdiff at start of recompiler main loop. --- src/386_dynarec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 77bba42..41d7bea 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -533,10 +533,8 @@ void exec386_dynarec(int cycs) { oldcs = CS; cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - cycdiff=0; oldcyc=cycles; // if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); if (!CACHE_ON()) /*Interpret block*/ From 6c65c34bd3ce33355ab7e53480ab52b377136bed Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 20:52:37 +0000 Subject: [PATCH 110/181] Don't clear trap at the start of the recompiler loop; instead, clear it when actually taking a trap. --- src/386_dynarec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 41d7bea..dbd8cb5 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -600,7 +600,6 @@ void exec386_dynarec(int cycs) int hash = HASH(phys_addr); codeblock_t *block = &codeblock[codeblock_hash[hash]]; int valid_block = 0; - trap = 0; if (block && !cpu_state.abrt) { @@ -877,7 +876,7 @@ inrecomp=0; if (trap) { - + trap = 0; flags_rebuild(); // oldpc=pc; // oldcs=CS; From 7b3b6a745d462216611ee3e6cbcb1bb57c04c0bc Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 20:52:59 +0000 Subject: [PATCH 111/181] Remove pointless NULL check against block in recompiler loop. --- src/386_dynarec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index dbd8cb5..60647e5 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -601,7 +601,7 @@ void exec386_dynarec(int cycs) codeblock_t *block = &codeblock[codeblock_hash[hash]]; int valid_block = 0; - if (block && !cpu_state.abrt) + if (!cpu_state.abrt) { page_t *page = &pages[phys_addr >> 12]; From ee186dbb0d794b9872b6b6c57f0b3965461dca40 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 20:54:22 +0000 Subject: [PATCH 112/181] Remove test-USE32-and-mask-PC operation following code block execution. Instead, ensure that all recompiled instructions mask PC correctly. --- src/386_dynarec.c | 1 - src/codegen_ops_branch.c | 106 ++++++++++++++++++++++++--------------- src/codegen_ops_jump.c | 18 +++++-- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 60647e5..62af26e 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -678,7 +678,6 @@ void exec386_dynarec(int cycs) inrecomp=1; code(); inrecomp=0; - if (!use32) cpu_state.pc &= 0xffff; // cpu_recomp_ins += block->ins; cpu_recomp_blocks++; /* ins += codeblock_ins[index]; diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index e5a34fd..fdc0569 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -19,7 +19,7 @@ static int VF_SET_01() return VF_SET() ? 1 : 0; } -static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -47,11 +47,11 @@ static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -59,7 +59,7 @@ static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u { case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Overflow is always zero*/ - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); return; @@ -81,12 +81,12 @@ static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -114,11 +114,11 @@ static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -126,7 +126,7 @@ static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u { case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Carry is always zero*/ - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); return; @@ -148,12 +148,12 @@ static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -166,11 +166,11 @@ static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui { jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -183,12 +183,12 @@ void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t { jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop, jump_uop2 = -1; @@ -219,11 +219,11 @@ static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u } if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop, jump_uop2 = -1; @@ -252,14 +252,14 @@ static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); } -static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -304,11 +304,11 @@ static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -353,33 +353,33 @@ static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -413,11 +413,11 @@ static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, ui jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop; @@ -451,12 +451,12 @@ static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop, jump_uop2 = -1; @@ -483,11 +483,11 @@ static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, u } if (jump_uop2 != -1) uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); } -static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t offset) +static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { int jump_uop, jump_uop2 = -1; @@ -512,7 +512,7 @@ static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); break; } - uop_MOV_IMM(ir, IREG_pc, base_pc + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); if (jump_uop2 != -1) @@ -523,21 +523,29 @@ static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t base_pc, uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); \ - ropJ ## cond ## _common(block, ir, op_pc+1, offset); \ + uint32_t dest_addr = op_pc + 1 + offset; \ + \ + if (!(op_32 & 0x100)) \ + dest_addr &= 0xffff; \ + ropJ ## cond ## _common(block, ir, dest_addr); \ \ return op_pc+1; \ } \ uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); \ - ropJ ## cond ## _common(block, ir, op_pc+2, offset); \ + uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ + \ + ropJ ## cond ## _common(block, ir, dest_addr); \ \ return op_pc+2; \ } \ uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ uint32_t offset = fastreadl(cs + op_pc); \ - ropJ ## cond ## _common(block, ir, op_pc+4, offset); \ + uint32_t dest_addr = op_pc + 4 + offset; \ + \ + ropJ ## cond ## _common(block, ir, dest_addr); \ \ return op_pc+4; \ } @@ -563,13 +571,17 @@ ropJ(NLE) uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; int jump_uop; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + if (op_32 & 0x200) jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); else jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); - uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); @@ -579,8 +591,12 @@ uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; int jump_uop; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + if (op_32 & 0x200) { uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); @@ -591,7 +607,7 @@ uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } - uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); @@ -601,8 +617,12 @@ uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; int jump_uop, jump_uop2; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + if (op_32 & 0x200) { uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); @@ -622,7 +642,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe { jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); } - uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); @@ -632,8 +652,12 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; int jump_uop, jump_uop2; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + if (op_32 & 0x200) { uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); @@ -653,7 +677,7 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f { jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); } - uop_MOV_IMM(ir, IREG_pc, op_pc + 1 + offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index c5209c1..d559881 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -12,22 +12,30 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc+1+offset; - uop_MOV_IMM(ir, IREG_pc, op_pc+1+offset); + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + uop_MOV_IMM(ir, IREG_pc, dest_addr); return -1; } uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); + uint32_t dest_addr = op_pc+2+offset; + + dest_addr &= 0xffff; - uop_MOV_IMM(ir, IREG_pc, op_pc+2+offset); + uop_MOV_IMM(ir, IREG_pc, dest_addr); return -1; } uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = fastreadl(cs + op_pc); - - uop_MOV_IMM(ir, IREG_pc, op_pc+4+offset); + uint32_t dest_addr = op_pc+4+offset; + + uop_MOV_IMM(ir, IREG_pc, dest_addr); return -1; } @@ -65,6 +73,8 @@ uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint16_t dest_addr = ret_addr + offset; int sp_reg; + dest_addr &= 0xffff; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr); From 889ca7f3f29d3b28c56a145f2aa24e1efca0624d Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 21:22:35 +0000 Subject: [PATCH 113/181] Remove test-USE32-and-mask-PC operation from interpreter as well. --- src/386.c | 2 -- src/386_dynarec.c | 6 ------ src/x86_ops_jump.h | 11 +++++++++++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/386.c b/src/386.c index 8d18d9a..12428bf 100644 --- a/src/386.c +++ b/src/386.c @@ -263,8 +263,6 @@ dontprint=0; break; } - if (!use32) cpu_state.pc &= 0xffff; - if (cpu_state.abrt) { flags_rebuild(); diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 62af26e..39d1787 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -567,8 +567,6 @@ void exec386_dynarec(int cycs) x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); } - if (!use32) cpu_state.pc &= 0xffff; - if (((cs + cpu_state.pc) >> 12) != pccache) CPU_BLOCK_END(); @@ -731,8 +729,6 @@ inrecomp=0; break; } - if (!use32) cpu_state.pc &= 0xffff; - /*Cap source code at 4000 bytes per block; this will prevent any block from spanning more than 2 pages. In practice this limit will never be @@ -808,8 +804,6 @@ inrecomp=0; break; } - if (!use32) cpu_state.pc &= 0xffff; - /*Cap source code at 4000 bytes per block; this will prevent any block from spanning more than 2 pages. In practice this limit will never be diff --git a/src/x86_ops_jump.h b/src/x86_ops_jump.h index 292102a..855ddf7 100644 --- a/src/x86_ops_jump.h +++ b/src/x86_ops_jump.h @@ -23,6 +23,8 @@ if (cond_ ## condition) \ { \ cpu_state.pc += offset; \ + if (!(cpu_state.op32 & 0x100)) \ + cpu_state.pc &= 0xffff; \ CLOCK_CYCLES_ALWAYS(timing_bt); \ CPU_BLOCK_END(); \ PREFETCH_RUN(timing_bt+timing_bnt, 2, -1, 0,0,0,0, 0); \ @@ -40,6 +42,7 @@ if (cond_ ## condition) \ { \ cpu_state.pc += offset; \ + cpu_state.pc &= 0xffff; \ CLOCK_CYCLES_ALWAYS(timing_bt); \ CPU_BLOCK_END(); \ PREFETCH_RUN(timing_bt+timing_bnt, 3, -1, 0,0,0,0, 0); \ @@ -95,6 +98,7 @@ static int opLOOPNE_w(uint32_t fetchdat) if (CX && !ZF_SET()) { cpu_state.pc += offset; + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -126,6 +130,7 @@ static int opLOOPE_w(uint32_t fetchdat) if (CX && ZF_SET()) { cpu_state.pc += offset; + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -157,6 +162,7 @@ static int opLOOP_w(uint32_t fetchdat) if (CX) { cpu_state.pc += offset; + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -186,6 +192,7 @@ static int opJCXZ(uint32_t fetchdat) if (!CX) { cpu_state.pc += offset; + cpu_state.pc &= 0xffff; CLOCK_CYCLES(4); CPU_BLOCK_END(); PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); @@ -217,6 +224,8 @@ static int opJMP_r8(uint32_t fetchdat) { int8_t offset = (int8_t)getbytef(); cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); PREFETCH_RUN(7, 2, -1, 0,0,0,0, 0); @@ -227,6 +236,7 @@ static int opJMP_r16(uint32_t fetchdat) { int16_t offset = (int16_t)getwordf(); cpu_state.pc += offset; + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); PREFETCH_RUN(7, 3, -1, 0,0,0,0, 0); @@ -274,6 +284,7 @@ static int opCALL_r16(uint32_t fetchdat) int16_t addr = (int16_t)getwordf(); PUSH_W(cpu_state.pc); cpu_state.pc += addr; + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); PREFETCH_RUN(7, 3, -1, 0,0,1,0, 0); From 32d4f4c765e241b78ec1c2a79e1535825e482273 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 27 Jan 2019 22:21:06 +0000 Subject: [PATCH 114/181] Fix incorrect PC size detection on LOOP/LOOPE/LOOPNE/JCXZ/JECXZ. Fixes Heaven 7. --- src/x86_ops_jump.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/x86_ops_jump.h b/src/x86_ops_jump.h index 855ddf7..a7c4fd5 100644 --- a/src/x86_ops_jump.h +++ b/src/x86_ops_jump.h @@ -98,7 +98,8 @@ static int opLOOPNE_w(uint32_t fetchdat) if (CX && !ZF_SET()) { cpu_state.pc += offset; - cpu_state.pc &= 0xffff; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -114,6 +115,8 @@ static int opLOOPNE_l(uint32_t fetchdat) if (ECX && !ZF_SET()) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -130,7 +133,8 @@ static int opLOOPE_w(uint32_t fetchdat) if (CX && ZF_SET()) { cpu_state.pc += offset; - cpu_state.pc &= 0xffff; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -146,6 +150,8 @@ static int opLOOPE_l(uint32_t fetchdat) if (ECX && ZF_SET()) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -162,7 +168,8 @@ static int opLOOP_w(uint32_t fetchdat) if (CX) { cpu_state.pc += offset; - cpu_state.pc &= 0xffff; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -178,6 +185,8 @@ static int opLOOP_l(uint32_t fetchdat) if (ECX) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -192,7 +201,8 @@ static int opJCXZ(uint32_t fetchdat) if (!CX) { cpu_state.pc += offset; - cpu_state.pc &= 0xffff; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CLOCK_CYCLES(4); CPU_BLOCK_END(); PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); @@ -209,6 +219,8 @@ static int opJECXZ(uint32_t fetchdat) if (!ECX) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CLOCK_CYCLES(4); CPU_BLOCK_END(); PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); From 6e5336ae564c1fbdbc02694c5e54137ff13963c8 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 17:40:28 +0000 Subject: [PATCH 115/181] When compiling with CODEBLOCK_STATIC_TOP, update TOP register with immediate moves rather than add/sub. --- src/codegen_ops_fpu_arith.c | 26 ++++++++++++-------------- src/codegen_ops_fpu_constant.c | 4 ++-- src/codegen_ops_fpu_loadstore.c | 20 ++++++++++---------- src/codegen_ops_fpu_misc.c | 4 ++-- src/codegen_ops_helpers.h | 21 +++++++++++++++++---- 5 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c index 9d4259c..3f05802 100644 --- a/src/codegen_ops_fpu_arith.c +++ b/src/codegen_ops_fpu_arith.c @@ -38,7 +38,7 @@ uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_FP_ENTER(ir); uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -62,7 +62,7 @@ uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -72,8 +72,7 @@ uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(ir); - fpu_POP(ir); + fpu_POP2(block, ir); return op_pc; } @@ -125,7 +124,7 @@ uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_FP_ENTER(ir); uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -136,7 +135,7 @@ uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_FP_ENTER(ir); uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -168,7 +167,7 @@ uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_FP_ENTER(ir); uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -220,7 +219,7 @@ uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_FP_ENTER(ir); uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -231,7 +230,7 @@ uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_FP_ENTER(ir); uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -255,7 +254,7 @@ uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } @@ -265,8 +264,7 @@ uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(ir); - fpu_POP(ir); + fpu_POP2(block, ir); return op_pc; } @@ -316,7 +314,7 @@ uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uin uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(ir); \ + fpu_POP(block, ir); \ \ return op_pc+1; \ } \ @@ -447,7 +445,7 @@ uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, ui uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(ir); \ + fpu_POP(block, ir); \ \ return op_pc+1; \ } \ diff --git a/src/codegen_ops_fpu_constant.c b/src/codegen_ops_fpu_constant.c index 187850c..aa264ce 100644 --- a/src/codegen_ops_fpu_constant.c +++ b/src/codegen_ops_fpu_constant.c @@ -17,7 +17,7 @@ uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV_IMM(ir, IREG_temp0, 1); uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc; } @@ -27,7 +27,7 @@ uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV_IMM(ir, IREG_temp0, 0); uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc; } diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c index 04ee62a..f5e42f3 100644 --- a/src/codegen_ops_fpu_loadstore.c +++ b/src/codegen_ops_fpu_loadstore.c @@ -22,7 +22,7 @@ uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc+1; } @@ -37,7 +37,7 @@ uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_check_seg_read(block, ir, target_seg); uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc+1; } @@ -66,7 +66,7 @@ uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc+1; } @@ -94,7 +94,7 @@ uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc+1; } @@ -112,7 +112,7 @@ uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc+1; } @@ -128,7 +128,7 @@ uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc+1; } @@ -144,7 +144,7 @@ uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr); uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1)); uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc+1; } @@ -176,7 +176,7 @@ uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc+1; } @@ -207,7 +207,7 @@ uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc+1; } @@ -223,7 +223,7 @@ uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc+1; } diff --git a/src/codegen_ops_fpu_misc.c b/src/codegen_ops_fpu_misc.c index 18d6f88..58902ac 100644 --- a/src/codegen_ops_fpu_misc.c +++ b/src/codegen_ops_fpu_misc.c @@ -29,7 +29,7 @@ uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg)); uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); - fpu_PUSH(ir); + fpu_PUSH(block, ir); return op_pc; } @@ -53,7 +53,7 @@ uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); - fpu_POP(ir); + fpu_POP(block, ir); return op_pc; } diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index 1b4cf30..9bde28f 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -46,11 +46,24 @@ static inline void SUB_SP(ir_data_t *ir, int offset) uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); } -static inline void fpu_POP(ir_data_t *ir) +static inline void fpu_POP(codeblock_t *block, ir_data_t *ir) { - uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1); + else + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } -static inline void fpu_PUSH(ir_data_t *ir) +static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir) { - uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2); + else + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2); +} +static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir) +{ + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); + else + uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } From 427aa72a15a47403deae36b35ff3c62964aa8a40 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 19:25:09 +0000 Subject: [PATCH 116/181] Don't set cpu_state.oldpc at the start of every iteration of the recompiler main loop. --- src/386_dynarec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 39d1787..6e2bf35 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -532,8 +532,6 @@ void exec386_dynarec(int cycs) while (cycles>0) { oldcs = CS; - cpu_state.oldpc = cpu_state.pc; - oldcyc=cycles; // if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); @@ -835,6 +833,9 @@ inrecomp=0; // output &= ~2; } + else + cpu_state.oldpc = cpu_state.pc; + // if (output && (SP & 1)) // fatal("odd SP\n"); } From ca89a51478cca5e07286334a5fc4eca531c83cfc Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 20:00:49 +0000 Subject: [PATCH 117/181] Remove redundant oldcs variable - when processing an exception, oldcs and CS are the same. --- src/386.c | 6 ------ src/386_dynarec.c | 9 --------- src/808x.c | 8 ++------ src/x86.h | 1 - src/x86seg.c | 16 ---------------- 5 files changed, 2 insertions(+), 38 deletions(-) diff --git a/src/386.c b/src/386.c index 12428bf..a0ad35f 100644 --- a/src/386.c +++ b/src/386.c @@ -50,7 +50,6 @@ extern int oddeven; int inttype; -uint32_t oldcs2; uint32_t oldecx; uint32_t *eal_r, *eal_w; @@ -233,10 +232,8 @@ void exec386(int cycs) /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX; testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/ /* testr[8]=flags;*/ -// oldcs2=oldcs; // oldpc2=oldpc; - oldcs=CS; cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; @@ -283,7 +280,6 @@ dontprint=0; if (cpu_state.abrt) { cpu_state.abrt = 0; - CS = oldcs; cpu_state.pc = cpu_state.oldpc; pclog("Double fault %i\n", ins); pmodeint(8, 0); @@ -302,7 +298,6 @@ dontprint=0; { flags_rebuild(); // oldpc=pc; -// oldcs=CS; if (msw&1) { pmodeint(1,0); @@ -323,7 +318,6 @@ dontprint=0; else if (nmi && nmi_enable && nmi_mask) { cpu_state.oldpc = cpu_state.pc; - oldcs = CS; // pclog("NMI\n"); x86_int(2); nmi_enable = 0; diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 6e2bf35..0137238 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -59,7 +59,6 @@ int oddeven=0; int inttype; -uint32_t oldcs2; uint32_t oldecx; uint32_t *eal_r, *eal_w; @@ -531,8 +530,6 @@ void exec386_dynarec(int cycs) // output=3; while (cycles>0) { - oldcs = CS; - oldcyc=cycles; // if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); if (!CACHE_ON()) /*Interpret block*/ @@ -542,7 +539,6 @@ void exec386_dynarec(int cycs) // if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); while (!cpu_block_end) { - oldcs=CS; cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; @@ -696,7 +692,6 @@ inrecomp=0; // if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); while (!cpu_block_end) { - oldcs=CS; cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; @@ -775,7 +770,6 @@ inrecomp=0; // if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); while (!cpu_block_end) { - oldcs=CS; cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; @@ -854,7 +848,6 @@ inrecomp=0; if (cpu_state.abrt) { cpu_state.abrt = 0; - CS = oldcs; cpu_state.pc = cpu_state.oldpc; pclog("Double fault %i\n", ins); pmodeint(8, 0); @@ -873,7 +866,6 @@ inrecomp=0; trap = 0; flags_rebuild(); // oldpc=pc; -// oldcs=CS; if (msw&1) { pmodeint(1,0); @@ -894,7 +886,6 @@ inrecomp=0; else if (nmi && nmi_enable && nmi_mask) { cpu_state.oldpc = cpu_state.pc; - oldcs = CS; // pclog("NMI\n"); x86_int(2); nmi_enable = 0; diff --git a/src/808x.c b/src/808x.c index 7368a4e..a20dc29 100644 --- a/src/808x.c +++ b/src/808x.c @@ -88,7 +88,6 @@ void writememl(uint32_t s, uint32_t a, uint32_t v) } -uint16_t oldcs; int oldcpl; int tempc; @@ -481,7 +480,6 @@ void makeznptable() } int timetolive=0; -extern uint32_t oldcs2; extern uint32_t oldpc2; int indump = 0; @@ -571,7 +569,7 @@ void dumpregs() else printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,cpu_state.flags); - printf("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); + printf("%04X %04X\n",cpu_state.oldpc, oldpc2); printf("%i ins\n",ins); if (is386) printf("In %s mode\n",(msw&1)?((cpu_state.eflags&VM_FLAG)?"V86":"protected"):"real"); @@ -1142,7 +1140,6 @@ void execx86(int cycs) { // old83=old82; // old82=old8; -// old8=oldpc|(oldcs<<16); // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; } // if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime); cycdiff=cycles; @@ -1152,7 +1149,6 @@ void execx86(int cycs) nextcyc=0; // if (output) printf("CLOCK %i %i\n",cycdiff,cycles); fetchclocks=0; - oldcs=CS; cpu_state.oldpc = cpu_state.pc; opcodestart: opcode=FETCH(); @@ -3092,7 +3088,7 @@ void execx86(int cycs) break; case 0xF4: /*HLT*/ -// printf("IN HLT!!!! %04X:%04X %08X %08X %08X\n",oldcs,oldpc,old8,old82,old83); +// printf("IN HLT!!!! %04X %08X %08X %08X\n",oldpc,old8,old82,old83); /* if (!(flags & I_FLAG)) { pclog("HLT\n"); diff --git a/src/x86.h b/src/x86.h index 195f52a..5a76ba9 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,4 +1,3 @@ -uint16_t oldcs; extern uint32_t rmdat32; int oldcpl; diff --git a/src/x86seg.c b/src/x86seg.c index 012e930..7876ae0 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -95,7 +95,6 @@ void x86seg_reset() void x86_doabrt(int x86_abrt) { // ingpf = 1; - CS = oldcs; cpu_state.pc = cpu_state.oldpc; cpu_state.seg_cs.access = oldcpl << 5; // pclog("x86_doabrt - %02X %08X %04X:%08X %i\n", x86_abrt, abrt_error, CS, pc, ins); @@ -730,7 +729,6 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) // pclog("Call gate\n"); cgate32=(type&0x800); cgate16=!cgate32; - oldcs=CS; cpu_state.oldpc = cpu_state.pc; if ((DPL < CPL) || (DPL < (seg&3))) { @@ -1267,8 +1265,6 @@ void loadcscall(uint16_t seg) } } // x86abort("Call gate with count %i\n",count); -// PUSHL(oldcs); -// PUSHL(oldpc); if (cpu_state.abrt) return; } else { @@ -1305,8 +1301,6 @@ void loadcscall(uint16_t seg) } // if (output) pclog("Stack %04X\n",SP); // if (count) x86abort("Call gate with count\n"); -// PUSHW(oldcs); -// PUSHW(oldpc); if (cpu_state.abrt) return; } cycles -= timing_call_pm_gate_inner; break; @@ -1318,16 +1312,6 @@ void loadcscall(uint16_t seg) return; } case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ -/* if (type==0xC00) - { - PUSHL(oldcs); - PUSHL(oldpc); if (cpu_state.abrt) return; - } - else - { - PUSHW(oldcs); - PUSHW(oldpc); if (cpu_state.abrt) return; - }*/ CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); From f0225d27102ca1ad45ccb19718655fa550fdc7d6 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 20:30:08 +0000 Subject: [PATCH 118/181] Hide fatal()s in codegen_backend_x86_uops.c behind a RECOMPILER_DEBUG #define. --- src/codegen_backend_x86_uops.c | 342 +++++++++++++++++++++++---------- 1 file changed, 236 insertions(+), 106 deletions(-) diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 9882f82..c6dea83 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -54,9 +54,10 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -84,9 +85,10 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -96,9 +98,10 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); else if (uop->imm_data < 4) host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); +#ifdef RECOMPILER_DEBUG else fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); - +#endif return 0; } @@ -129,9 +132,10 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); host_x86_AND8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -158,9 +162,10 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_AND8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -173,9 +178,10 @@ static int codegen_ANDN(codeblock_t *block, uop_t *uop) { host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -189,10 +195,12 @@ static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); +#ifdef RECOMPILER_DEBUG int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); if (!REG_IS_L(dest_size)) fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); +#endif host_x86_CALL(block, uop->p); host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); @@ -218,8 +226,10 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +#endif host_x86_JZ(block, uop->p); return 0; @@ -238,9 +248,10 @@ static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNZ_long(block); return 0; @@ -258,9 +269,10 @@ static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JZ_long(block); return 0; @@ -283,9 +295,10 @@ static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNB_long(block); return 0; @@ -307,9 +320,10 @@ static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNBE_long(block); return 0; @@ -331,9 +345,10 @@ static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNL_long(block); return 0; @@ -355,9 +370,10 @@ static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNLE_long(block); return 0; @@ -379,9 +395,10 @@ static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNO_long(block); return 0; @@ -403,9 +420,10 @@ static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNZ_long(block); return 0; @@ -427,9 +445,10 @@ static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JB_long(block); return 0; @@ -451,9 +470,10 @@ static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JBE_long(block); return 0; @@ -475,9 +495,10 @@ static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JL_long(block); return 0; @@ -499,9 +520,10 @@ static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JLE_long(block); return 0; @@ -523,9 +545,10 @@ static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JO_long(block); return 0; @@ -547,9 +570,10 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JZ_long(block); return 0; @@ -566,9 +590,10 @@ static int codegen_FABS(codeblock_t *block, uop_t *uop) host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_FCHS(codeblock_t *block, uop_t *uop) @@ -582,9 +607,10 @@ static int codegen_FCHS(codeblock_t *block, uop_t *uop) host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_FSQRT(codeblock_t *block, uop_t *uop) @@ -596,9 +622,10 @@ static int codegen_FSQRT(codeblock_t *block, uop_t *uop) { host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_FTST(codeblock_t *block, uop_t *uop) @@ -621,9 +648,10 @@ static int codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -636,9 +664,10 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) { host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FCOM(codeblock_t *block, uop_t *uop) @@ -660,9 +689,10 @@ static int codegen_FCOM(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FDIV(codeblock_t *block, uop_t *uop) @@ -680,9 +710,10 @@ static int codegen_FDIV(codeblock_t *block, uop_t *uop) host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FMUL(codeblock_t *block, uop_t *uop) @@ -694,9 +725,10 @@ static int codegen_FMUL(codeblock_t *block, uop_t *uop) { host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FSUB(codeblock_t *block, uop_t *uop) @@ -714,9 +746,10 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -778,24 +811,31 @@ static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) { host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); - +#endif return 0; } static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); +#endif return 0; } static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); +#endif return 0; } static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); +#endif return 0; } @@ -823,10 +863,12 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) { int src_reg = HOST_REG_GET(uop->src_reg_a_real); +#ifdef RECOMPILER_DEBUG int src_size = IREG_GET_SIZE(uop->src_reg_a_real); if (!REG_IS_W(src_size)) fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +#endif host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t)uop->p); host_x86_CALL(block, loadseg); @@ -854,8 +896,10 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_long); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) @@ -897,8 +941,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_quad); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) @@ -923,11 +969,12 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); +#ifdef RECOMPILER_DEBUG int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); if (!REG_IS_D(dest_size)) fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -942,11 +989,12 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); +#ifdef RECOMPILER_DEBUG int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); if (!REG_IS_D(dest_size)) fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -979,8 +1027,10 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1015,8 +1065,10 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_quad); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1063,11 +1115,12 @@ static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) { int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); +#ifdef RECOMPILER_DEBUG int src_size = IREG_GET_SIZE(uop->src_reg_c_real); if (!REG_IS_D(src_size)) fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -1081,11 +1134,12 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) { int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); +#ifdef RECOMPILER_DEBUG int src_size = IREG_GET_SIZE(uop->src_reg_c_real); if (!REG_IS_D(src_size)) fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -1122,9 +1176,10 @@ static int codegen_MOV(codeblock_t *block, uop_t *uop) { host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) @@ -1144,9 +1199,10 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) @@ -1171,8 +1227,10 @@ static int codegen_MOVSX(codeblock_t *block, uop_t *uop) { host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif return 0; } static int codegen_MOVZX(codeblock_t *block, uop_t *uop) @@ -1200,8 +1258,10 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif return 0; } @@ -1228,9 +1288,10 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_x87_FSTPd_BASE(block, REG_ESP); host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); } +#ifdef RECOMPILER_DEBUG else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) @@ -1251,9 +1312,10 @@ static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } +#ifdef RECOMPILER_DEBUG else fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1282,9 +1344,10 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; } +#ifdef RECOMPILER_DEBUG else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1313,9 +1376,10 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) { host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) @@ -1335,9 +1399,10 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1350,9 +1415,10 @@ static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) { host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) @@ -1364,9 +1430,10 @@ static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) { host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) @@ -1378,9 +1445,10 @@ static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) { host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1393,9 +1461,10 @@ static int codegen_PADDB(codeblock_t *block, uop_t *uop) { host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDW(codeblock_t *block, uop_t *uop) @@ -1407,9 +1476,10 @@ static int codegen_PADDW(codeblock_t *block, uop_t *uop) { host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDD(codeblock_t *block, uop_t *uop) @@ -1421,9 +1491,10 @@ static int codegen_PADDD(codeblock_t *block, uop_t *uop) { host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDSB(codeblock_t *block, uop_t *uop) @@ -1435,9 +1506,10 @@ static int codegen_PADDSB(codeblock_t *block, uop_t *uop) { host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDSW(codeblock_t *block, uop_t *uop) @@ -1449,9 +1521,10 @@ static int codegen_PADDSW(codeblock_t *block, uop_t *uop) { host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) @@ -1463,9 +1536,10 @@ static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) { host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) @@ -1477,9 +1551,10 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) { host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1492,9 +1567,10 @@ static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) { host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) @@ -1506,9 +1582,10 @@ static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) { host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) @@ -1520,9 +1597,10 @@ static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) { host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) @@ -1534,9 +1612,10 @@ static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) { host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) @@ -1548,9 +1627,10 @@ static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) { host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) @@ -1562,9 +1642,10 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) { host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1579,9 +1660,10 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } +#ifdef RECOMPILER_DEBUG else fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_PFADD(codeblock_t *block, uop_t *uop) @@ -1593,9 +1675,10 @@ static int codegen_PFADD(codeblock_t *block, uop_t *uop) { host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) @@ -1607,9 +1690,10 @@ static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) { host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); } +#ifdef RECOMPILER_DEBUG else fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) @@ -1621,9 +1705,10 @@ static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) { host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); } +#ifdef RECOMPILER_DEBUG else fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) @@ -1635,9 +1720,10 @@ static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) { host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); } +#ifdef RECOMPILER_DEBUG else fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFMAX(codeblock_t *block, uop_t *uop) @@ -1649,9 +1735,10 @@ static int codegen_PFMAX(codeblock_t *block, uop_t *uop) { host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFMIN(codeblock_t *block, uop_t *uop) @@ -1663,9 +1750,10 @@ static int codegen_PFMIN(codeblock_t *block, uop_t *uop) { host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFMUL(codeblock_t *block, uop_t *uop) @@ -1677,9 +1765,10 @@ static int codegen_PFMUL(codeblock_t *block, uop_t *uop) { host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFRCP(codeblock_t *block, uop_t *uop) @@ -1696,9 +1785,10 @@ static int codegen_PFRCP(codeblock_t *block, uop_t *uop) host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) @@ -1715,9 +1805,10 @@ static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_PFSUB(codeblock_t *block, uop_t *uop) @@ -1735,9 +1826,10 @@ static int codegen_PFSUB(codeblock_t *block, uop_t *uop) host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PI2FD(codeblock_t *block, uop_t *uop) @@ -1749,9 +1841,10 @@ static int codegen_PI2FD(codeblock_t *block, uop_t *uop) { host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); } +#ifdef RECOMPILER_DEBUG else fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } @@ -1764,9 +1857,10 @@ static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PMULHW(codeblock_t *block, uop_t *uop) @@ -1778,9 +1872,10 @@ static int codegen_PMULHW(codeblock_t *block, uop_t *uop) { host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PMULLW(codeblock_t *block, uop_t *uop) @@ -1792,9 +1887,10 @@ static int codegen_PMULLW(codeblock_t *block, uop_t *uop) { host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1807,9 +1903,10 @@ static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) @@ -1821,9 +1918,10 @@ static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) @@ -1835,9 +1933,10 @@ static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) @@ -1849,9 +1948,10 @@ static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) @@ -1863,9 +1963,10 @@ static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) @@ -1877,9 +1978,10 @@ static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) @@ -1891,9 +1993,10 @@ static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) @@ -1905,9 +2008,10 @@ static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) @@ -1919,9 +2023,10 @@ static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1934,9 +2039,10 @@ static int codegen_PSUBB(codeblock_t *block, uop_t *uop) { host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBW(codeblock_t *block, uop_t *uop) @@ -1948,9 +2054,10 @@ static int codegen_PSUBW(codeblock_t *block, uop_t *uop) { host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBD(codeblock_t *block, uop_t *uop) @@ -1962,9 +2069,10 @@ static int codegen_PSUBD(codeblock_t *block, uop_t *uop) { host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) @@ -1976,9 +2084,10 @@ static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) { host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) @@ -1990,9 +2099,10 @@ static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) { host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) @@ -2004,9 +2114,10 @@ static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) { host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) @@ -2018,9 +2129,10 @@ static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) { host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -2033,9 +2145,10 @@ static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) @@ -2047,9 +2160,10 @@ static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) @@ -2061,9 +2175,10 @@ static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) @@ -2075,9 +2190,10 @@ static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) @@ -2089,9 +2205,10 @@ static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) @@ -2103,9 +2220,10 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -2133,9 +2251,10 @@ static int codegen_SAR(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SAR8_CL(block, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) @@ -2161,9 +2280,10 @@ static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHL(codeblock_t *block, uop_t *uop) @@ -2190,9 +2310,10 @@ static int codegen_SHL(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHL8_CL(block, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) @@ -2218,9 +2339,10 @@ static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHR(codeblock_t *block, uop_t *uop) @@ -2247,9 +2369,10 @@ static int codegen_SHR(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHR8_CL(block, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) @@ -2275,9 +2398,10 @@ static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -2315,9 +2439,10 @@ static int codegen_SUB(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) @@ -2343,9 +2468,10 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -2366,9 +2492,10 @@ static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) { host_x86_TEST8_REG(block, src_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNS_long(block); return 0; @@ -2390,9 +2517,10 @@ static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) { host_x86_TEST8_REG(block, src_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JS_long(block); return 0; @@ -2419,9 +2547,10 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) { host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) @@ -2441,9 +2570,10 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } From b018dc1005eea20ea78fa6478452419f8d48d5d0 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 21:08:01 +0000 Subject: [PATCH 119/181] Remove fake 3-operand instructions in x86 backend. --- src/codegen_backend_x86.c | 16 +-- src/codegen_backend_x86_ops.c | 182 +++++++++------------------------ src/codegen_backend_x86_ops.h | 62 +++++------ src/codegen_backend_x86_uops.c | 137 +++++++++++++------------ 4 files changed, 157 insertions(+), 240 deletions(-) diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 6119ea2..7beffc5 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -99,7 +99,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); else fatal("build_load_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); host_x86_RET(block); *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; @@ -189,7 +189,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); else fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); host_x86_RET(block); *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; @@ -203,7 +203,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) if (size == 8) { host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); - host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 8); + host_x86_SUB32_REG_IMM(block, REG_ESP, 8); } host_x86_PUSH(block, REG_EDI); if (size == 1) @@ -216,7 +216,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_CALL(block, (void *)writememql); host_x86_POP(block, REG_EDI); if (size == 8) - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 8); + host_x86_ADD32_REG_IMM(block, REG_ESP, 8); host_x86_POP(block, REG_ECX); host_x86_POP(block, REG_EDX); host_x86_POP(block, REG_EAX); @@ -309,7 +309,7 @@ pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); host_x86_CALL(block, (void *)x86gpf); codegen_exit_rout = &codeblock[block_current].data[block_pos]; - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_ADD32_REG_IMM(block, REG_ESP, 64); host_x86_POP(block, REG_EDI); host_x86_POP(block, REG_ESI); host_x86_POP(block, REG_EBP); @@ -342,19 +342,19 @@ void codegen_backend_prologue(codeblock_t *block) host_x86_PUSH(block, REG_EBP); host_x86_PUSH(block, REG_ESI); host_x86_PUSH(block, REG_EDI); - host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_SUB32_REG_IMM(block, REG_ESP, 64); host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); - host_x86_SUB32_REG_IMM(block, REG_EAX, REG_EAX, block->TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); } } void codegen_backend_epilogue(codeblock_t *block) { - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64); + host_x86_ADD32_REG_IMM(block, REG_ESP, 64); host_x86_POP(block, REG_EDI); host_x86_POP(block, REG_ESI); host_x86_POP(block, REG_EBP); diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 2d9ef2c..47f7493 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -103,7 +103,7 @@ static int is_imm8(uint32_t imm_data) return 0; } -void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void *p) +void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -121,11 +121,8 @@ void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void * } } -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); - if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -137,11 +134,8 @@ void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ } } -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -160,11 +154,8 @@ void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -184,29 +175,20 @@ void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 } } -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) @@ -220,11 +202,8 @@ void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); - if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -236,11 +215,8 @@ void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ } } -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -259,11 +235,8 @@ void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -283,29 +256,20 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 } } -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ } -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ } -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ } void host_x86_CALL(codeblock_t *block, void *p) @@ -1263,36 +1227,24 @@ void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ } -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ } -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ } -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); - if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -1304,11 +1256,8 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ } } -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1327,11 +1276,8 @@ void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_ codegen_addword(block, imm_data); } } -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -1732,11 +1678,8 @@ void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ } -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); - if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -1748,11 +1691,8 @@ void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ } } -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1771,11 +1711,8 @@ void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -1795,29 +1732,20 @@ void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 } } -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) @@ -1868,36 +1796,24 @@ void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); - if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -1909,11 +1825,8 @@ void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ } } -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1932,11 +1845,8 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); - if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 22a8746..db7b37c 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -1,23 +1,23 @@ -void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void *p); +void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CALL(codeblock_t *block, void *p); @@ -165,13 +165,13 @@ void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -259,13 +259,13 @@ void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -278,13 +278,13 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_ void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); void host_x87_FILDq_BASE(codeblock_t *block, int base_reg); void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index c6dea83..55bcc13 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -40,19 +40,19 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); else - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -71,19 +71,19 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); else - host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ADD16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -95,7 +95,12 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { if (!uop->imm_data) - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + { + if (uop->dest_reg_a_real == uop->src_reg_a_real) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); + else + host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + } else if (uop->imm_data < 4) host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); #ifdef RECOMPILER_DEBUG @@ -118,19 +123,19 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -148,19 +153,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_AND32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_AND16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_AND8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -638,10 +643,10 @@ static int codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); if (dest_reg != REG_EAX) host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); @@ -679,10 +684,10 @@ static int codegen_FCOM(codeblock_t *block, uop_t *uop) { if (dest_reg != REG_EAX) host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); @@ -924,7 +929,7 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); if (REG_IS_B(dest_size)) { host_x86_CALL(block, codegen_mem_load_byte); @@ -977,7 +982,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -997,7 +1002,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1044,7 +1049,7 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); if (REG_IS_B(src_size)) { host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); @@ -1123,7 +1128,7 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -1142,7 +1147,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -1364,17 +1369,19 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -1385,19 +1392,19 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + if (REG_IS_L(dest_size) && dest_reg == src_reg) { - host_x86_OR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + else if (REG_IS_W(dest_size) && dest_reg == src_reg) { - host_x86_OR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + else if (REG_IS_B(dest_size) && dest_reg == src_reg) { - host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -2425,19 +2432,19 @@ static int codegen_SUB(codeblock_t *block, uop_t *uop) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { if (uop->dest_reg_a_real != uop->src_reg_a_real) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -2454,19 +2461,19 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { if (dest_reg != src_reg) host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SUB32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { if (dest_reg != src_reg) host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SUB16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { if (dest_reg != src_reg) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -2528,24 +2535,24 @@ static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) static int codegen_XOR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -2555,20 +2562,20 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + if (REG_IS_L(dest_size) && REG_IS_L(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -2783,8 +2790,8 @@ void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 0); } void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) @@ -2792,8 +2799,8 @@ void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) @@ -2801,8 +2808,8 @@ void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } @@ -2831,8 +2838,8 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); } void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) @@ -2840,8 +2847,8 @@ void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) @@ -2849,8 +2856,8 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } From 9283ab5fef3632ef7e52c1ad858f52f177f96c44 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 21:21:47 +0000 Subject: [PATCH 120/181] Hide fatal()s in codegen_backend_x86-64_uops.c behind a RECOMPILER_DEBUG #define. --- src/codegen_backend_x86-64_uops.c | 350 +++++++++++++++++++++--------- 1 file changed, 244 insertions(+), 106 deletions(-) diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 79bfed3..7b475bf 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -48,9 +48,10 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -78,9 +79,10 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -90,9 +92,10 @@ static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); else if (uop->imm_data < 4) host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); +#ifdef RECOMPILER_DEBUG else fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); - +#endif return 0; } @@ -123,9 +126,10 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); host_x86_AND8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -152,9 +156,10 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_AND8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -167,9 +172,10 @@ static int codegen_ANDN(codeblock_t *block, uop_t *uop) { host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -185,8 +191,10 @@ static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); +#ifdef RECOMPILER_DEBUG if (!REG_IS_L(dest_size)) fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); +#endif host_x86_CALL(block, uop->p); host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); @@ -211,8 +219,10 @@ static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +#endif host_x86_JZ(block, uop->p); return 0; @@ -231,9 +241,10 @@ static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNZ_long(block); return 0; @@ -251,9 +262,10 @@ static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JZ_long(block); return 0; @@ -276,9 +288,10 @@ static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNB_long(block); return 0; @@ -300,9 +313,10 @@ static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNBE_long(block); return 0; @@ -324,9 +338,10 @@ static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNL_long(block); return 0; @@ -348,9 +363,10 @@ static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNLE_long(block); return 0; @@ -372,9 +388,10 @@ static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNO_long(block); return 0; @@ -396,9 +413,10 @@ static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNZ_long(block); return 0; @@ -420,9 +438,10 @@ static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JB_long(block); return 0; @@ -444,9 +463,10 @@ static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JBE_long(block); return 0; @@ -468,9 +488,10 @@ static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JL_long(block); return 0; @@ -492,9 +513,10 @@ static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JLE_long(block); return 0; @@ -516,9 +538,10 @@ static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JO_long(block); return 0; @@ -540,9 +563,10 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JZ_long(block); return 0; @@ -559,9 +583,10 @@ static int codegen_FABS(codeblock_t *block, uop_t *uop) host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_FCHS(codeblock_t *block, uop_t *uop) @@ -575,9 +600,10 @@ static int codegen_FCHS(codeblock_t *block, uop_t *uop) host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_FSQRT(codeblock_t *block, uop_t *uop) @@ -589,9 +615,10 @@ static int codegen_FSQRT(codeblock_t *block, uop_t *uop) { host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_FTST(codeblock_t *block, uop_t *uop) @@ -614,9 +641,10 @@ static int codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -629,9 +657,10 @@ static int codegen_FADD(codeblock_t *block, uop_t *uop) { host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FCOM(codeblock_t *block, uop_t *uop) @@ -653,9 +682,10 @@ static int codegen_FCOM(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FDIV(codeblock_t *block, uop_t *uop) @@ -673,9 +703,10 @@ static int codegen_FDIV(codeblock_t *block, uop_t *uop) host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FMUL(codeblock_t *block, uop_t *uop) @@ -687,9 +718,10 @@ static int codegen_FMUL(codeblock_t *block, uop_t *uop) { host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_FSUB(codeblock_t *block, uop_t *uop) @@ -707,9 +739,10 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop) host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -776,24 +809,31 @@ static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) host_x86_MOVZX_REG_32_16(block, REG_EDI, src_reg); #endif } +#ifdef RECOMPILER_DEBUG else fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); - +#endif return 0; } static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); +#endif return 0; } static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); +#endif return 0; } static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); +#endif return 0; } @@ -817,12 +857,16 @@ static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) } static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG2_IMM\n"); +#endif return 0; } static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG fatal("codegen_LOAD_FUNC_ARG3_IMM\n"); +#endif return 0; } @@ -831,8 +875,10 @@ static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) int src_reg = HOST_REG_GET(uop->src_reg_a_real); int src_size = IREG_GET_SIZE(uop->src_reg_a_real); +#ifdef RECOMPILER_DEBUG if (!REG_IS_W(src_size)) fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +#endif #if WIN64 host_x86_MOV16_REG_REG(block, REG_CX, src_reg); host_x86_MOV64_REG_IMM(block, REG_EDX, (uint64_t)uop->p); @@ -865,8 +911,10 @@ static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_long); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) @@ -908,8 +956,10 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { host_x86_CALL(block, codegen_mem_load_quad); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); if (REG_IS_B(dest_size)) @@ -936,9 +986,10 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); +#ifdef RECOMPILER_DEBUG if (!REG_IS_D(dest_size)) fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -954,9 +1005,10 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); +#ifdef RECOMPILER_DEBUG if (!REG_IS_D(dest_size)) fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -989,8 +1041,10 @@ static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1062,8 +1116,10 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_quad); } +#ifdef RECOMPILER_DEBUG else fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); +#endif host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1075,9 +1131,10 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); int src_size = IREG_GET_SIZE(uop->src_reg_c_real); +#ifdef RECOMPILER_DEBUG if (!REG_IS_D(src_size)) fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -1093,9 +1150,10 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); int src_size = IREG_GET_SIZE(uop->src_reg_c_real); +#ifdef RECOMPILER_DEBUG if (!REG_IS_D(src_size)) fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); - +#endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); @@ -1132,9 +1190,10 @@ static int codegen_MOV(codeblock_t *block, uop_t *uop) { host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) @@ -1154,9 +1213,10 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) @@ -1181,8 +1241,10 @@ static int codegen_MOVSX(codeblock_t *block, uop_t *uop) { host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif return 0; } static int codegen_MOVZX(codeblock_t *block, uop_t *uop) @@ -1210,8 +1272,10 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) { host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif return 0; } @@ -1234,9 +1298,10 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); } +#ifdef RECOMPILER_DEBUG else fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) @@ -1257,9 +1322,10 @@ static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } +#ifdef RECOMPILER_DEBUG else fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) @@ -1283,9 +1349,10 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; } +#ifdef RECOMPILER_DEBUG else fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1314,9 +1381,10 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) { host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) @@ -1336,9 +1404,10 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) { host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1351,9 +1420,10 @@ static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) { host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) @@ -1365,9 +1435,10 @@ static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) { host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) @@ -1379,9 +1450,10 @@ static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) { host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1394,9 +1466,10 @@ static int codegen_PADDB(codeblock_t *block, uop_t *uop) { host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDW(codeblock_t *block, uop_t *uop) @@ -1408,9 +1481,10 @@ static int codegen_PADDW(codeblock_t *block, uop_t *uop) { host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDD(codeblock_t *block, uop_t *uop) @@ -1422,9 +1496,10 @@ static int codegen_PADDD(codeblock_t *block, uop_t *uop) { host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDSB(codeblock_t *block, uop_t *uop) @@ -1436,9 +1511,10 @@ static int codegen_PADDSB(codeblock_t *block, uop_t *uop) { host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDSW(codeblock_t *block, uop_t *uop) @@ -1450,9 +1526,10 @@ static int codegen_PADDSW(codeblock_t *block, uop_t *uop) { host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) @@ -1464,9 +1541,10 @@ static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) { host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) @@ -1478,9 +1556,10 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) { host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1493,9 +1572,10 @@ static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) { host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) @@ -1507,9 +1587,10 @@ static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) { host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) @@ -1521,9 +1602,10 @@ static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) { host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) @@ -1535,9 +1617,10 @@ static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) { host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) @@ -1549,9 +1632,10 @@ static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) { host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) @@ -1563,9 +1647,10 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) { host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1580,9 +1665,10 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } +#ifdef RECOMPILER_DEBUG else fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_PFADD(codeblock_t *block, uop_t *uop) @@ -1594,9 +1680,10 @@ static int codegen_PFADD(codeblock_t *block, uop_t *uop) { host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) @@ -1608,9 +1695,10 @@ static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) { host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); } +#ifdef RECOMPILER_DEBUG else fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) @@ -1622,9 +1710,10 @@ static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) { host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); } +#ifdef RECOMPILER_DEBUG else fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) @@ -1636,9 +1725,10 @@ static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) { host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); } +#ifdef RECOMPILER_DEBUG else fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFMAX(codeblock_t *block, uop_t *uop) @@ -1650,9 +1740,10 @@ static int codegen_PFMAX(codeblock_t *block, uop_t *uop) { host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFMIN(codeblock_t *block, uop_t *uop) @@ -1664,9 +1755,10 @@ static int codegen_PFMIN(codeblock_t *block, uop_t *uop) { host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFMUL(codeblock_t *block, uop_t *uop) @@ -1678,9 +1770,10 @@ static int codegen_PFMUL(codeblock_t *block, uop_t *uop) { host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PFRCP(codeblock_t *block, uop_t *uop) @@ -1697,9 +1790,10 @@ static int codegen_PFRCP(codeblock_t *block, uop_t *uop) host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) @@ -1716,9 +1810,10 @@ static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } static int codegen_PFSUB(codeblock_t *block, uop_t *uop) @@ -1736,9 +1831,10 @@ static int codegen_PFSUB(codeblock_t *block, uop_t *uop) host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } +#ifdef RECOMPILER_DEBUG else fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PI2FD(codeblock_t *block, uop_t *uop) @@ -1750,9 +1846,10 @@ static int codegen_PI2FD(codeblock_t *block, uop_t *uop) { host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); } +#ifdef RECOMPILER_DEBUG else fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); - +#endif return 0; } @@ -1765,9 +1862,10 @@ static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PMULHW(codeblock_t *block, uop_t *uop) @@ -1779,9 +1877,10 @@ static int codegen_PMULHW(codeblock_t *block, uop_t *uop) { host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PMULLW(codeblock_t *block, uop_t *uop) @@ -1793,9 +1892,10 @@ static int codegen_PMULLW(codeblock_t *block, uop_t *uop) { host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -1808,9 +1908,10 @@ static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) @@ -1822,9 +1923,10 @@ static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) @@ -1836,9 +1938,10 @@ static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) @@ -1850,9 +1953,10 @@ static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) @@ -1864,9 +1968,10 @@ static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) @@ -1878,9 +1983,10 @@ static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) @@ -1892,9 +1998,10 @@ static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) @@ -1906,9 +2013,10 @@ static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) @@ -1920,9 +2028,10 @@ static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) { host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -1935,9 +2044,10 @@ static int codegen_PSUBB(codeblock_t *block, uop_t *uop) { host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBW(codeblock_t *block, uop_t *uop) @@ -1949,9 +2059,10 @@ static int codegen_PSUBW(codeblock_t *block, uop_t *uop) { host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBD(codeblock_t *block, uop_t *uop) @@ -1963,9 +2074,10 @@ static int codegen_PSUBD(codeblock_t *block, uop_t *uop) { host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) @@ -1977,9 +2089,10 @@ static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) { host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) @@ -1991,9 +2104,10 @@ static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) { host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) @@ -2005,9 +2119,10 @@ static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) { host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) @@ -2019,9 +2134,10 @@ static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) { host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -2034,9 +2150,10 @@ static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) @@ -2048,9 +2165,10 @@ static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) @@ -2062,9 +2180,10 @@ static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) @@ -2076,9 +2195,10 @@ static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) @@ -2090,9 +2210,10 @@ static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) @@ -2104,9 +2225,10 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) { host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } @@ -2134,9 +2256,10 @@ static int codegen_SAR(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SAR8_CL(block, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) @@ -2162,9 +2285,10 @@ static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHL(codeblock_t *block, uop_t *uop) @@ -2191,9 +2315,10 @@ static int codegen_SHL(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHL8_CL(block, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) @@ -2219,9 +2344,10 @@ static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHR(codeblock_t *block, uop_t *uop) @@ -2248,9 +2374,10 @@ static int codegen_SHR(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHR8_CL(block, dest_reg); } +#ifdef RECOMPILER_DEBUG else fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) @@ -2276,23 +2403,28 @@ static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG if (((uintptr_t)uop->p) >> 32) fatal("STORE_PTR_IMM 64-bit addr\n"); +#endif host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); return 0; } static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) { +#ifdef RECOMPILER_DEBUG if (((uintptr_t)uop->p) >> 32) fatal("STORE_PTR_IMM_8 64-bit addr\n"); +#endif host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); return 0; } @@ -2320,9 +2452,10 @@ static int codegen_SUB(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) @@ -2348,9 +2481,10 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } @@ -2371,9 +2505,10 @@ static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) { host_x86_TEST8_REG(block, src_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JNS_long(block); return 0; @@ -2395,9 +2530,10 @@ static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) { host_x86_TEST8_REG(block, src_reg, src_reg); } +#ifdef RECOMPILER_DEBUG else fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); - +#endif uop->p = host_x86_JS_long(block); return 0; @@ -2424,9 +2560,10 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) { host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); } +#ifdef RECOMPILER_DEBUG else fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - +#endif return 0; } static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) @@ -2446,9 +2583,10 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); } +#ifdef RECOMPILER_DEBUG else fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - +#endif return 0; } From e822460f333a16d177dce7d4699763917e6b8795 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 21:22:03 +0000 Subject: [PATCH 121/181] Fix missing function prototypes in codegen_backend_x86-64_ops.h. --- src/codegen_backend_x86-64_ops.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 209e270..0f99fe9 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -99,6 +99,7 @@ void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg); void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); +void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg); void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p); void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p); @@ -113,6 +114,7 @@ void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int ba void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); +void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data); void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data); @@ -160,6 +162,7 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); From 9060f4552f7629ee106645447edb3db0fa41f693 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 28 Jan 2019 21:56:57 +0000 Subject: [PATCH 122/181] Remove fake 3-operand instructions in x86-64 backend. --- src/codegen_backend_x86-64.c | 22 ++-- src/codegen_backend_x86-64_ops.c | 210 +++++++++++++++--------------- src/codegen_backend_x86-64_ops.h | 60 ++++----- src/codegen_backend_x86-64_uops.c | 119 +++++++++-------- 4 files changed, 209 insertions(+), 202 deletions(-) diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 2c1d970..01eec22 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -100,7 +100,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); else fatal("build_load_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); host_x86_RET(block); *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; @@ -198,7 +198,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); else fatal("build_store_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); host_x86_RET(block); *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; @@ -305,15 +305,15 @@ void codegen_backend_init() codegen_gpf_rout = &codeblock[block_current].data[block_pos]; #if WIN64 - host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX, REG_ECX); - host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX, REG_EDX); + host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX); + host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX); #else - host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI, REG_EDI); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI); + host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); #endif host_x86_CALL(block, (uintptr_t)x86gpf); codegen_exit_rout = &codeblock[block_current].data[block_pos]; - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); host_x86_POP(block, REG_R15); host_x86_POP(block, REG_R14); host_x86_POP(block, REG_R13); @@ -349,19 +349,19 @@ void codegen_backend_prologue(codeblock_t *block) host_x86_PUSH(block, REG_R13); host_x86_PUSH(block, REG_R14); host_x86_PUSH(block, REG_R15); - host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38); host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128); if (block->flags & CODEBLOCK_HAS_FPU) { host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); - host_x86_SUB32_REG_IMM(block, REG_EAX, REG_EAX, block->TOP); - host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); + host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX); } } void codegen_backend_epilogue(codeblock_t *block) { - host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38); + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); host_x86_POP(block, REG_R15); host_x86_POP(block, REG_R14); host_x86_POP(block, REG_R13); diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 90700fe..9e9928d 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -163,10 +163,10 @@ static inline void jmp(codeblock_t *block, uintptr_t func) } } -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\n"); if (dst_reg == REG_EAX) { @@ -179,10 +179,10 @@ void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ } } -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -202,10 +202,10 @@ void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -238,29 +238,29 @@ void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) else fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); } -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD8_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD8_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD16_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD16_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_ADD32_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ } void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) @@ -274,10 +274,10 @@ void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND8_REG_IMM - dst_reg & 8\n"); if (dst_reg == REG_EAX) { @@ -290,10 +290,10 @@ void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ } } -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND16_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -313,10 +313,10 @@ void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND32_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -336,29 +336,29 @@ void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 codegen_addlong(block, imm_data); } } -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND8_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ } -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND16_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ } -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ } void host_x86_CALL(codeblock_t *block, void *p) @@ -1512,10 +1512,10 @@ void host_x86_NOP(codeblock_t *block) codegen_addbyte(block, 0x90); /*NOP*/ } -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); if (dst_reg == REG_EAX) { @@ -1528,10 +1528,10 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ } } -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -1551,10 +1551,10 @@ void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_ codegen_addword(block, imm_data); } } -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -1574,29 +1574,29 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_ codegen_addlong(block, imm_data); } } -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ } -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ } -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ } void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) @@ -2046,10 +2046,10 @@ void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ } -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\n"); if (dst_reg == REG_EAX) { @@ -2062,10 +2062,10 @@ void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ } } -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -2085,10 +2085,10 @@ void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -2121,29 +2121,29 @@ void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) else fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); } -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB8_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB16_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB32_REG_REG - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ } void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) @@ -2201,10 +2201,10 @@ void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data) +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); if (dst_reg == REG_EAX) { @@ -2217,10 +2217,10 @@ void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ } } -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data) +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -2240,10 +2240,10 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16 codegen_addword(block, imm_data); } } -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data) +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n"); + if (dst_reg & 8) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); if (is_imm8(imm_data)) { @@ -2263,29 +2263,29 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32 codegen_addlong(block, imm_data); } } -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8)) - fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } #endif diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 0f99fe9..aa7e0c7 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -1,22 +1,22 @@ -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data); -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_CALL(codeblock_t *block, void *p); @@ -168,13 +168,13 @@ void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_NOP(codeblock_t *block); -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -262,14 +262,14 @@ void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data); -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -281,10 +281,10 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data); -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data); -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data); +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); +void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 7b475bf..e17ad0e 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -34,19 +34,19 @@ static int codegen_ADD(codeblock_t *block, uop_t *uop) if (dest_reg != src_reg_a) host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); else - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -65,19 +65,19 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) if (dest_reg != src_reg) host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); else - host_x86_ADD32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { if (dest_reg != src_reg) host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ADD16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { if (dest_reg != src_reg) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ADD8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -89,7 +89,12 @@ static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { if (!uop->imm_data) - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + { + if (uop->dest_reg_a_real == uop->src_reg_a_real) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); + else + host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + } else if (uop->imm_data < 4) host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); #ifdef RECOMPILER_DEBUG @@ -112,19 +117,19 @@ static int codegen_AND(codeblock_t *block, uop_t *uop) { if (dest_reg != src_reg_a) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -142,19 +147,19 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) { if (dest_reg != src_reg) host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_AND32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { if (dest_reg != src_reg) host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_AND16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { if (dest_reg != src_reg) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_AND8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -631,10 +636,10 @@ static int codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); if (dest_reg != REG_EAX) host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); @@ -672,10 +677,10 @@ static int codegen_FCOM(codeblock_t *block, uop_t *uop) { if (dest_reg != REG_EAX) host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, REG_EAX, C0|C2|C3); + host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); @@ -939,7 +944,7 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); if (REG_IS_B(dest_size)) { host_x86_CALL(block, codegen_mem_load_byte); @@ -992,7 +997,7 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1011,7 +1016,7 @@ static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_CALL(block, codegen_mem_load_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); host_x86_JNZ(block, codegen_exit_rout); @@ -1095,7 +1100,7 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); if (REG_IS_B(src_size)) { host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); @@ -1137,7 +1142,7 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_single); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -1156,7 +1161,7 @@ static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) #endif host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, REG_ESI, uop->imm_data); + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); host_x86_CALL(block, codegen_mem_store_double); host_x86_TEST32_REG(block, REG_ESI, REG_ESI); @@ -1369,17 +1374,19 @@ static int codegen_OR(codeblock_t *block, uop_t *uop) { if (dest_reg != src_reg_a) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { - host_x86_OR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -1394,15 +1401,15 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_OR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_OR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_OR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -2438,19 +2445,19 @@ static int codegen_SUB(codeblock_t *block, uop_t *uop) { if (dest_reg != src_reg_a) host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB32_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB16_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { if (dest_reg != src_reg_a) host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB8_REG_REG(block, dest_reg, dest_reg, src_reg_b); + host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -2467,19 +2474,19 @@ static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { if (dest_reg != src_reg) host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SUB32_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { if (dest_reg != src_reg) host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SUB16_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { if (dest_reg != src_reg) host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SUB8_REG_IMM(block, dest_reg, dest_reg, uop->imm_data); + host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -2548,17 +2555,17 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop) { host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR32_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR16_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) + else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_x86_XOR8_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); } #ifdef RECOMPILER_DEBUG else @@ -2573,15 +2580,15 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { - host_x86_XOR32_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { - host_x86_XOR16_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { - host_x86_XOR8_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); } #ifdef RECOMPILER_DEBUG else @@ -2781,8 +2788,8 @@ void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 0); } void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) @@ -2790,8 +2797,8 @@ void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) @@ -2799,8 +2806,8 @@ void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } @@ -2833,8 +2840,8 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); } void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) @@ -2842,8 +2849,8 @@ void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) @@ -2851,8 +2858,8 @@ void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } From 2ccf771cf3d341a455def1710225ea72c0fbc915 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 1 Feb 2019 20:11:08 +0000 Subject: [PATCH 123/181] Cleaned up exec386_dynarec() a bit. --- src/386_dynarec.c | 696 ++++++++++++++++++++++------------------------ 1 file changed, 333 insertions(+), 363 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 0137238..3e77c8a 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -506,7 +506,7 @@ int dontprint=0; #include "386_ops.h" -#define CACHE_ON() (!(cr0 & (1 << 30)) /*&& (cr0 & 1)*/ && !(cpu_state.flags & T_FLAG)) +#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) //#define CACHE_ON() 0 static int cycles_main = 0; @@ -518,7 +518,7 @@ void exec386_dynarec(int cycs) int cycdiff; int oldcyc; int cyc_period = cycs / 2000; /*5us*/ -//output = 3; + cycles_main += cycs; while (cycles_main > 0) { @@ -527,385 +527,317 @@ void exec386_dynarec(int cycs) cycles += cyc_period; cycles_start = cycles; -// output=3; - while (cycles>0) - { - oldcyc=cycles; -// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); - if (!CACHE_ON()) /*Interpret block*/ + while (cycles>0) { - cpu_block_end = 0; - x86_was_reset = 0; -// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); - while (!cpu_block_end) + oldcyc=cycles; +// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); + if (!CACHE_ON()) /*Interpret block*/ { - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + cpu_block_end = 0; + x86_was_reset = 0; +// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); + while (!cpu_block_end) + { + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; - fetchdat = fastreadl(cs + cpu_state.pc); -// if (!fetchdat) -// fatal("Dead with cache off\n"); - if (!cpu_state.abrt) - { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; - fetchdat >>= 8; + fetchdat = fastreadl(cs + cpu_state.pc); -// if (output == 3) -// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); - - cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - } - - if (((cs + cpu_state.pc) >> 12) != pccache) - CPU_BLOCK_END(); - -/* if (ssegs) - { - ds=oldds; - ss=oldss; - ssegs=0; - }*/ - if (cpu_state.abrt) - CPU_BLOCK_END(); - if (trap) - CPU_BLOCK_END(); - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - - ins++; - insc++; - -/* if ((cs + pc) == 4) - fatal("4\n");*/ -/* if (ins >= 141400000) - output = 3;*/ - } - } - else - { - uint32_t phys_addr = get_phys(cs+cpu_state.pc); - int hash = HASH(phys_addr); - codeblock_t *block = &codeblock[codeblock_hash[hash]]; - int valid_block = 0; - - if (!cpu_state.abrt) - { - page_t *page = &pages[phys_addr >> 12]; - - /*Block must match current CS, PC, code segment size, - and physical address. The physical address check will - also catch any page faults at this stage*/ - valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) && - (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); - if (!valid_block) - { - uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask) - { - /*Walk page tree to see if we find the correct block*/ - codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); - if (new_block) + if (!cpu_state.abrt) { - valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && - (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); - if (valid_block) - { - block = new_block; - codeblock_hash[hash] = get_block_nr(block); - } + trap = cpu_state.flags & T_FLAG; + opcode = fetchdat & 0xFF; + fetchdat >>= 8; + +// if (output == 3) +// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); + + cpu_state.pc++; + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); } - } - } - if (valid_block && (block->page_mask & *block->dirty_mask)) - { - codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr); - page->dirty_mask[(phys_addr >> 10) & 3] = 0; - if (block->pc == BLOCK_PC_INVALID) - valid_block = 0; - } - if (valid_block && block->page_mask2) - { - /*We don't want the second page to cause a page - fault at this stage - that would break any - code crossing a page boundary where the first - page is present but the second isn't. Instead - allow the first page to be interpreted and for - the page fault to occur when the page boundary - is actually crossed.*/ - uint32_t phys_addr_2 = get_phys_noabrt(block->pc + 0x400); - page_t *page_2 = &pages[phys_addr_2 >> 12]; - if ((block->phys_2 ^ phys_addr_2) & ~0xfff) - valid_block = 0; - else if (block->page_mask2 & *block->dirty_mask2) - { - codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2); - page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0; - if (block->pc == BLOCK_PC_INVALID) - valid_block = 0; - } - } - if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) - { - /*FPU top-of-stack does not match the value this block was compiled - with, re-compile using dynamic top-of-stack*/ - block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); - } - } + if (((cs + cpu_state.pc) >> 12) != pccache) + CPU_BLOCK_END(); - if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED)) - { - void (*code)() = (void *)&block->data[BLOCK_START]; - -// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc); - -inrecomp=1; - code(); -inrecomp=0; -// cpu_recomp_ins += block->ins; - cpu_recomp_blocks++; -/* ins += codeblock_ins[index]; - insc += codeblock_ins[index];*/ -/* pclog("Exit block now %04X:%04X\n", CS, pc);*/ - } - else if (valid_block && !cpu_state.abrt) - { - uint32_t start_pc = cpu_state.pc; - -// pclog("Hash %08x %i\n", codeblock_hash_pc[HASH(cs + pc)], codeblock_page_dirty[(cs + pc) >> 12]); - cpu_block_end = 0; - x86_was_reset = 0; - - cpu_new_blocks++; - - codegen_block_start_recompile(block); - codegen_in_recompile = 1; - -// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); - while (!cpu_block_end) - { - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; - - fetchdat = fastreadl(cs + cpu_state.pc); -// if (fetchdat == 0xffffffff) -// fatal("Dead ffffffff\n"); -// if (!fetchdat) -// fatal("Dead\n"); - if (!cpu_state.abrt) - { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; - fetchdat >>= 8; - -// if (output == 3) -// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); - - cpu_state.pc++; - - codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1); - - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - - if (x86_was_reset) - break; - } - - /*Cap source code at 4000 bytes per block; this - will prevent any block from spanning more than - 2 pages. In practice this limit will never be - hit, as host block size is only 2kB*/ - if ((cpu_state.pc - start_pc) > 1000) - CPU_BLOCK_END(); + if (cpu_state.abrt) + CPU_BLOCK_END(); + if (trap) + CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); - if (trap) - CPU_BLOCK_END(); - - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - - if (cpu_state.abrt) - { - codegen_block_remove(); - CPU_BLOCK_END(); + ins++; + insc++; } - - ins++; - insc++; - } - - if (!cpu_state.abrt && !x86_was_reset) - codegen_block_end_recompile(block); - - if (x86_was_reset) - codegen_reset(); - - codegen_in_recompile = 0; -// output &= ~2; - } - else if (!cpu_state.abrt) - { - /*Mark block but do not recompile*/ - uint32_t start_pc = cpu_state.pc; - -// pclog("Hash %08x %i\n", codeblock_hash_pc[HASH(cs + pc)], codeblock_page_dirty[(cs + pc) >> 12]); - cpu_block_end = 0; - x86_was_reset = 0; - -// cpu_new_blocks++; - - codegen_block_init(phys_addr); - -// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); - while (!cpu_block_end) - { - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; - - codegen_endpc = (cs + cpu_state.pc) + 8; - fetchdat = fastreadl(cs + cpu_state.pc); - - if (!cpu_state.abrt) - { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; - fetchdat >>= 8; - -// if (output == 3) -// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); - - cpu_state.pc++; - - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - - if (x86_was_reset) - break; - } - - /*Cap source code at 4000 bytes per block; this - will prevent any block from spanning more than - 2 pages. In practice this limit will never be - hit, as host block size is only 2kB*/ - if ((cpu_state.pc - start_pc) > 1000) - CPU_BLOCK_END(); - - if (trap) - CPU_BLOCK_END(); - - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - - if (cpu_state.abrt) - { - codegen_block_remove(); - CPU_BLOCK_END(); - } - - ins++; - insc++; - } - - if (!cpu_state.abrt && !x86_was_reset) - codegen_block_end(); - - if (x86_was_reset) - codegen_reset(); - -// output &= ~2; - } - else - cpu_state.oldpc = cpu_state.pc; - -// if (output && (SP & 1)) -// fatal("odd SP\n"); - } - - cycdiff=oldcyc-cycles; - tsc += cycdiff; - -// timer_end_period(cycles); - - if (cpu_state.abrt) - { - flags_rebuild(); - tempi = cpu_state.abrt; - cpu_state.abrt = 0; - x86_doabrt(tempi); - if (cpu_state.abrt) - { - cpu_state.abrt = 0; - cpu_state.pc = cpu_state.oldpc; - pclog("Double fault %i\n", ins); - pmodeint(8, 0); - if (cpu_state.abrt) - { - cpu_state.abrt = 0; - softresetx86(); - cpu_set_edx(); - pclog("Triple fault - reset\n"); - } - } - } - - if (trap) - { - trap = 0; - flags_rebuild(); -// oldpc=pc; - if (msw&1) - { - pmodeint(1,0); } else { - writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr = (1 << 2) + idt.base; - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); + uint32_t phys_addr = get_phys(cs+cpu_state.pc); + int hash = HASH(phys_addr); + codeblock_t *block = &codeblock[codeblock_hash[hash]]; + int valid_block = 0; + + if (!cpu_state.abrt) + { + page_t *page = &pages[phys_addr >> 12]; + + /*Block must match current CS, PC, code segment size, + and physical address. The physical address check will + also catch any page faults at this stage*/ + valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) && + (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && + ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); + if (!valid_block) + { + uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + + if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask) + { + /*Walk page tree to see if we find the correct block*/ + codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); + if (new_block) + { + valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && + (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && + ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); + if (valid_block) + { + block = new_block; + codeblock_hash[hash] = get_block_nr(block); + } + } + } + } + + if (valid_block && (block->page_mask & *block->dirty_mask)) + { + codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr); + page->dirty_mask[(phys_addr >> 10) & 3] = 0; + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + } + if (valid_block && block->page_mask2) + { + /*We don't want the second page to cause a page + fault at this stage - that would break any + code crossing a page boundary where the first + page is present but the second isn't. Instead + allow the first page to be interpreted and for + the page fault to occur when the page boundary + is actually crossed.*/ + uint32_t phys_addr_2 = get_phys_noabrt(block->pc + 0x400); + page_t *page_2 = &pages[phys_addr_2 >> 12]; + if ((block->phys_2 ^ phys_addr_2) & ~0xfff) + valid_block = 0; + else if (block->page_mask2 & *block->dirty_mask2) + { + codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2); + page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0; + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + } + } + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) + { + /*FPU top-of-stack does not match the value this block was compiled + with, re-compile using dynamic top-of-stack*/ + block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); + } + } + + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED)) + { + void (*code)() = (void *)&block->data[BLOCK_START]; + +// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc); + + inrecomp=1; + code(); + inrecomp=0; + + cpu_recomp_blocks++; + } + else if (valid_block && !cpu_state.abrt) + { + uint32_t start_pc = cpu_state.pc; + + cpu_block_end = 0; + x86_was_reset = 0; + + cpu_new_blocks++; + + codegen_block_start_recompile(block); + codegen_in_recompile = 1; + +// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); + while (!cpu_block_end) + { + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; + + fetchdat = fastreadl(cs + cpu_state.pc); + + if (!cpu_state.abrt) + { + trap = cpu_state.flags & T_FLAG; + opcode = fetchdat & 0xFF; + fetchdat >>= 8; + +// if (output == 3) +// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); + + cpu_state.pc++; + + codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1); + + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + + if (x86_was_reset) + break; + } + + /*Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB*/ + if ((cpu_state.pc - start_pc) > 1000) + CPU_BLOCK_END(); + + if (trap) + CPU_BLOCK_END(); + + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + + if (cpu_state.abrt) + { + codegen_block_remove(); + CPU_BLOCK_END(); + } + + ins++; + insc++; + } + + if (!cpu_state.abrt && !x86_was_reset) + codegen_block_end_recompile(block); + + if (x86_was_reset) + codegen_reset(); + + codegen_in_recompile = 0; + } + else if (!cpu_state.abrt) + { + /*Mark block but do not recompile*/ + uint32_t start_pc = cpu_state.pc; + + cpu_block_end = 0; + x86_was_reset = 0; + + codegen_block_init(phys_addr); + +// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); + while (!cpu_block_end) + { + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; + + codegen_endpc = (cs + cpu_state.pc) + 8; + fetchdat = fastreadl(cs + cpu_state.pc); + + if (!cpu_state.abrt) + { + trap = cpu_state.flags & T_FLAG; + opcode = fetchdat & 0xFF; + fetchdat >>= 8; + +// if (output == 3) +// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); + + cpu_state.pc++; + + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + + if (x86_was_reset) + break; + } + + /*Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB*/ + if ((cpu_state.pc - start_pc) > 1000) + CPU_BLOCK_END(); + + if (trap) + CPU_BLOCK_END(); + + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + + if (cpu_state.abrt) + { + codegen_block_remove(); + CPU_BLOCK_END(); + } + + ins++; + insc++; + } + + if (!cpu_state.abrt && !x86_was_reset) + codegen_block_end(); + + if (x86_was_reset) + codegen_reset(); + } + else + cpu_state.oldpc = cpu_state.pc; + } - } - else if (nmi && nmi_enable && nmi_mask) - { - cpu_state.oldpc = cpu_state.pc; -// pclog("NMI\n"); - x86_int(2); - nmi_enable = 0; - if (nmi_auto_clear) + + cycdiff=oldcyc-cycles; + tsc += cycdiff; + + if (cpu_state.abrt) { - nmi_auto_clear = 0; - nmi = 0; + flags_rebuild(); + tempi = cpu_state.abrt; + cpu_state.abrt = 0; + x86_doabrt(tempi); + if (cpu_state.abrt) + { + cpu_state.abrt = 0; + cpu_state.pc = cpu_state.oldpc; + pclog("Double fault %i\n", ins); + pmodeint(8, 0); + if (cpu_state.abrt) + { + cpu_state.abrt = 0; + softresetx86(); + cpu_set_edx(); + pclog("Triple fault - reset\n"); + } + } } - } - else if ((cpu_state.flags & I_FLAG) && pic_intpending) - { - temp=picinterrupt(); - if (temp!=0xFF) + + if (trap) { -// pclog("IRQ %02X %04X:%04X %04X:%04X\n", temp, SS, SP, CS, pc); - CPU_BLOCK_END(); + trap = 0; flags_rebuild(); if (msw&1) { - pmodeint(temp,0); + pmodeint(1,0); } else { @@ -913,16 +845,54 @@ inrecomp=0; writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; - addr=temp<<2; + addr = (1 << 2) + idt.base; cpu_state.flags &= ~I_FLAG; cpu_state.flags &= ~T_FLAG; - oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); } } + else if (nmi && nmi_enable && nmi_mask) + { + cpu_state.oldpc = cpu_state.pc; +// pclog("NMI\n"); + x86_int(2); + nmi_enable = 0; + if (nmi_auto_clear) + { + nmi_auto_clear = 0; + nmi = 0; + } + } + else if ((cpu_state.flags & I_FLAG) && pic_intpending) + { + temp=picinterrupt(); + if (temp!=0xFF) + { +// pclog("IRQ %02X %04X:%04X %04X:%04X\n", temp, SS, SP, CS, pc); + CPU_BLOCK_END(); + flags_rebuild(); + if (msw&1) + { + pmodeint(temp,0); + } + else + { + writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); + writememw(ss,(SP-4)&0xFFFF,CS); + writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); + SP-=6; + addr=temp<<2; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; + oxpc=cpu_state.pc; + cpu_state.pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + } + } + } } - } + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) timer_process(); cycles_main -= (cycles_start - cycles); From 9a6376dbf99eaa651d94d1650fb7756343420cfe Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 2 Feb 2019 13:46:06 +0000 Subject: [PATCH 124/181] Clear codeblock physical addresses when resetting codegen. Fixes out-of-bounds accesses to the pages[] array during reset. --- src/codegen_backend.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/codegen_backend.c b/src/codegen_backend.c index c047ba3..4874233 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -161,7 +161,11 @@ void codegen_reset() codeblock_t *block = &codeblock[c]; if (block->pc != BLOCK_PC_INVALID) + { + block->phys = 0; + block->phys_2 = 0; delete_block(block); + } } memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); From 4c523a5fe2518e86825d9805c379fb823d3e62ad Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 2 Feb 2019 19:20:42 +0000 Subject: [PATCH 125/181] Split x86 and x86-64 ops files into main/FPU/SSE files. --- src/Makefile.am | 4 +- src/codegen_backend_x86-64.c | 1 + src/codegen_backend_x86-64_ops.c | 707 +--------------------- src/codegen_backend_x86-64_ops.h | 115 ---- src/codegen_backend_x86-64_ops_helpers.h | 102 ++++ src/codegen_backend_x86-64_ops_sse.c | 614 +++++++++++++++++++ src/codegen_backend_x86-64_ops_sse.h | 114 ++++ src/codegen_backend_x86-64_uops.c | 1 + src/codegen_backend_x86.c | 1 + src/codegen_backend_x86_ops.c | 732 +---------------------- src/codegen_backend_x86_ops.h | 119 ---- src/codegen_backend_x86_ops_fpu.c | 80 +++ src/codegen_backend_x86_ops_fpu.h | 5 + src/codegen_backend_x86_ops_helpers.h | 84 +++ src/codegen_backend_x86_ops_sse.c | 588 ++++++++++++++++++ src/codegen_backend_x86_ops_sse.h | 112 ++++ src/codegen_backend_x86_uops.c | 2 + 17 files changed, 1708 insertions(+), 1673 deletions(-) create mode 100644 src/codegen_backend_x86-64_ops_helpers.h create mode 100644 src/codegen_backend_x86-64_ops_sse.c create mode 100644 src/codegen_backend_x86-64_ops_sse.h create mode 100644 src/codegen_backend_x86_ops_fpu.c create mode 100644 src/codegen_backend_x86_ops_fpu.h create mode 100644 src/codegen_backend_x86_ops_helpers.h create mode 100644 src/codegen_backend_x86_ops_sse.c create mode 100644 src/codegen_backend_x86_ops_sse.h diff --git a/src/Makefile.am b/src/Makefile.am index f098a4d..93f8f32 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,12 +72,12 @@ pcem_SOURCES += wx-sdl2-midi.c endif if CPU_I386 -pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_ops.c codegen_backend_x86_uops.c +pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_ops.c codegen_backend_x86_ops_fpu.c codegen_backend_x86_ops_sse.c codegen_backend_x86_uops.c pcem_CFLAGS += -msse2 endif if CPU_X86_64 -pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_ops.c codegen_backend_x86-64_uops.c +pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_ops.c codegen_backend_x86-64_ops_sse.c codegen_backend_x86-64_uops.c endif if CPU_ARM diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 01eec22..bfbf6a7 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -6,6 +6,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" +#include "codegen_backend_x86-64_ops_sse.h" #include "codegen_reg.h" #include "x86.h" diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 9e9928d..a4a8680 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -6,6 +6,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" +#include "codegen_backend_x86-64_ops_helpers.h" #define RM_OP_ADD 0x00 #define RM_OP_OR 0x08 @@ -18,109 +19,6 @@ #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 -#define JMP_LEN_BYTES 5 - -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) -{ - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } - block_write_data[block_pos++] = val; -} -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) -{ - if (block_pos > (BLOCK_MAX-2)) - { - fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; -} -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) -{ - if (block_pos > (BLOCK_MAX-3)) - { - fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; -} -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) -{ - if (block_pos > (BLOCK_MAX-4)) - { - fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; - block_write_data[block_pos++] = vald; -} - -static inline void codegen_addword(codeblock_t *block, uint16_t val) -{ - if (block_pos > (BLOCK_MAX-2)) - { - fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint16_t *)&block_write_data[block_pos] = val; - block_pos += 2; -} - -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - if (block_pos > (BLOCK_MAX-4)) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; -} - -static inline void codegen_addquad(codeblock_t *block, uint64_t val) -{ - if (block_pos > (BLOCK_MAX-8)) - { - fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint64_t *)&block_write_data[block_pos] = val; - block_pos += 8; -} - -static inline void codegen_alloc_bytes(codeblock_t *block, int size) -{ - if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) - { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - - /*Add a jump instruction to the new block*/ - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); - - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; - } -} - -static int is_imm8(uint32_t imm_data) -{ - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; -} - static inline void call(codeblock_t *block, uintptr_t func) { uintptr_t diff; @@ -263,17 +161,6 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ -} -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { if (dst_reg & 8) @@ -433,86 +320,6 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ -} - -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); -} - -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ -} -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ -} - -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ -} -void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ -} - void host_x86_JMP(codeblock_t *block, void *p) { jmp(block, (uintptr_t)p); @@ -655,27 +462,6 @@ void host_x86_LAHF(codeblock_t *block) codegen_addbyte(block, 0x9f); /*LAHF*/ } -void host_x86_LDMXCSR(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ - codegen_addlong(block, offset); - } - else - { - fatal("host_x86_LDMXCSR - out of range %p\n", p); - } -} - void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) { if (offset) @@ -709,12 +495,6 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ -} - void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -1220,187 +1000,6 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addbyte(block, 0x25); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) -{ - if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); - - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} - -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); -} - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (dst_reg & 8) - fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addbyte(block, 0x25); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); - - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ -} - -void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { codegen_alloc_bytes(block, 4); @@ -1484,28 +1083,6 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); } -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ -} -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ -} - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ -} -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_NOP(codeblock_t *block) { codegen_alloc_bytes(block, 1); @@ -1599,260 +1176,6 @@ void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ } -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); -} -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); -} -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); -} - -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ -} -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ -} -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ -} -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ -} - -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ -} -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ -} -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ -} -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ -} -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ -} -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ -} -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ -} -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ -} -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ -} - -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} - -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} - -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ -} -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ -} -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ -} -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ -} - -void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ -} -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ -} -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ -} - void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) @@ -2035,17 +1358,6 @@ void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ -} -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ -} - void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { if (dst_reg & 8) @@ -2146,17 +1458,6 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ -} -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); -} - #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) @@ -2195,12 +1496,6 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { if (dst_reg & 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index aa7e0c7..eaee044 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -7,9 +7,6 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); @@ -28,28 +25,6 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); -#define CMPPS_EQ 0 -#define CMPPS_NLT 5 -#define CMPPS_NLE 6 -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type); - -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); - -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_JMP(codeblock_t *block, void *p); void host_x86_JNZ(codeblock_t *block, void *p); @@ -76,14 +51,10 @@ uint32_t *host_x86_JZ_long(codeblock_t *block); void host_x86_LAHF(codeblock_t *block); -void host_x86_LDMXCSR(codeblock_t *block, void *p); - void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset); void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); @@ -128,24 +99,6 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg); -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); - -void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); @@ -159,13 +112,6 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_NOP(codeblock_t *block); void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); @@ -176,59 +122,6 @@ void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); - -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); @@ -259,9 +152,6 @@ void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); @@ -271,16 +161,11 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg); void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); diff --git a/src/codegen_backend_x86-64_ops_helpers.h b/src/codegen_backend_x86-64_ops_helpers.h new file mode 100644 index 0000000..4e63bbd --- /dev/null +++ b/src/codegen_backend_x86-64_ops_helpers.h @@ -0,0 +1,102 @@ +#define JMP_LEN_BYTES 5 + +static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +{ + if (block_pos >= BLOCK_MAX) + { + fatal("codegen_addbyte over! %i\n", block_pos); +// CPU_BLOCK_END(); + } + block_write_data[block_pos++] = val; +} +static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +{ + if (block_pos > (BLOCK_MAX-2)) + { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; +} +static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +{ + if (block_pos > (BLOCK_MAX-3)) + { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; +} +static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +{ + if (block_pos > (BLOCK_MAX-4)) + { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; +} + +static inline void codegen_addword(codeblock_t *block, uint16_t val) +{ + if (block_pos > (BLOCK_MAX-2)) + { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint16_t *)&block_write_data[block_pos] = val; + block_pos += 2; +} + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + if (block_pos > (BLOCK_MAX-4)) + { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; +} + +static inline void codegen_addquad(codeblock_t *block, uint64_t val) +{ + if (block_pos > (BLOCK_MAX-8)) + { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint64_t *)&block_write_data[block_pos] = val; + block_pos += 8; +} + +static inline void codegen_alloc_bytes(codeblock_t *block, int size) +{ + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + { + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; + } +} + +static inline int is_imm8(uint32_t imm_data) +{ + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; +} diff --git a/src/codegen_backend_x86-64_ops_sse.c b/src/codegen_backend_x86-64_ops_sse.c new file mode 100644 index 0000000..cdff2c6 --- /dev/null +++ b/src/codegen_backend_x86-64_ops_sse.c @@ -0,0 +1,614 @@ +#ifdef __amd64__ + +#include "ibm.h" +#include "codegen.h" +#include "codegen_allocator.h" +#include "codegen_backend.h" +#include "codegen_backend_x86-64_defs.h" +#include "codegen_backend_x86-64_ops_sse.h" +#include "codegen_backend_x86-64_ops_helpers.h" + +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ +} +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ +} + +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); +} + +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ +} +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ +} + +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ +} +void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); +} +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} + +void host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } + else if (offset < (1ull << 32)) + { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ + codegen_addlong(block, offset); + } + else + { + fatal("host_x86_LDMXCSR - out of range %p\n", p); + } +} + +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ +} + +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) +{ + if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); + + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} + +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_RSP) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} + +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + if ((uintptr_t)p >> 32) + fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t)(uintptr_t)p); + } +} +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); + + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); +} + +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ +} + +void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ +} +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ +} + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ +} +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} + +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ +} + +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} + +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ +} + +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} + +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); +} + +#endif diff --git a/src/codegen_backend_x86-64_ops_sse.h b/src/codegen_backend_x86-64_ops_sse.h new file mode 100644 index 0000000..39e39f4 --- /dev/null +++ b/src/codegen_backend_x86-64_ops_sse.h @@ -0,0 +1,114 @@ +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +#define CMPPS_EQ 0 +#define CMPPS_NLT 5 +#define CMPPS_NLE 6 +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type); + +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); + +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_LDMXCSR(codeblock_t *block, void *p); + +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg); +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); + +void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index e17ad0e..aaabbbc 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -8,6 +8,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86-64_defs.h" #include "codegen_backend_x86-64_ops.h" +#include "codegen_backend_x86-64_ops_sse.h" #include "codegen_ir_defs.h" #define STACK_ARG0 (0) diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 7beffc5..7aef0e3 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -7,6 +7,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" +#include "codegen_backend_x86_ops_sse.h" #include "codegen_reg.h" #include "x86.h" diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 47f7493..ce64b33 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -6,6 +6,7 @@ #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" +#include "codegen_backend_x86_ops_helpers.h" #define RM_OP_ADD 0x00 #define RM_OP_OR 0x08 @@ -18,91 +19,6 @@ #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 -#define JMP_LEN_BYTES 5 - -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) -{ - if (block_pos >= BLOCK_MAX) - fatal("codegen_addbyte over! %i\n", block_pos); - block_write_data[block_pos++] = val; -} -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) -{ - if (block_pos > (BLOCK_MAX-2)) - fatal("codegen_addbyte2 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; -} -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) -{ - if (block_pos > (BLOCK_MAX-3)) - fatal("codegen_addbyte3 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; -} -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) -{ - if (block_pos > (BLOCK_MAX-4)) - fatal("codegen_addbyte4 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; - block_write_data[block_pos++] = vald; -} - -static inline void codegen_addword(codeblock_t *block, uint16_t val) -{ - if (block_pos > (BLOCK_MAX-2)) - fatal("codegen_addword over! %i\n", block_pos); - *(uint16_t *)&block_write_data[block_pos] = val; - block_pos += 2; -} - -static inline void codegen_addlong(codeblock_t *block, uint32_t val) -{ - if (block_pos > (BLOCK_MAX-4)) - fatal("codegen_addlong over! %i\n", block_pos); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; -} - -static inline void codegen_addquad(codeblock_t *block, uint64_t val) -{ - if (block_pos > (BLOCK_MAX-8)) - fatal("codegen_addquad over! %i\n", block_pos); - *(uint64_t *)&block_write_data[block_pos] = val; - block_pos += 8; -} - -static void codegen_allocate_new_block(codeblock_t *block) -{ - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - - /*Add a jump instruction to the new block*/ - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); - - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; -} - -static inline void codegen_alloc_bytes(codeblock_t *block, int size) -{ - if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) - codegen_allocate_new_block(block); -} - -static int is_imm8(uint32_t imm_data) -{ - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; -} - void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -191,17 +107,6 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ -} -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { if (dst_reg == REG_EAX) @@ -336,74 +241,6 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ } -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ -} - -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); -} - -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ -} -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ -} - -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ -} -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ -} - -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} - -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ -} -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ -} - void host_x86_INC32_ABS(codeblock_t *block, void *p) { codegen_alloc_bytes(block, 6); @@ -562,23 +399,6 @@ void host_x86_LAHF(codeblock_t *block) codegen_addbyte(block, 0x9f); /*LAHF*/ } -void host_x86_LDMXCSR(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} - void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) { if (offset) @@ -605,12 +425,6 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ } -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ -} - void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -958,177 +772,6 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d } } -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); -} -void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) -{ - if (!offset) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ - codegen_addbyte(block, 0x24); - } - else if (offset >= -80 || offset < 0x80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ - codegen_addbyte2(block, 0x24, offset & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ - codegen_addbyte(block, 0x24); - codegen_addlong(block, offset); - } - -} - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ -} - void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { codegen_alloc_bytes(block, 4); @@ -1205,28 +848,6 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ } -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ -} -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ -} - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ -} -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_alloc_bytes(block, 2); @@ -1297,260 +918,6 @@ void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); -} -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); -} -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); -} - -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ -} -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ -} -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ -} -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ -} - -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ -} -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ -} -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ -} -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ -} -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ -} -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ -} -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ -} -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ -} -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ -} - -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} - -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} - -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ -} -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ -} -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ -} -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ -} - -void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ -} -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ -} -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ -} - void host_x86_POP(codeblock_t *block, int src_reg) { codegen_alloc_bytes(block, 1); @@ -1667,17 +1034,6 @@ void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ -} -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ -} - void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { if (dst_reg == REG_EAX) @@ -1748,17 +1104,6 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ -} -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { codegen_alloc_bytes(block, 2); @@ -1790,12 +1135,6 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); -} - void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { codegen_alloc_bytes(block, 2); @@ -1866,73 +1205,4 @@ void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) } } -void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) -{ - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ - } -} -void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) -{ - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ - } -} -void host_x87_FLDCW(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) -{ - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ - } -} -void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) -{ - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ - } -} - #endif diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index db7b37c..08b7e9f 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -8,9 +8,6 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); @@ -28,28 +25,6 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); -#define CMPPS_EQ 0 -#define CMPPS_NLT 5 -#define CMPPS_NLE 6 -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type); - -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); - -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg); -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg); -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_INC32_ABS(codeblock_t *block, void *p); void host_x86_JMP(codeblock_t *block, void *p); @@ -80,14 +55,10 @@ uint32_t *host_x86_JZ_long(codeblock_t *block); void host_x86_LAHF(codeblock_t *block); -void host_x86_LDMXCSR(codeblock_t *block, void *p); - void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset); void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b); void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift); -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data); @@ -129,23 +100,6 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data); -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg); -void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg); - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); @@ -159,12 +113,6 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); @@ -173,59 +121,6 @@ void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); - -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - -void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); @@ -256,9 +151,6 @@ void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift); -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); @@ -267,17 +159,12 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg); void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data); -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); @@ -285,9 +172,3 @@ void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data); void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data); void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data); - -void host_x87_FILDq_BASE(codeblock_t *block, int base_reg); -void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg); -void host_x87_FLDCW(codeblock_t *block, void *p); -void host_x87_FLDd_BASE(codeblock_t *block, int base_reg); -void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg); diff --git a/src/codegen_backend_x86_ops_fpu.c b/src/codegen_backend_x86_ops_fpu.c new file mode 100644 index 0000000..1c3f990 --- /dev/null +++ b/src/codegen_backend_x86_ops_fpu.c @@ -0,0 +1,80 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#include "ibm.h" +#include "codegen.h" +#include "codegen_allocator.h" +#include "codegen_backend.h" +#include "codegen_backend_x86_defs.h" +#include "codegen_backend_x86_ops_fpu.h" +#include "codegen_backend_x86_ops_helpers.h" + +void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + } + else + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ + } +} +void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ + } + else + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ + } +} +void host_x87_FLDCW(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ + } + else + { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ + } + else + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ + } +} +void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) +{ + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + } + else + { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ + } +} + +#endif diff --git a/src/codegen_backend_x86_ops_fpu.h b/src/codegen_backend_x86_ops_fpu.h new file mode 100644 index 0000000..3692715 --- /dev/null +++ b/src/codegen_backend_x86_ops_fpu.h @@ -0,0 +1,5 @@ +void host_x87_FILDq_BASE(codeblock_t *block, int base_reg); +void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg); +void host_x87_FLDCW(codeblock_t *block, void *p); +void host_x87_FLDd_BASE(codeblock_t *block, int base_reg); +void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg); diff --git a/src/codegen_backend_x86_ops_helpers.h b/src/codegen_backend_x86_ops_helpers.h new file mode 100644 index 0000000..9c100ec --- /dev/null +++ b/src/codegen_backend_x86_ops_helpers.h @@ -0,0 +1,84 @@ +#define JMP_LEN_BYTES 5 + +static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +{ + if (block_pos >= BLOCK_MAX) + fatal("codegen_addbyte over! %i\n", block_pos); + block_write_data[block_pos++] = val; +} +static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +{ + if (block_pos > (BLOCK_MAX-2)) + fatal("codegen_addbyte2 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; +} +static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +{ + if (block_pos > (BLOCK_MAX-3)) + fatal("codegen_addbyte3 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; +} +static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +{ + if (block_pos > (BLOCK_MAX-4)) + fatal("codegen_addbyte4 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; +} + +static inline void codegen_addword(codeblock_t *block, uint16_t val) +{ + if (block_pos > (BLOCK_MAX-2)) + fatal("codegen_addword over! %i\n", block_pos); + *(uint16_t *)&block_write_data[block_pos] = val; + block_pos += 2; +} + +static inline void codegen_addlong(codeblock_t *block, uint32_t val) +{ + if (block_pos > (BLOCK_MAX-4)) + fatal("codegen_addlong over! %i\n", block_pos); + *(uint32_t *)&block_write_data[block_pos] = val; + block_pos += 4; +} + +static inline void codegen_addquad(codeblock_t *block, uint64_t val) +{ + if (block_pos > (BLOCK_MAX-8)) + fatal("codegen_addquad over! %i\n", block_pos); + *(uint64_t *)&block_write_data[block_pos] = val; + block_pos += 8; +} + +static void codegen_allocate_new_block(codeblock_t *block) +{ + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; +} + +static inline void codegen_alloc_bytes(codeblock_t *block, int size) +{ + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + codegen_allocate_new_block(block); +} + +static inline int is_imm8(uint32_t imm_data) +{ + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; +} diff --git a/src/codegen_backend_x86_ops_sse.c b/src/codegen_backend_x86_ops_sse.c new file mode 100644 index 0000000..dc20d34 --- /dev/null +++ b/src/codegen_backend_x86_ops_sse.c @@ -0,0 +1,588 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#include "ibm.h" +#include "codegen.h" +#include "codegen_allocator.h" +#include "codegen_backend.h" +#include "codegen_backend_x86_defs.h" +#include "codegen_backend_x86_ops_sse.h" +#include "codegen_backend_x86_ops_helpers.h" + +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ +} +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ +} + +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); +} + +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ +} +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ +} + +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ +} +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ +} + +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} + +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ +} +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} + +void host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } + else + { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} + +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ +} + +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) +{ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} +void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) +{ + if (!offset) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ + codegen_addbyte(block, 0x24); + } + else if (offset >= -80 || offset < 0x80) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte2(block, 0x24, offset & 0xff); + } + else + { + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte(block, 0x24); + codegen_addlong(block, offset); + } + +} + +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } + else + { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t)p); + } +} +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if (addr < 0x80 || addr >= 0xffffff80) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } + else + { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) + { + if (base_reg == REG_ESP) + { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } + else + { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } + else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); +} +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ +} + +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ +} +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ +} + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ +} +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} + +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ +} + +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} + +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ +} + +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} + +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); +} + +#endif diff --git a/src/codegen_backend_x86_ops_sse.h b/src/codegen_backend_x86_ops_sse.h new file mode 100644 index 0000000..596f361 --- /dev/null +++ b/src/codegen_backend_x86_ops_sse.h @@ -0,0 +1,112 @@ +void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +#define CMPPS_EQ 0 +#define CMPPS_NLT 5 +#define CMPPS_NLE 6 +void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type); + +void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b); + +void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg); +void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg); +void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); + +void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_LDMXCSR(codeblock_t *block, void *p); + +void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg); +void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg); +void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg); +void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg); +void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg); + +void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift); +void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); +void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset); +void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 55bcc13..b05d4c1 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -9,6 +9,8 @@ #include "codegen_backend.h" #include "codegen_backend_x86_defs.h" #include "codegen_backend_x86_ops.h" +#include "codegen_backend_x86_ops_fpu.h" +#include "codegen_backend_x86_ops_sse.h" #include "codegen_ir_defs.h" /*void codegen_debug() From 095cf53265a83f8a84967527d5177978c6d4ae88 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 3 Feb 2019 17:48:11 +0000 Subject: [PATCH 126/181] Added segment limit checking to some instructions. --- src/codegen_backend_arm64_uops.c | 40 ++++++++++++++++++++++++ src/codegen_backend_arm_uops.c | 40 ++++++++++++++++++++++++ src/codegen_backend_x86-64_uops.c | 42 +++++++++++++++++++++++++ src/codegen_backend_x86_uops.c | 42 +++++++++++++++++++++++++ src/codegen_ir_defs.h | 17 +++++++++++ src/codegen_ops_fpu_loadstore.c | 2 ++ src/codegen_ops_helpers.h | 18 +++++++++++ src/codegen_ops_mmx_loadstore.c | 2 ++ src/codegen_ops_mov.c | 5 +++ src/codegen_reg.c | 14 +++++++++ src/codegen_reg.h | 51 ++++++++++++++++++++++++++++++- 11 files changed, 272 insertions(+), 1 deletion(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 48f748b..47a6b3a 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -306,6 +306,43 @@ static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); + + jump_p = host_arm64_BCC_(block); + host_arm64_branch_set_offset(jump_p, uop->p); + + return 0; +} +static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + + jump_p = host_arm64_BHI_(block); + host_arm64_branch_set_offset(jump_p, uop->p); + + return 0; +} + static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2751,6 +2788,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, + [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 5160511..a47488d 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -381,6 +381,43 @@ static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); + + jump_p = host_arm_BCC_(block); + *jump_p |= ((((uintptr_t)uop->p - (uintptr_t)jump_p) - 8) & 0x3fffffc) >> 2; + + return 0; +} +static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + + jump_p = host_arm_BHI_(block); + *jump_p |= ((((uintptr_t)uop->p - (uintptr_t)jump_p) - 8) & 0x3fffffc) >> 2; + + return 0; +} + static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2900,6 +2937,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, + [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index aaabbbc..da8e8e4 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -277,6 +277,45 @@ static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +#ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); +#endif + jump_p = host_x86_JB_long(block); + *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + + return 0; +} +static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +#ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); +#endif + jump_p = host_x86_JNBE_long(block); + *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + + return 0; +} + static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2665,6 +2704,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, + [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index b05d4c1..f3ace1e 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -285,6 +285,45 @@ static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +#ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); +#endif + jump_p = host_x86_JB_long(block); + *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + + return 0; +} +static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) + { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +#ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); +#endif + jump_p = host_x86_JNBE_long(block); + *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + + return 0; +} + static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2664,6 +2703,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, + [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index aa95c06..a69f346 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -125,6 +125,10 @@ #define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/ #define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER) +/*UOP_CMP_JB - if (src_reg_a < src_reg_b) then jump to ptr*/ +#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER) +/*UOP_CMP_JNBE - if (src_reg_a > src_reg_b) then jump to ptr*/ +#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER) /*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/ #define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) @@ -563,6 +567,16 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, uop->imm_data = imm; } +static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p) +{ + uop_t *uop = uop_alloc(ir); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->p = p; +} + #define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) #define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) @@ -596,6 +610,9 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm) #define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm) +#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p) +#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p) + #define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b) #define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b) #define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b) diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c index f5e42f3..e61e5cb 100644 --- a/src/codegen_ops_fpu_loadstore.c +++ b/src/codegen_ops_fpu_loadstore.c @@ -79,6 +79,7 @@ uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet op_pc--; target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); return op_pc+1; @@ -92,6 +93,7 @@ uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe op_pc--; target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); fpu_POP(block, ir); diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index 9bde28f..0da73b6 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -1,3 +1,5 @@ +#include "codegen_backend.h" + static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) { if (stack32) @@ -67,3 +69,19 @@ static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir) else uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } + +static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || + (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + return; + + uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout); + if (end_offset) + { + uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset); + uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout); + } + else + uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout); +} diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c index e0ea5f7..e3c33e0 100644 --- a/src/codegen_ops_mmx_loadstore.c +++ b/src/codegen_ops_mmx_loadstore.c @@ -51,6 +51,7 @@ uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); } @@ -99,6 +100,7 @@ uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); } diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index c33271f..669523d 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -5,6 +5,7 @@ #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" +#include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -50,6 +51,7 @@ uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); } @@ -71,6 +73,7 @@ uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); } @@ -92,6 +95,7 @@ uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); } @@ -363,6 +367,7 @@ uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); } diff --git a/src/codegen_reg.c b/src/codegen_reg.c index 7c74153..f352d0a 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -149,6 +149,20 @@ struct [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT}, [IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT}, + [IREG_CS_limit_low] = {REG_DWORD, &cpu_state.seg_cs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_limit_low] = {REG_DWORD, &cpu_state.seg_ds.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_limit_low] = {REG_DWORD, &cpu_state.seg_es.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_limit_low] = {REG_DWORD, &cpu_state.seg_fs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_limit_low] = {REG_DWORD, &cpu_state.seg_gs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_limit_low] = {REG_DWORD, &cpu_state.seg_ss.limit_low, REG_INTEGER, REG_PERMANENT}, + + [IREG_CS_limit_high] = {REG_DWORD, &cpu_state.seg_cs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_limit_high] = {REG_DWORD, &cpu_state.seg_ds.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_limit_high] = {REG_DWORD, &cpu_state.seg_es.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_limit_high] = {REG_DWORD, &cpu_state.seg_fs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_limit_high] = {REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_limit_high] = {REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, + /*Temporary registers are stored on the stack, and are not guaranteed to be preserved across uOPs. They will not be written back if they will not be read again.*/ diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 2e76936..b498ac4 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -119,7 +119,21 @@ enum IREG_flagsx = 74, IREG_eflagsx = 75, - IREG_COUNT = 76, + IREG_CS_limit_low = 76, + IREG_DS_limit_low = 77, + IREG_ES_limit_low = 78, + IREG_FS_limit_low = 79, + IREG_GS_limit_low = 80, + IREG_SS_limit_low = 81, + + IREG_CS_limit_high = 82, + IREG_DS_limit_high = 83, + IREG_ES_limit_high = 84, + IREG_FS_limit_high = 85, + IREG_GS_limit_high = 86, + IREG_SS_limit_high = 87, + + IREG_COUNT = 88, IREG_INVALID = 255, @@ -221,6 +235,41 @@ static inline int ireg_seg_base(x86seg *seg) return 0; } +static inline int ireg_seg_limit_low(x86seg *seg) +{ + if (seg == &cpu_state.seg_cs) + return IREG_CS_limit_low; + if (seg == &cpu_state.seg_ds) + return IREG_DS_limit_low; + if (seg == &cpu_state.seg_es) + return IREG_ES_limit_low; + if (seg == &cpu_state.seg_fs) + return IREG_FS_limit_low; + if (seg == &cpu_state.seg_gs) + return IREG_GS_limit_low; + if (seg == &cpu_state.seg_ss) + return IREG_SS_limit_low; + fatal("ireg_seg_limit_low : unknown segment\n"); + return 0; +} +static inline int ireg_seg_limit_high(x86seg *seg) +{ + if (seg == &cpu_state.seg_cs) + return IREG_CS_limit_high; + if (seg == &cpu_state.seg_ds) + return IREG_DS_limit_high; + if (seg == &cpu_state.seg_es) + return IREG_ES_limit_high; + if (seg == &cpu_state.seg_fs) + return IREG_FS_limit_high; + if (seg == &cpu_state.seg_gs) + return IREG_GS_limit_high; + if (seg == &cpu_state.seg_ss) + return IREG_SS_limit_high; + fatal("ireg_seg_limit_high : unknown segment\n"); + return 0; +} + extern uint8_t reg_last_version[IREG_COUNT]; extern uint8_t reg_version_refcount[IREG_COUNT][256]; From d66731f85ad8256108f96a61f4c5418e367f7875 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 3 Feb 2019 21:35:24 +0000 Subject: [PATCH 127/181] In codegen_ir_compile(), rearrange order of register lookups and order barrier flushing to reduce pointless writes of temporary registers. --- src/codegen_ir.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 97a2dc1..556cb8c 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -33,8 +33,6 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) if (uop->type & UOP_TYPE_BARRIER) codegen_reg_flush_invalidate(ir, block); - else if (uop->type & UOP_TYPE_ORDER_BARRIER) - codegen_reg_flush(ir, block); if (uop->type & UOP_TYPE_JUMP_DEST) { @@ -62,6 +60,13 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) { uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL); } + } + + if (uop->type & UOP_TYPE_ORDER_BARRIER) + codegen_reg_flush(ir, block); + + if (uop->type & UOP_TYPE_PARAMS_REGS) + { if (uop->dest_reg_a.reg != IREG_INVALID) { uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); From b105445a522016069616e73b3013706414549dad Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 4 Feb 2019 21:32:25 +0000 Subject: [PATCH 128/181] Correct Voodoo hvRetrace register. Fixes intermittent hangs on Voodoo mode setting. --- src/vid_voodoo.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index 8a1d76c..a5d03e7 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -6127,8 +6127,19 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) temp = voodoo->line & 0x1fff; break; case SST_hvRetrace: - temp = voodoo->line & 0x1fff; - temp |= ((((tsc - timer_get_ts_int(&voodoo->timer)) * voodoo->h_total) / (voodoo->line_time >> 32)) << 16) & 0x7ff0000; + { + uint32_t line_time = (uint32_t)(voodoo->line_time >> 32); + uint32_t diff = (timer_get_ts_int(&voodoo->timer) > (tsc & 0xffffffff)) ? (timer_get_ts_int(&voodoo->timer) - (tsc & 0xffffffff)) : 0; + uint32_t pre_div = diff * voodoo->h_total; + uint32_t post_div = pre_div / line_time; + uint32_t h_pos = (voodoo->h_total - 1) - post_div; + + if (h_pos >= voodoo->h_total) + h_pos = 0; + + temp = voodoo->line & 0x1fff; + temp |= (h_pos << 16); + } break; case SST_fbiInit5: From 222071b742afabf7538628507ff7ae30131f4aff Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 5 Feb 2019 21:54:38 +0000 Subject: [PATCH 129/181] ADC and SBC now use lazy flags. --- src/x86_flags.h | 160 ++++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 68 deletions(-) diff --git a/src/x86_flags.h b/src/x86_flags.h index e7c2cc2..8d50dba 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -33,6 +33,14 @@ enum FLAGS_DEC8, FLAGS_DEC16, FLAGS_DEC32, + + FLAGS_ADC8, + FLAGS_ADC16, + FLAGS_ADC32, + + FLAGS_SBC8, + FLAGS_SBC16, + FLAGS_SBC32 }; static inline int ZF_SET() @@ -63,6 +71,12 @@ static inline int ZF_SET() case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: + case FLAGS_ADC8: + case FLAGS_ADC16: + case FLAGS_ADC32: + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: return !cpu_state.flags_res; case FLAGS_UNKNOWN: @@ -83,6 +97,8 @@ static inline int NF_SET() case FLAGS_SAR8: case FLAGS_INC8: case FLAGS_DEC8: + case FLAGS_ADC8: + case FLAGS_SBC8: return cpu_state.flags_res & 0x80; case FLAGS_ZN16: @@ -93,6 +109,8 @@ static inline int NF_SET() case FLAGS_SAR16: case FLAGS_INC16: case FLAGS_DEC16: + case FLAGS_ADC16: + case FLAGS_SBC16: return cpu_state.flags_res & 0x8000; case FLAGS_ZN32: @@ -103,6 +121,8 @@ static inline int NF_SET() case FLAGS_SAR32: case FLAGS_INC32: case FLAGS_DEC32: + case FLAGS_ADC32: + case FLAGS_SBC32: return cpu_state.flags_res & 0x80000000; case FLAGS_UNKNOWN: @@ -139,6 +159,12 @@ static inline int PF_SET() case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: + case FLAGS_ADC8: + case FLAGS_ADC16: + case FLAGS_ADC32: + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; case FLAGS_UNKNOWN: @@ -159,22 +185,28 @@ static inline int VF_SET() case FLAGS_SAR32: return 0; + case FLAGS_ADC8: case FLAGS_ADD8: case FLAGS_INC8: return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); + case FLAGS_ADC16: case FLAGS_ADD16: case FLAGS_INC16: return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); + case FLAGS_ADC32: case FLAGS_ADD32: case FLAGS_INC32: return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); + case FLAGS_SBC8: case FLAGS_SUB8: case FLAGS_DEC8: return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); + case FLAGS_SBC16: case FLAGS_SUB16: case FLAGS_DEC16: return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); + case FLAGS_SBC32: case FLAGS_SUB32: case FLAGS_DEC32: return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); @@ -225,6 +257,16 @@ static inline int AF_SET() case FLAGS_INC32: return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10; + case FLAGS_ADC8: + return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || + ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xff); + case FLAGS_ADC16: + return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || + ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffff); + case FLAGS_ADC32: + return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || + ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffffffff); + case FLAGS_SUB8: case FLAGS_SUB16: case FLAGS_SUB32: @@ -232,6 +274,12 @@ static inline int AF_SET() case FLAGS_DEC16: case FLAGS_DEC32: return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10; + + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: + return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) || + ((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0); case FLAGS_UNKNOWN: return cpu_state.flags & A_FLAG; @@ -250,11 +298,27 @@ static inline int CF_SET() case FLAGS_ADD32: return (cpu_state.flags_res < cpu_state.flags_op1); + case FLAGS_ADC8: + return (cpu_state.flags_res < cpu_state.flags_op1) || + (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xff); + case FLAGS_ADC16: + return (cpu_state.flags_res < cpu_state.flags_op1) || + (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffff); + case FLAGS_ADC32: + return (cpu_state.flags_res < cpu_state.flags_op1) || + (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffffffff); + case FLAGS_SUB8: case FLAGS_SUB16: case FLAGS_SUB32: return (cpu_state.flags_op1 < cpu_state.flags_op2); - + + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: + return (cpu_state.flags_op1 < cpu_state.flags_op2) || + (cpu_state.flags_op1 == cpu_state.flags_op2 && cpu_state.flags_res != 0); + case FLAGS_SHL8: return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80; case FLAGS_SHL16: @@ -447,85 +511,45 @@ static inline void setsub32nc(uint32_t a, uint32_t b) static inline void setadc8(uint8_t a, uint8_t b) { - uint16_t c = (uint16_t)a + (uint16_t)b + tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags &= ~0x8D5; - cpu_state.flags |= znptable8[c&0xFF]; - if (c & 0x100) - cpu_state.flags |= C_FLAG; - if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) - cpu_state.flags |= V_FLAG; - if (((a & 0xF) + (b & 0xF)) & 0x10) - cpu_state.flags |= A_FLAG; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b + tempc) & 0xff; + cpu_state.flags_op = FLAGS_ADC8; } static inline void setadc16(uint16_t a, uint16_t b) { - uint32_t c = (uint32_t)a + (uint32_t)b + tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags &= ~0x8D5; - cpu_state.flags |= znptable16[c&0xFFFF]; - if (c & 0x10000) - cpu_state.flags |= C_FLAG; - if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) - cpu_state.flags |= V_FLAG; - if (((a & 0xF) + (b & 0xF)) & 0x10) - cpu_state.flags |= A_FLAG; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b + tempc) & 0xffff; + cpu_state.flags_op = FLAGS_ADC16; +} +static inline void setadc32(uint32_t a, uint32_t b) +{ + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a + b + tempc; + cpu_state.flags_op = FLAGS_ADC32; } static inline void setsbc8(uint8_t a, uint8_t b) { - uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc); - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags &= ~0x8D5; - cpu_state.flags |= znptable8[c&0xFF]; - if (c & 0x100) - cpu_state.flags |= C_FLAG; - if ((a ^ b) & (a ^ c) & 0x80) - cpu_state.flags |= V_FLAG; - if (((a & 0xF) - (b & 0xF)) & 0x10) - cpu_state.flags |= A_FLAG; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - (b + tempc)) & 0xff; + cpu_state.flags_op = FLAGS_SBC8; } static inline void setsbc16(uint16_t a, uint16_t b) { - uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc); - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags &= ~0x8D5; - cpu_state.flags |= (znptable16[c&0xFFFF] & ~4); - cpu_state.flags |= (znptable8[c&0xFF] & 4); - if (c & 0x10000) - cpu_state.flags |= C_FLAG; - if ((a ^ b) & (a ^ c) & 0x8000) - cpu_state.flags |= V_FLAG; - if (((a & 0xF) - (b & 0xF)) & 0x10) - cpu_state.flags |= A_FLAG; -} - -static inline void setadc32(uint32_t a, uint32_t b) -{ - uint32_t c = (uint32_t)a + (uint32_t)b + tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags &= ~0x8D5; - cpu_state.flags |= ((c & 0x80000000) ? N_FLAG : ((!c) ? Z_FLAG : 0)); - cpu_state.flags |= (znptable8[c&0xFF] & P_FLAG); - if ((c < a) || (c == a && tempc)) - cpu_state.flags |= C_FLAG; - if (!((a ^ b) & 0x80000000) && ((a ^ c) & 0x80000000)) - cpu_state.flags |= V_FLAG; - if (((a & 0xF) + (b & 0xF) + tempc) & 0x10) - cpu_state.flags |= A_FLAG; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - (b + tempc)) & 0xffff; + cpu_state.flags_op = FLAGS_SBC16; } static inline void setsbc32(uint32_t a, uint32_t b) { - uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc); - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags &= ~0x8D5; - cpu_state.flags |= ((c & 0x80000000) ? N_FLAG : ((!c) ? Z_FLAG : 0)); - cpu_state.flags |= (znptable8[c&0xFF] & P_FLAG); - if ((c > a) || (c == a && tempc)) - cpu_state.flags |= C_FLAG; - if ((a ^ b) & (a ^ c) & 0x80000000) - cpu_state.flags |= V_FLAG; - if (((a & 0xF) - ((b & 0xF) + tempc)) & 0x10) - cpu_state.flags |= A_FLAG; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a - (b + tempc); + cpu_state.flags_op = FLAGS_SBC32; } From d4d6a26283d4f92f8bf57c456101a0ad4f8b0d2a Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 6 Feb 2019 21:07:45 +0000 Subject: [PATCH 130/181] Added recompiled versions of ADC and SBC. --- src/codegen_ops.c | 4 +- src/codegen_ops_arith.c | 739 +++++++++++++++++++++++++++++++++++++++- src/codegen_ops_arith.h | 20 ++ src/codegen_reg.h | 1 + src/x86_flags.h | 10 +- 5 files changed, 750 insertions(+), 24 deletions(-) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index a339224..5c63795 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -27,7 +27,7 @@ RecompOpFn recomp_opcodes[512] = /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16, +/*10*/ ropADC_b_rmw, ropADC_w_rmw, ropADC_b_rm, ropADC_w_rm, ropADC_AL_imm, ropADC_AX_imm, ropPUSH_SS_16, NULL, ropSBB_b_rmw, ropSBB_w_rmw, ropSBB_b_rm, ropSBB_w_rm, ropSBB_AL_imm, ropSBB_AX_imm, ropPUSH_DS_16, ropPOP_DS_16, /*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, @@ -49,7 +49,7 @@ RecompOpFn recomp_opcodes[512] = /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32, +/*10*/ ropADC_b_rmw, ropADC_l_rmw, ropADC_b_rm, ropADC_l_rm, ropADC_AL_imm, ropADC_EAX_imm, ropPUSH_SS_32, NULL, ropSBB_b_rmw, ropSBB_l_rmw, ropSBB_b_rm, ropSBB_l_rm, ropSBB_AL_imm, ropSBB_EAX_imm, ropPUSH_DS_32, ropPOP_DS_32, /*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index 4c7c43d..ca0b980 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -8,6 +8,263 @@ #include "codegen_ops.h" #include "codegen_ops_arith.h" +static inline void get_cf(ir_data_t *ir, int dest_reg) +{ + uop_CALL_FUNC_RESULT(ir, dest_reg, CF_SET); +} + +uint32_t ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_ADD(ir, IREG_AL, IREG_AL, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_ADD(ir, IREG_AX, IREG_AX, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} +uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; +//return 0; + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); + uop_ADD(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } + + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); + uop_ADD(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } + + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); + uop_ADD(ir, IREG_temp2, IREG_temp2, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp2); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -462,6 +719,260 @@ uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ return op_pc + 1; } +uint32_t ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_SUB(ir, IREG_AL, IREG_AL, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_SUB(ir, IREG_AX, IREG_AX, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + return op_pc + 2; +} +uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; +} +uint32_t ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); + uop_SUB(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } + + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); + uop_SUB(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } + + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } + else + { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); + uop_SUB(ir, IREG_temp2, IREG_temp2, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp2); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint8_t imm_data = fastreadb(cs + op_pc); @@ -697,9 +1208,6 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ - return 0; - if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -721,6 +1229,26 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); @@ -785,6 +1313,28 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_ADD(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); @@ -826,9 +1376,6 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch } uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ - return 0; - if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -850,6 +1397,26 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); @@ -914,6 +1481,28 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); @@ -955,9 +1544,6 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ - return 0; - if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -979,6 +1565,26 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); @@ -1041,6 +1647,28 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); @@ -1083,9 +1711,6 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ - return 0; - if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1107,6 +1732,26 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); @@ -1170,6 +1815,28 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); @@ -1212,11 +1879,6 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t imm; - - if ((fetchdat & 0x30) == 0x10) /*ADC/SBB*/ - return 0; - if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1237,6 +1899,26 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); @@ -1272,6 +1954,7 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet else { x86seg *target_seg; + uint32_t imm; uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); @@ -1299,6 +1982,28 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; case 0x20: /*AND*/ uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index 75a70b2..1338102 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -1,3 +1,13 @@ +uint32_t ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); @@ -18,6 +28,16 @@ uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_reg.h b/src/codegen_reg.h index b498ac4..448518e 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -170,6 +170,7 @@ enum IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, + IREG_temp2_B = IREG_temp2 + IREG_SIZE_B, IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, diff --git a/src/x86_flags.h b/src/x86_flags.h index 8d50dba..70d8965 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -292,9 +292,9 @@ static inline int CF_SET() switch (cpu_state.flags_op) { case FLAGS_ADD8: - return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100; + return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100) ? 1 : 0; case FLAGS_ADD16: - return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000; + return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000) ? 1 : 0; case FLAGS_ADD32: return (cpu_state.flags_res < cpu_state.flags_op1); @@ -320,11 +320,11 @@ static inline int CF_SET() (cpu_state.flags_op1 == cpu_state.flags_op2 && cpu_state.flags_res != 0); case FLAGS_SHL8: - return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80; + return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80) ? 1 : 0; case FLAGS_SHL16: - return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000; + return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000) ? 1 : 0; case FLAGS_SHL32: - return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000; + return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000) ? 1 : 0; case FLAGS_SHR8: case FLAGS_SHR16: From 87031d4d0966930b43c329760adaa56f3ab77473 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 20:18:03 +0000 Subject: [PATCH 131/181] Remove readmemb386l() and writememb386l(). --- src/386_common.h | 8 ++--- src/386_dynarec.c | 2 +- src/808x.c | 2 +- src/codegen_backend_x86-64.c | 8 ++--- src/codegen_backend_x86.c | 8 ++--- src/ibm.h | 2 -- src/mem.c | 59 ++---------------------------------- 7 files changed, 17 insertions(+), 72 deletions(-) diff --git a/src/386_common.h b/src/386_common.h index 91bf3c1..fa18096 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -4,10 +4,10 @@ extern uint16_t ea_rseg; #undef writememb -#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmemb386l((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) +#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) #define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writememb386l((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v #define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v #define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v @@ -225,11 +225,11 @@ static inline void seteaq(uint64_t v) writememql(easeg+cpu_state.eaaddr, v); } -#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v +#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v #define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v #define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v -#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg+cpu_state.eaaddr,v); +#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); #define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); #define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3e77c8a..f6c5572 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -428,7 +428,7 @@ int checkio(int port) // pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3)); if ((t+(port>>3))>tr.limit) return 1; cpl_override = 1; - d = readmemb386l(tr.base + t + (port >> 3)); + d = readmembl(tr.base + t + (port >> 3)); // d=readmemb(tr.base,t+(port>>3)); cpl_override = 0; // pclog("%02X %02X\n",d,d&(1<<(port&7))); diff --git a/src/808x.c b/src/808x.c index a20dc29..465156e 100644 --- a/src/808x.c +++ b/src/808x.c @@ -529,7 +529,7 @@ void dumpregs() for (c=0;c<0x0050000;c++) { cpu_state.abrt = 0; - putc(readmemb386l(c+0x80000000),f); + putc(readmembl(c+0x80000000),f); } fclose(f); pclog("Dumping done\n"); diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index bfbf6a7..f1dcd86 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -71,7 +71,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) * PUSH EAX PUSH EDX PUSH ECX - CALL readmemb386l + CALL readmembl POP ECX POP EDX POP EAX @@ -117,7 +117,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) #endif if (size == 1 && !is_float) { - host_x86_CALL(block, (void *)readmemb386l); + host_x86_CALL(block, (void *)readmembl); host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); } else if (size == 2 && !is_float) @@ -169,7 +169,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) * PUSH EAX PUSH EDX PUSH ECX - CALL writememb386l + CALL writemembl POP ECX POP EDX POP EAX @@ -227,7 +227,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data #endif if (size == 1) - host_x86_CALL(block, (void *)writememb386l); + host_x86_CALL(block, (void *)writemembl); else if (size == 2) host_x86_CALL(block, (void *)writememwl); else if (size == 4) diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 7aef0e3..1700eb0 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -71,7 +71,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) * PUSH EAX PUSH EDX PUSH ECX - CALL readmemb386l + CALL readmembl POP ECX POP EDX POP EAX @@ -110,7 +110,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_x86_PUSH(block, REG_EDX); host_x86_PUSH(block, REG_ECX); if (size == 1) - host_x86_CALL(block, (void *)readmemb386l); + host_x86_CALL(block, (void *)readmembl); else if (size == 2) host_x86_CALL(block, (void *)readmemwl); else if (size == 4) @@ -161,7 +161,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) * PUSH EAX PUSH EDX PUSH ECX - CALL writememb386l + CALL writemembl POP ECX POP EDX POP EAX @@ -208,7 +208,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) } host_x86_PUSH(block, REG_EDI); if (size == 1) - host_x86_CALL(block, (void *)writememb386l); + host_x86_CALL(block, (void *)writemembl); else if (size == 2) host_x86_CALL(block, (void *)writememwl); else if (size == 4) diff --git a/src/ibm.h b/src/ibm.h index b587e62..026d4e0 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -45,8 +45,6 @@ extern int mmu_perm; //void writememb(uint32_t addr, uint8_t val); uint8_t readmembl(uint32_t addr); void writemembl(uint32_t addr, uint8_t val); -uint8_t readmemb386l(uint32_t addr); -void writememb386l(uint32_t addr, uint8_t val); uint16_t readmemwl(uint32_t addr); void writememwl(uint32_t addr, uint16_t val); uint32_t readmemll(uint32_t addr); diff --git a/src/mem.c b/src/mem.c index cc253d8..6cb3888 100644 --- a/src/mem.c +++ b/src/mem.c @@ -497,50 +497,6 @@ void writemembl(uint32_t addr, uint8_t val) // else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc); } -uint8_t readmemb386l(uint32_t addr) -{ - mem_logical_addr = addr; -/* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF) - { - return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)]; - }*/ - - if (cr0 >> 31) - { - addr = mmutranslate_read(addr); - if (addr == 0xFFFFFFFF) return 0xFF; - } - - addr &= rammask; - - if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); -// pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc); - return 0xFF; -} - -void writememb386l(uint32_t addr, uint8_t val) -{ - mem_logical_addr = addr; - if (page_lookup[addr>>12]) - { - page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0 >> 31) - { - addr = mmutranslate_write(addr); - if (addr == 0xFFFFFFFF) return; - } - - addr &= rammask; - -/* if (addr >= 0xa0000 && addr < 0xc0000) - pclog("writemembl %08X %02X\n", addr, val);*/ - - if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); -// else pclog("Bad writememb386l %08X %02X %04X:%08X\n", addr, val, CS, pc); -} - uint16_t readmemwl(uint32_t addr) { mem_logical_addr = addr; @@ -556,8 +512,7 @@ uint16_t readmemwl(uint32_t addr) if (mmutranslate_read(addr) == 0xffffffff) return 0xffff; if (mmutranslate_read(addr+1) == 0xffffffff) return 0xffff; } - if (is386) return readmemb386l(addr)|(readmemb386l(addr+1)<<8); - else return readmembl(addr)|(readmembl(addr+1)<<8); + return readmembl(addr)|(readmembl(addr+1)<<8); } else if (readlookup2[addr >> 12] != -1) return *(uint16_t *)(readlookup2[addr >> 12] + addr); @@ -594,16 +549,8 @@ void writememwl(uint32_t addr, uint16_t val) if (mmutranslate_write(addr) == 0xffffffff) return; if (mmutranslate_write(addr+1) == 0xffffffff) return; } - if (is386) - { - writememb386l(addr,val); - writememb386l(addr+1,val>>8); - } - else - { - writemembl(addr,val); - writemembl(addr+1,val>>8); - } + writemembl(addr,val); + writemembl(addr+1,val>>8); return; } else if (writelookup2[addr >> 12] != -1) From 5edc23a602c68ee74267f6ded155885fc19403de Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 20:21:39 +0000 Subject: [PATCH 132/181] Reduce number of massive static arrays in mem.c. --- src/mem.c | 270 ++++++++++++++++++++++++++---------------------------- 1 file changed, 132 insertions(+), 138 deletions(-) diff --git a/src/mem.c b/src/mem.c index 6cb3888..ccc7057 100644 --- a/src/mem.c +++ b/src/mem.c @@ -22,18 +22,10 @@ page_t *pages; page_t **page_lookup; -static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); -static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); -static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); -static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv); -static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv); -static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); -static uint8_t *_mem_exec[0x40000]; -static void *_mem_priv_r[0x40000]; -static void *_mem_priv_w[0x40000]; -static mem_mapping_t *_mem_mapping_r[0x40000]; -static mem_mapping_t *_mem_mapping_w[0x40000]; -static int _mem_state[0x40000]; +static mem_mapping_t *read_mapping[0x40000]; +static mem_mapping_t *write_mapping[0x40000]; +static uint8_t *_mem_exec[0x40000]; +static uint8_t _mem_state[0x40000]; static mem_mapping_t base_mapping; mem_mapping_t ram_low_mapping; @@ -448,7 +440,7 @@ uint8_t *getpccache(uint32_t a) if (_mem_exec[a >> 14]) { - if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM) + if (read_mapping[a >> 14]->flags & MEM_MAPPING_ROM) cpu_prefetch_cycles = cpu_rom_prefetch_cycles; else cpu_prefetch_cycles = cpu_mem_prefetch_cycles; @@ -464,6 +456,8 @@ uint8_t *getpccache(uint32_t a) uint32_t mem_logical_addr; uint8_t readmembl(uint32_t addr) { + mem_mapping_t *map; + mem_logical_addr = addr; if (cr0 >> 31) { @@ -472,13 +466,17 @@ uint8_t readmembl(uint32_t addr) } addr &= rammask; - if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); + map = read_mapping[addr >> 14]; + if (map && map->read_b) + return map->read_b(addr, map->p); // pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc); return 0xFF; } void writemembl(uint32_t addr, uint8_t val) { + mem_mapping_t *map; + mem_logical_addr = addr; if (page_lookup[addr>>12]) @@ -493,12 +491,16 @@ void writemembl(uint32_t addr, uint8_t val) } addr &= rammask; - if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + map = write_mapping[addr >> 14]; + if (map && map->write_b) + return map->write_b(addr, val, map->p); // else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc); } uint16_t readmemwl(uint32_t addr) { + mem_mapping_t *map; + mem_logical_addr = addr; if (addr & 1) @@ -525,10 +527,15 @@ uint16_t readmemwl(uint32_t addr) addr &= rammask; - if (_mem_read_w[addr >> 14]) return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]); + map = read_mapping[addr >> 14]; + if (map) + { + if (map->read_w) + return map->read_w(addr, map->p); - if (_mem_read_b[addr >> 14]) - return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]) | (_mem_read_b[(addr + 1) >> 14](addr + 1, _mem_priv_r[addr >> 14]) << 8); + if (map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + } // pclog("Bad readmemwl %08X\n", addr); return 0xffff; @@ -536,6 +543,8 @@ uint16_t readmemwl(uint32_t addr) void writememwl(uint32_t addr, uint16_t val) { + mem_mapping_t *map; + mem_logical_addr = addr; if (addr & 1) @@ -573,23 +582,25 @@ void writememwl(uint32_t addr, uint16_t val) addr &= rammask; - if (_mem_write_w[addr >> 14]) + map = write_mapping[addr >> 14]; + if (map) { - _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - return; + if (map->write_w) + map->write_w(addr, val, map->p); + else if (map->write_b) + { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + } } - if (_mem_write_b[addr >> 14]) - { - _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - _mem_write_b[(addr + 1) >> 14](addr + 1, val >> 8, _mem_priv_w[addr >> 14]); - return; - } // pclog("Bad writememwl %08X %04X\n", addr, val); } uint32_t readmemll(uint32_t addr) { + mem_mapping_t *map; + mem_logical_addr = addr; if (addr & 3) @@ -617,11 +628,19 @@ uint32_t readmemll(uint32_t addr) addr&=rammask; - if (_mem_read_l[addr >> 14]) return _mem_read_l[addr >> 14](addr, _mem_priv_r[addr >> 14]); + map = read_mapping[addr >> 14]; + if (map) + { + if (map->read_l) + return map->read_l(addr, map->p); - if (_mem_read_w[addr >> 14]) return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]) | (_mem_read_w[addr >> 14](addr + 2, _mem_priv_r[addr >> 14]) << 16); - - if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]) | (_mem_read_b[addr >> 14](addr + 1, _mem_priv_r[addr >> 14]) << 8) | (_mem_read_b[addr >> 14](addr + 2, _mem_priv_r[addr >> 14]) << 16) | (_mem_read_b[addr >> 14](addr + 3, _mem_priv_r[addr >> 14]) << 24); + if (map->read_w) + return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); + + if (map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) | + (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24); + } // pclog("Bad readmemll %08X\n", addr); return 0xffffffff; @@ -629,6 +648,8 @@ uint32_t readmemll(uint32_t addr) void writememll(uint32_t addr, uint32_t val) { + mem_mapping_t *map; + mem_logical_addr = addr; if (addr & 3) @@ -665,33 +686,31 @@ void writememll(uint32_t addr, uint32_t val) addr&=rammask; -/* if (addr >= 0xa0000 && addr < 0xc0000) - pclog("writememll %08X %08X\n", addr, val);*/ - - if (_mem_write_l[addr >> 14]) + map = write_mapping[addr >> 14]; + if (map) { - _mem_write_l[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - return; - } - if (_mem_write_w[addr >> 14]) - { - _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - _mem_write_w[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); - return; - } - if (_mem_write_b[addr >> 14]) - { - _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 1, val >> 8, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 3, val >> 24, _mem_priv_w[addr >> 14]); - return; + if (map->write_l) + map->write_l(addr, val, map->p); + else if (map->write_w) + { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + } + else if (map->write_b) + { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + } } // pclog("Bad writememll %08X %08X\n", addr, val); } uint64_t readmemql(uint32_t addr) { + mem_mapping_t *map; + mem_logical_addr = addr; if (addr & 7) @@ -718,15 +737,17 @@ uint64_t readmemql(uint32_t addr) addr&=rammask; - if (_mem_read_l[addr >> 14]) - return _mem_read_l[addr >> 14](addr, _mem_priv_r[addr >> 14]) | - ((uint64_t)_mem_read_l[addr >> 14](addr + 4, _mem_priv_r[addr >> 14]) << 32); + map = read_mapping[addr >> 14]; + if (map && map->read_l) + return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); } void writememql(uint32_t addr, uint64_t val) { + mem_mapping_t *map; + mem_logical_addr = addr; if (addr & 7) @@ -763,76 +784,87 @@ void writememql(uint32_t addr, uint64_t val) addr&=rammask; - if (_mem_write_l[addr >> 14]) + map = write_mapping[addr >> 14]; + if (map) { - _mem_write_l[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - _mem_write_l[addr >> 14](addr+4, val >> 32, _mem_priv_w[addr >> 14]); - return; - } - if (_mem_write_w[addr >> 14]) - { - _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - _mem_write_w[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); - _mem_write_w[addr >> 14](addr + 4, val >> 32, _mem_priv_w[addr >> 14]); - _mem_write_w[addr >> 14](addr + 6, val >> 48, _mem_priv_w[addr >> 14]); - return; - } - if (_mem_write_b[addr >> 14]) - { - _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 1, val >> 8, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 2, val >> 16, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 3, val >> 24, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 4, val >> 32, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 5, val >> 40, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 6, val >> 48, _mem_priv_w[addr >> 14]); - _mem_write_b[addr >> 14](addr + 7, val >> 56, _mem_priv_w[addr >> 14]); - return; + if (map->write_l) + { + map->write_l(addr, val, map->p); + map->write_l(addr + 4, val >> 32, map->p); + } + else if (map->write_w) + { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + map->write_w(addr + 4, val >> 32, map->p); + map->write_w(addr + 6, val >> 48, map->p); + } + else if (map->write_b) + { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + map->write_b(addr + 4, val >> 32, map->p); + map->write_b(addr + 5, val >> 40, map->p); + map->write_b(addr + 6, val >> 48, map->p); + map->write_b(addr + 7, val >> 56, map->p); + } } // pclog("Bad writememql %08X %08X\n", addr, val); } uint8_t mem_readb_phys(uint32_t addr) { + mem_mapping_t *map = read_mapping[addr >> 14]; + mem_logical_addr = 0xffffffff; - if (_mem_read_b[addr >> 14]) - return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); + if (map && map->read_b) + return map->read_b(addr, map->p); return 0xff; } uint16_t mem_readw_phys(uint32_t addr) { + mem_mapping_t *map = read_mapping[addr >> 14]; + mem_logical_addr = 0xffffffff; - if (_mem_read_w[addr >> 14] && !(addr & 1)) - return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]); + if (map && map->read_w) + return map->read_w(addr, map->p); return mem_readb_phys(addr) | (mem_readb_phys(addr + 1) << 8); } uint32_t mem_readl_phys(uint32_t addr) { + mem_mapping_t *map = read_mapping[addr >> 14]; + mem_logical_addr = 0xffffffff; - if (_mem_read_l[addr >> 14] && !(addr & 3)) - return _mem_read_l[addr >> 14](addr, _mem_priv_r[addr >> 14]); + if (map && map->read_l) + return map->read_l(addr, map->p); return mem_readw_phys(addr) | (mem_readw_phys(addr + 2) << 16); } void mem_writeb_phys(uint32_t addr, uint8_t val) { + mem_mapping_t *map = write_mapping[addr >> 14]; + mem_logical_addr = 0xffffffff; - if (_mem_write_b[addr >> 14]) - _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + if (map && map->write_b) + map->write_b(addr, val, map->p); } void mem_writew_phys(uint32_t addr, uint16_t val) { + mem_mapping_t *map = write_mapping[addr >> 14]; + mem_logical_addr = 0xffffffff; - if (_mem_write_w[addr >> 14] && !(addr & 1)) - _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + if (map && map->write_w && !(addr & 1)) + map->write_w(addr, val, map->p); else { mem_writeb_phys(addr, val); @@ -841,10 +873,12 @@ void mem_writew_phys(uint32_t addr, uint16_t val) } void mem_writel_phys(uint32_t addr, uint32_t val) { + mem_mapping_t *map = write_mapping[addr >> 14]; + mem_logical_addr = 0xffffffff; - if (_mem_write_l[addr >> 14] && !(addr & 3)) - _mem_write_l[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); + if (map && map->write_l && !(addr & 3)) + map->write_l(addr, val, map->p); else { mem_writew_phys(addr, val); @@ -1119,17 +1153,9 @@ static void mem_mapping_recalc(uint64_t base, uint64_t size) /*Clear out old mappings*/ for (c = base; c < base + size; c += 0x4000) { - _mem_read_b[c >> 14] = NULL; - _mem_read_w[c >> 14] = NULL; - _mem_read_l[c >> 14] = NULL; - _mem_priv_r[c >> 14] = NULL; - _mem_mapping_r[c >> 14] = NULL; + read_mapping[c >> 14] = NULL; + write_mapping[c >> 14] = NULL; _mem_exec[c >> 14] = NULL; - _mem_write_b[c >> 14] = NULL; - _mem_write_w[c >> 14] = NULL; - _mem_write_l[c >> 14] = NULL; - _mem_priv_w[c >> 14] = NULL; - _mem_mapping_w[c >> 14] = NULL; } /*Walk mapping list*/ @@ -1148,24 +1174,16 @@ static void mem_mapping_recalc(uint64_t base, uint64_t size) if ((mapping->read_b || mapping->read_w || mapping->read_l) && mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14])) { - _mem_read_b[c >> 14] = mapping->read_b; - _mem_read_w[c >> 14] = mapping->read_w; - _mem_read_l[c >> 14] = mapping->read_l; + read_mapping[c >> 14] = mapping; if (mapping->exec) _mem_exec[c >> 14] = mapping->exec + (c - mapping->base); else _mem_exec[c >> 14] = NULL; - _mem_priv_r[c >> 14] = mapping->p; - _mem_mapping_r[c >> 14] = mapping; } if ((mapping->write_b || mapping->write_w || mapping->write_l) && mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14])) { - _mem_write_b[c >> 14] = mapping->write_b; - _mem_write_w[c >> 14] = mapping->write_w; - _mem_write_l[c >> 14] = mapping->write_l; - _mem_priv_w[c >> 14] = mapping->p; - _mem_mapping_w[c >> 14] = mapping; + write_mapping[c >> 14] = mapping; } } } @@ -1336,20 +1354,8 @@ void mem_init() pages[c].evict_prev = EVICT_NOT_IN_LIST; } - memset(isram, 0, sizeof(isram)); - for (c = 0; c < (mem_size / 64); c++) - { - isram[c] = 1; - if ((c >= 0xa && c <= 0xf) || (cpu_16bitbus && c >= 0xfe && c <= 0xff)) - isram[c] = 0; - } - - memset(_mem_read_b, 0, sizeof(_mem_read_b)); - memset(_mem_read_w, 0, sizeof(_mem_read_w)); - memset(_mem_read_l, 0, sizeof(_mem_read_l)); - memset(_mem_write_b, 0, sizeof(_mem_write_b)); - memset(_mem_write_w, 0, sizeof(_mem_write_w)); - memset(_mem_write_l, 0, sizeof(_mem_write_l)); + memset(read_mapping, 0, sizeof(read_mapping)); + memset(write_mapping, 0, sizeof(write_mapping)); memset(_mem_exec, 0, sizeof(_mem_exec)); memset(ff_array, 0xff, sizeof(ff_array)); @@ -1446,20 +1452,8 @@ void mem_resize() pages[c].evict_prev = EVICT_NOT_IN_LIST; } - memset(isram, 0, sizeof(isram)); - for (c = 0; c < (mem_size / 64); c++) - { - isram[c] = 1; - if ((c >= 0xa && c <= 0xf) || (cpu_16bitbus && c >= 0xfe && c <= 0xff)) - isram[c] = 0; - } - - memset(_mem_read_b, 0, sizeof(_mem_read_b)); - memset(_mem_read_w, 0, sizeof(_mem_read_w)); - memset(_mem_read_l, 0, sizeof(_mem_read_l)); - memset(_mem_write_b, 0, sizeof(_mem_write_b)); - memset(_mem_write_w, 0, sizeof(_mem_write_w)); - memset(_mem_write_l, 0, sizeof(_mem_write_l)); + memset(read_mapping, 0, sizeof(read_mapping)); + memset(write_mapping, 0, sizeof(write_mapping)); memset(_mem_exec, 0, sizeof(_mem_exec)); memset(&base_mapping, 0, sizeof(base_mapping)); From 3c2dbf063ee3ad0eac72d7f75866585bf9288724 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 20:23:14 +0000 Subject: [PATCH 133/181] Remove unused and superfluous variables from mem.c. --- src/808x.c | 2 -- src/ali1429.c | 2 -- src/headland.c | 4 +--- src/i430fx.c | 1 - src/i430lx.c | 1 - src/i430vx.c | 1 - src/ibm.h | 8 -------- src/mcr.c | 3 +-- src/mem.c | 23 ++++------------------- src/mem.h | 2 -- src/opti495.c | 7 +------ src/pc.c | 5 +---- src/ps2_mca.c | 4 +--- src/scat.c | 2 -- src/sis496.c | 1 - src/um8881f.c | 3 +-- 16 files changed, 10 insertions(+), 59 deletions(-) diff --git a/src/808x.c b/src/808x.c index 465156e..1ea2091 100644 --- a/src/808x.c +++ b/src/808x.c @@ -97,8 +97,6 @@ int noint=0; int output=0; -int shadowbios=0; - int ins=0; //#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a)) diff --git a/src/ali1429.c b/src/ali1429.c index 388ab48..099a865 100644 --- a/src/ali1429.c +++ b/src/ali1429.c @@ -55,8 +55,6 @@ void ali1429_write(uint16_t port, uint8_t val, void *priv) ali1429_recalc(); break; case 0x14: - shadowbios = val & 1; - shadowbios_write = val & 2; ali1429_recalc(); break; } diff --git a/src/headland.c b/src/headland.c index b3bc4d0..c0ebe01 100644 --- a/src/headland.c +++ b/src/headland.c @@ -20,9 +20,7 @@ void headland_write(uint16_t addr, uint8_t val, void *priv) pclog("Headland write %02X %02X\n",headland_index,val); if (headland_index == 0x82) { - shadowbios = val & 0x10; - shadowbios_write = !(val & 0x10); - if (shadowbios) + if (val & 0x10) mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); else mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); diff --git a/src/i430fx.c b/src/i430fx.c index 8a7fe79..4d328b2 100644 --- a/src/i430fx.c +++ b/src/i430fx.c @@ -65,7 +65,6 @@ void i430fx_write(int func, int addr, uint8_t val, void *priv) if ((card_i430fx[0x59] ^ val) & 0xf0) { i430fx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); } pclog("i430fx_write : PAM0 write %02X\n", val); break; diff --git a/src/i430lx.c b/src/i430lx.c index ebde9bc..17ef4a9 100644 --- a/src/i430lx.c +++ b/src/i430lx.c @@ -65,7 +65,6 @@ void i430lx_write(int func, int addr, uint8_t val, void *priv) if ((card_i430lx[0x59] ^ val) & 0xf0) { i430lx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); } pclog("i430lx_write : PAM0 write %02X\n", val); break; diff --git a/src/i430vx.c b/src/i430vx.c index 6b1c4bb..79b7517 100644 --- a/src/i430vx.c +++ b/src/i430vx.c @@ -64,7 +64,6 @@ void i430vx_write(int func, int addr, uint8_t val, void *priv) if ((card_i430vx[0x59] ^ val) & 0xf0) { i430vx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); } pclog("i430vx_write : PAM0 write %02X\n", val); break; diff --git a/src/ibm.h b/src/ibm.h index 026d4e0..f9974be 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -36,13 +36,6 @@ extern int mmu_perm; #define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -//#define writememb(a,v) if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v); else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v -//#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v -//#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v -//#define readmemb(a) ((isram[((a)>>16)&255] && !(cr0>>31))?ram[a&0xFFFFFF]:readmembl(a)) -//#define writememb(a,v) if (isram[((a)>>16)&255] && !(cr0>>31)) ram[a&0xFFFFFF]=v; else writemembl(a,v) - -//void writememb(uint32_t addr, uint8_t val); uint8_t readmembl(uint32_t addr); void writemembl(uint32_t addr, uint8_t val); uint16_t readmemwl(uint32_t addr); @@ -69,7 +62,6 @@ uint32_t inl(uint16_t port); void outl(uint16_t port, uint32_t val); FILE *romfopen(char *fn, char *mode); -extern int shadowbios,shadowbios_write; extern int mem_size; extern int readlnum,writelnum; diff --git a/src/mcr.c b/src/mcr.c index 83d7530..81293c2 100644 --- a/src/mcr.c +++ b/src/mcr.c @@ -10,7 +10,6 @@ void resetmcr() { mcrlock=0; mcrfirst=1; - shadowbios=0; } void writemcr(uint16_t addr, uint8_t val) @@ -29,7 +28,7 @@ void writemcr(uint16_t addr, uint8_t val) // exit(-1); break; case 0x23: - if (nextreg6) shadowbios=!val; +// if (nextreg6) shadowbios=!val; break; } mcr22=val; diff --git a/src/mem.c b/src/mem.c index ccc7057..74e7980 100644 --- a/src/mem.c +++ b/src/mem.c @@ -36,10 +36,6 @@ mem_mapping_t bios_mapping[8]; mem_mapping_t bios_high_mapping[8]; static mem_mapping_t romext_mapping; -int shadowbios,shadowbios_write; - -unsigned char isram[0x10000]; - static uint8_t ff_array[0x1000]; int mem_size; @@ -50,7 +46,10 @@ int cachesize=256; uint8_t *ram, *rom = NULL; uint8_t romext[32768]; -//int abrt=0; +uint32_t mem_logical_addr; + +int mmuflush=0; +int mmu_perm=4; void resetreadlookup() { @@ -68,9 +67,6 @@ void resetreadlookup() } -int mmuflush=0; -int mmu_perm=4; - void flushmmucache() { int c; @@ -202,15 +198,9 @@ void mem_flush_write_page(uint32_t addr, uint32_t virt) } } -extern int output; - #define mmutranslate_read(addr) mmutranslatereal(addr,0) #define mmutranslate_write(addr) mmutranslatereal(addr,1) -int pctrans=0; - -extern uint32_t testr[9]; - static inline uint32_t mmu_readl(uint32_t addr) { return *(uint32_t *)&_mem_exec[addr >> 14][addr & 0x3fff]; @@ -423,16 +413,13 @@ void addwritelookup(uint32_t virt, uint32_t phys) cycles -= 9; } -#undef printf uint8_t *getpccache(uint32_t a) { uint32_t a2=a; if (cr0>>31) { - pctrans=1; a = mmutranslate_read(a); - pctrans=0; if (a==0xFFFFFFFF) return ram; } @@ -451,9 +438,7 @@ uint8_t *getpccache(uint32_t a) pclog("Bad getpccache %08X\n", a); return &ff_array[0-(uintptr_t)(a2 & ~0xFFF)]; } -#define printf pclog -uint32_t mem_logical_addr; uint8_t readmembl(uint32_t addr) { mem_mapping_t *map; diff --git a/src/mem.h b/src/mem.h index 4b640ea..5a21e6a 100644 --- a/src/mem.h +++ b/src/mem.h @@ -222,7 +222,5 @@ void mmu_invalidate(uint32_t addr); int loadbios(); -extern unsigned char isram[0x10000]; - extern int purgeable_page_count; #endif diff --git a/src/opti495.c b/src/opti495.c index 1faef5a..ebf8e2b 100644 --- a/src/opti495.c +++ b/src/opti495.c @@ -27,15 +27,10 @@ static void opti495_write(uint16_t addr, uint8_t val, void *p) } if (optireg == 0x22) { - shadowbios = !(val & 0x80); - shadowbios_write = val & 0x80; - //pclog("shadowbios %i %02x\n", shadowbios, val); - if (shadowbios) + if (!(val & 0x80)) mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); else mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); -// if (shadowbios) -// fatal("Here\n"); } } break; diff --git a/src/pc.c b/src/pc.c index ea77535..23099a1 100644 --- a/src/pc.c +++ b/src/pc.c @@ -360,8 +360,7 @@ void initpc(int argc, char *argv[]) ali1429_reset(); // CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9)); // pclog("Init - CPUID %i %i\n",CPUID,cpuspeed); - shadowbios=0; - + #if __unix if (cdrom_drive == -1) cdrom_null_reset(); @@ -387,7 +386,6 @@ void resetpc() // cpuspeed2=(AT)?2:1; // atfullspeed=0; ///* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed(); - shadowbios=0; } void resetpc_cad() @@ -449,7 +447,6 @@ void resetpchard() // atfullspeed = 0; // setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed); - shadowbios = 0; ali1429_reset(); keyboard_at_reset(); diff --git a/src/ps2_mca.c b/src/ps2_mca.c index 5113642..1e8b77f 100644 --- a/src/ps2_mca.c +++ b/src/ps2_mca.c @@ -404,10 +404,8 @@ static void model_55sx_write(uint16_t port, uint8_t val) case 0x105: pclog("Write POS3 %02x\n", val); ps2.option[3] = val; - shadowbios = !(val & 0x10); - shadowbios_write = val & 0x10; - if (shadowbios) + if (!(val & 0x10)) { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); mem_mapping_disable(&ps2.shadow_mapping); diff --git a/src/scat.c b/src/scat.c index 966814f..a899b95 100644 --- a/src/scat.c +++ b/src/scat.c @@ -564,8 +564,6 @@ void scat_init() mem_mapping_disable(&scat_mapping[i]); } - for(i=4;i<10;i++) isram[i] = 0; - // TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later. for (i = 12; i < 16; i++) { diff --git a/src/sis496.c b/src/sis496.c index b958feb..6738ba5 100644 --- a/src/sis496.c +++ b/src/sis496.c @@ -43,7 +43,6 @@ void sis496_recalcmapping(sis496_t *sis496) } flushmmucache(); - shadowbios = (sis496->pci_conf[0x44] & 0xf0); } void sis496_write(int func, int addr, uint8_t val, void *p) diff --git a/src/um8881f.c b/src/um8881f.c index b469bbd..84c0434 100644 --- a/src/um8881f.c +++ b/src/um8881f.c @@ -33,8 +33,7 @@ void um8881f_write(int func, int addr, uint8_t val, void *priv) case 0x80: mem_bios_set_state(0xf0000, 0x10000, 1, 1); break; case 0xc0: mem_bios_set_state(0xf0000, 0x10000, 1, 0); break; }*/ - shadowbios = val & 0x80; - shadowbios_write = !(val & 0x40); +// shadowbios = val & 0x80; flushmmucache_nopc(); } } From 2735920f5847907fab354121d527da6b37e4f2c6 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 20:34:06 +0000 Subject: [PATCH 134/181] De-duplicate allocation code in mem_init(). --- src/mem.c | 78 +++++++++---------------------------------------- src/mem.h | 2 +- src/pc.c | 2 +- src/wx-config.c | 2 +- 4 files changed, 16 insertions(+), 68 deletions(-) diff --git a/src/mem.c b/src/mem.c index 74e7980..9c6c536 100644 --- a/src/mem.c +++ b/src/mem.c @@ -1313,69 +1313,6 @@ void mem_add_bios() int mem_a20_key = 0, mem_a20_alt = 0; static int mem_a20_state = 2; -void mem_init() -{ - int c; - - ram = malloc(mem_size * 1024); -// rom = malloc(0x20000); - readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); - writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); - biosmask = 0xffff; - pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); - page_lookup = malloc((1 << 20) * sizeof(page_t *)); - - memset(ram, 0, mem_size * 1024); - memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); - - memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); - - for (c = 0; c < (((mem_size + 384) * 1024) >> 12); c++) - { - pages[c].mem = &ram[c << 12]; - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - pages[c].evict_prev = EVICT_NOT_IN_LIST; - } - - memset(read_mapping, 0, sizeof(read_mapping)); - memset(write_mapping, 0, sizeof(write_mapping)); - memset(_mem_exec, 0, sizeof(_mem_exec)); - - memset(ff_array, 0xff, sizeof(ff_array)); - - memset(&base_mapping, 0, sizeof(base_mapping)); - - memset(_mem_state, 0, sizeof(_mem_state)); - - mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - mem_mapping_add(&ram_low_mapping, 0x00000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL); - if (mem_size > 1024) - { - if (cpu_16bitbus && mem_size > 16256) - { - mem_set_mem_state(0x100000, (16256 - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, ((16256 - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - } - else - { - mem_set_mem_state(0x100000, (mem_size - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - } - } - if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); - - if (romset == ROM_IBMPS1_2011) - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); -// pclog("Mem resize %i %i\n",mem_size,c); - mem_a20_key = 2; - mem_a20_alt = 0; -} - static void mem_remap_top(int max_size) { int c; @@ -1417,7 +1354,16 @@ void mem_set_704kb() mem_mapping_set_addr(&ram_low_mapping, 0x00000, (mem_size > 704) ? 0xb0000 : mem_size * 1024); } -void mem_resize() +void mem_init() +{ + readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); + writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); + page_lookup = malloc((1 << 20) * sizeof(page_t *)); + + memset(ff_array, 0xff, sizeof(ff_array)); +} + +void mem_alloc() { int c; @@ -1436,7 +1382,9 @@ void mem_resize() pages[c].write_l = mem_write_raml_page; pages[c].evict_prev = EVICT_NOT_IN_LIST; } - + + memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); + memset(read_mapping, 0, sizeof(read_mapping)); memset(write_mapping, 0, sizeof(write_mapping)); memset(_mem_exec, 0, sizeof(_mem_exec)); diff --git a/src/mem.h b/src/mem.h index 5a21e6a..3bffffd 100644 --- a/src/mem.h +++ b/src/mem.h @@ -208,7 +208,7 @@ void mem_flush_write_page(uint32_t addr, uint32_t virt); void mem_add_bios(); void mem_init(); -void mem_resize(); +void mem_alloc(); void mem_set_704kb(); diff --git a/src/pc.c b/src/pc.c index 23099a1..d3fd112 100644 --- a/src/pc.c +++ b/src/pc.c @@ -408,7 +408,7 @@ void resetpchard() sound_reset(); io_init(); cpu_set(); - mem_resize(); + mem_alloc(); fdc_init(); disc_reset(); disc_load(0, discfns[0]); diff --git a/src/wx-config.c b/src/wx-config.c index 618363d..90c38a3 100644 --- a/src/wx-config.c +++ b/src/wx-config.c @@ -553,7 +553,7 @@ int config_dlgsave(void* hdlg) if (has_been_inited) { - mem_resize(); + mem_alloc(); loadbios(); resetpchard(); } From 1af0b660b37601d99ba6029bf730655c6a0d71d4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 21:30:53 +0000 Subject: [PATCH 135/181] First pass at sanitising CPU headers. --- src/386.c | 22 +++++------ src/386.h | 13 ------- src/386_common.h | 3 -- src/386_dynarec.c | 27 ++++--------- src/386_dynarec_ops.c | 4 -- src/808x.c | 21 +++++------ src/codegen_ops_jump.c | 1 - src/codegen_ops_misc.c | 1 - src/fdc.c | 1 - src/ibm.h | 1 - src/pc.c | 1 - src/pic.c | 1 - src/x86.h | 86 ++++++++++++++++-------------------------- src/x86_flags.h | 4 ++ src/x86_ops_call.h | 22 +++++------ src/x86_ops_jump.h | 8 ++-- src/x86_ops_ret.h | 5 --- src/x86seg.c | 27 +++++-------- 18 files changed, 87 insertions(+), 161 deletions(-) delete mode 100644 src/386.h diff --git a/src/386.c b/src/386.c index a0ad35f..4568199 100644 --- a/src/386.c +++ b/src/386.c @@ -2,7 +2,6 @@ #include #include #include "ibm.h" -#include "386.h" #include "x86.h" #include "x87.h" #include "mem.h" @@ -20,7 +19,10 @@ extern int codegen_flags_changed; extern int nmi_enable; -int inscounts[256]; +uint32_t use32; +int stack32; +int optype; + uint32_t oldpc2; int trap; @@ -31,7 +33,6 @@ extern int cpl_override; int has_fpu; extern int fpucount; -uint16_t rds; uint16_t ea_rseg; int is486; @@ -42,9 +43,8 @@ int cgate32; uint8_t romext[32768]; uint8_t *ram,*rom; -uint32_t rmdat32; -#define rmdat rmdat32 -#define fetchdat rmdat32 +uint32_t rmdat; + uint32_t backupregs[16]; extern int oddeven; int inttype; @@ -54,9 +54,6 @@ uint32_t oldecx; uint32_t *eal_r, *eal_w; -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; - static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; @@ -245,10 +242,10 @@ dontprint=0; fetchdat = fastreadl(cs + cpu_state.pc); if (!cpu_state.abrt) - { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; + { + uint8_t opcode = fetchdat & 0xFF; fetchdat >>= 8; + trap = cpu_state.flags & T_FLAG; if (output == 3) { @@ -350,7 +347,6 @@ dontprint=0; addr = (temp << 2) + idt.base; cpu_state.flags &= ~I_FLAG; cpu_state.flags &= ~T_FLAG; - oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); // if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc); diff --git a/src/386.h b/src/386.h deleted file mode 100644 index 595773e..0000000 --- a/src/386.h +++ /dev/null @@ -1,13 +0,0 @@ -extern void cpu_386_flags_extract(); -extern void cpu_386_flags_rebuild(); - -void pmodeint(int num, int soft); -void loadcscall(uint16_t seg); -void loadcsjmp(uint16_t seg, uint32_t oxpc); -void pmoderetf(int is32, uint16_t off); -void pmodeiret(int is32); -void x86_int_sw(int num); -int x86_int_sw_rm(int num); - -int divl(uint32_t val); -int idivl(int32_t val); diff --git a/src/386_common.h b/src/386_common.h index fa18096..cf12239 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -239,7 +239,4 @@ static inline void seteaq(uint64_t v) #define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 -#define rmdat rmdat32 -#define fetchdat rmdat32 - void x86_int(int num); diff --git a/src/386_dynarec.c b/src/386_dynarec.c index f6c5572..43388fc 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -2,7 +2,6 @@ #include #include #include "ibm.h" -#include "386.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -32,7 +31,6 @@ int cpu_block_end = 0; int nmi_enable = 1; -int inscounts[256]; uint32_t oldpc2; int trap; @@ -43,7 +41,6 @@ int cpl_override=0; int has_fpu; int fpucount=0; -uint16_t rds; uint16_t ea_rseg; int is486; @@ -53,7 +50,6 @@ int cgate32; uint8_t romext[32768]; uint8_t *ram,*rom; -uint32_t rmdat32; uint32_t backupregs[16]; int oddeven=0; int inttype; @@ -61,11 +57,6 @@ int inttype; uint32_t oldecx; -uint32_t *eal_r, *eal_w; - -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; - static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; @@ -231,7 +222,6 @@ void x86_int(int num) cpu_state.flags &= ~I_FLAG; cpu_state.flags &= ~T_FLAG; - oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); } @@ -278,7 +268,6 @@ void x86_int_sw(int num) cpu_state.flags &= ~I_FLAG; cpu_state.flags &= ~T_FLAG; - oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); cycles -= timing_int_rm; @@ -311,7 +300,6 @@ int x86_int_sw_rm(int num) cpu_state.flags &= ~T_FLAG; cpu_state.pc = new_pc; loadcs(new_cs); - oxpc=cpu_state.pc; cycles -= timing_int_rm; trap = 0; @@ -548,9 +536,9 @@ void exec386_dynarec(int cycs) if (!cpu_state.abrt) { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; + uint8_t opcode = fetchdat & 0xFF; fetchdat >>= 8; + trap = cpu_state.flags & T_FLAG; // if (output == 3) // pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); @@ -685,9 +673,10 @@ void exec386_dynarec(int cycs) if (!cpu_state.abrt) { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; + uint8_t opcode = fetchdat & 0xFF; fetchdat >>= 8; + + trap = cpu_state.flags & T_FLAG; // if (output == 3) // pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); @@ -757,10 +746,11 @@ void exec386_dynarec(int cycs) if (!cpu_state.abrt) { - trap = cpu_state.flags & T_FLAG; - opcode = fetchdat & 0xFF; + uint8_t opcode = fetchdat & 0xFF; fetchdat >>= 8; + trap = cpu_state.flags & T_FLAG; + // if (output == 3) // pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); @@ -885,7 +875,6 @@ void exec386_dynarec(int cycs) addr=temp<<2; cpu_state.flags &= ~I_FLAG; cpu_state.flags &= ~T_FLAG; - oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); } diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index 342e138..1b77f71 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -1,6 +1,5 @@ #include "ibm.h" #include "cpu.h" -#include "386.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -15,9 +14,6 @@ #include "386_common.h" -extern uint16_t *mod1add[2][8]; -extern uint32_t *mod1seg[8]; - static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; diff --git a/src/808x.c b/src/808x.c index 1ea2091..fa83679 100644 --- a/src/808x.c +++ b/src/808x.c @@ -38,6 +38,8 @@ int nopageerrors=0; void FETCHCOMPLETE(); +#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) + #undef readmemb #undef readmemw uint8_t readmemb(uint32_t a) @@ -91,9 +93,8 @@ void writememl(uint32_t s, uint32_t a, uint32_t v) int oldcpl; int tempc; -uint8_t opcode; uint16_t pc2,pc3; -int noint=0; +static int noint=0; int output=0; @@ -330,9 +331,9 @@ reg = If mod=11, (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit */ uint32_t easeg; -int rmdat; +uint32_t rmdat; -uint16_t zero=0; +static uint16_t zero=0; uint16_t *mod1add[2][8]; uint32_t *mod1seg[8]; @@ -429,7 +430,7 @@ static inline void seteaw(uint16_t val) /*Flags*/ uint8_t znptable8[256]; -uint16_t znptable16[65536]; +static uint16_t znptable16[65536]; void makeznptable() { @@ -649,7 +650,6 @@ void resetx86() EAX = 0; ESP=0; mmu_perm=4; - memset(inscounts, 0, sizeof(inscounts)); x86seg_reset(); codegen_reset(); x86_was_reset = 1; @@ -1112,10 +1112,9 @@ void rep(int fv) } -int inhlt=0; -uint16_t lastpc,lastcs; +static int inhlt=0; int firstrepcycle; -int skipnextprint=0; +static int skipnextprint=0; int instime=0; //#if 0 @@ -1136,6 +1135,8 @@ void execx86(int cycs) // return; while (cycles>0) { + uint8_t opcode; + // old83=old82; // old82=old8; // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; } @@ -2450,8 +2451,6 @@ void execx86(int cycs) cycles-=72; break; case 0xCD: /*INT*/ - lastpc=cpu_state.pc; - lastcs=CS; temp=FETCH(); if (cpu_state.ssegs) ss=oldss; diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index d559881..c2c7eb6 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -2,7 +2,6 @@ #include "x86.h" #include "386_common.h" -#include "386.h" #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index 8afb20a..2db4c32 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -3,7 +3,6 @@ #include "x86.h" #include "x86_flags.h" #include "386_common.h" -#include "386.h" #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" diff --git a/src/fdc.c b/src/fdc.c index 883cf01..f958bd3 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -70,7 +70,6 @@ typedef struct FDC static FDC fdc; void fdc_callback(); -int timetolive; //#define SECTORS 9 int lastbyte=0; uint8_t disc_3f7; diff --git a/src/ibm.h b/src/ibm.h index f9974be..9b3a07a 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -276,7 +276,6 @@ uint32_t dr[8]; //#define IOPLV86 ((!(msw&1)) || (CPL<=IOPL)) extern int cycles_lost; extern int is486; -extern uint8_t opcode; extern int insc; extern int fpucount; extern float mips,flops; diff --git a/src/pc.c b/src/pc.c index d3fd112..d574087 100644 --- a/src/pc.c +++ b/src/pc.c @@ -81,7 +81,6 @@ void fullspeed(); int framecount,fps; -int output; int atfullspeed; void saveconfig(char *fn); diff --git a/src/pic.c b/src/pic.c index b1110a4..a7636ef 100644 --- a/src/pic.c +++ b/src/pic.c @@ -4,7 +4,6 @@ #include "pit.h" #include "video.h" -int output; int intclear; int keywaiting=0; int pic_intpending; diff --git a/src/x86.h b/src/x86.h index 5a76ba9..5f0be4d 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,22 +1,30 @@ -extern uint32_t rmdat32; -int oldcpl; +extern uint32_t rmdat; +#define fetchdat rmdat + +extern uint32_t easeg; + +extern int oldcpl; extern int nmi_enable; -int tempc; -int output; -int firstrepcycle; +extern int output; +extern int timetolive; -uint32_t easeg,ealimit,ealimitw; +extern uint8_t znptable8[256]; -int skipnextprint; -int inhlt; +extern uint32_t use32; +extern int stack32; + +extern uint16_t *mod1add[2][8]; +extern uint32_t *mod1seg[8]; + +extern int cgate32; + +extern uint32_t *eal_r, *eal_w; + +extern int x86_was_reset; -uint8_t opcode; -int noint; -uint16_t lastcs,lastpc; -int timetolive,keyboardtimer; #define setznp168 setznp16 @@ -29,12 +37,6 @@ int timetolive,keyboardtimer; #define setr16(r,v) cpu_state.regs[r].w=v #define setr32(r,v) cpu_state.regs[r].l=v -uint8_t znptable8[256]; -uint16_t znptable16[65536]; - -int use32; -int stack32; - #define fetchea() { rmdat=readmemb(cs+pc); pc++; \ reg=(rmdat>>3)&7; \ mod=(rmdat>>6)&3; \ @@ -42,34 +44,12 @@ int stack32; if (mod!=3) fetcheal(); } -int optype; +extern int optype; #define JMP 1 #define CALL 2 #define IRET 3 #define OPTYPE_INT 4 -uint32_t oxpc; - -extern uint16_t *mod1add[2][8]; -extern uint32_t *mod1seg[8]; - - -#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) - -extern int cgate32; - - -extern uint32_t *eal_r, *eal_w; - - -extern uint32_t flags_zn; -extern uint8_t flags_p; -#define FLAG_N (flags_zn>>31) -#define FLAG_Z (flags_zn) -#define FLAG_P (znptable8[flags_p]&P_FLAG) - -extern int gpf; - enum { @@ -86,22 +66,14 @@ extern uint32_t abrt_error; void x86_doabrt(int x86_abrt); -extern uint8_t opcode2; - -extern uint16_t rds; -extern uint32_t rmdat32; - -extern int inscounts[256]; +extern int codegen_flat_ds; +extern int codegen_flat_ss; void x86illegal(); void x86seg_reset(); void x86gpf(char *s, uint16_t error); -extern uint16_t zero; - -extern int x86_was_reset; - void resetx86(); void softresetx86(); void refreshread(); @@ -111,5 +83,13 @@ void execx86(int cycs); void exec386(int cycs); void exec386_dynarec(int cycs); -extern int codegen_flat_ds; -extern int codegen_flat_ss; +void pmodeint(int num, int soft); +void loadcscall(uint16_t seg, uint32_t old_pc); +void loadcsjmp(uint16_t seg, uint32_t old_pc); +void pmoderetf(int is32, uint16_t off); +void pmodeiret(int is32); +void x86_int_sw(int num); +int x86_int_sw_rm(int num); + +int divl(uint32_t val); +int idivl(int32_t val); diff --git a/src/x86_flags.h b/src/x86_flags.h index 70d8965..4332fad 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -1,3 +1,5 @@ +extern int tempc; + enum { FLAGS_UNKNOWN, @@ -553,3 +555,5 @@ static inline void setsbc32(uint32_t a, uint32_t b) cpu_state.flags_op = FLAGS_SBC32; } +extern void cpu_386_flags_extract(); +extern void cpu_386_flags_rebuild(); diff --git a/src/x86_ops_call.h b/src/x86_ops_call.h index aa126c6..4c2e117 100644 --- a/src/x86_ops_call.h +++ b/src/x86_ops_call.h @@ -1,11 +1,10 @@ #define CALL_FAR_w(new_seg, new_pc) \ old_cs = CS; \ old_pc = cpu_state.pc; \ - oxpc = cpu_state.pc; \ cpu_state.pc = new_pc; \ optype = CALL; \ cgate16 = cgate32 = 0; \ - if (msw & 1) loadcscall(new_seg); \ + if (msw & 1) loadcscall(new_seg, old_pc); \ else \ { \ loadcs(new_seg); \ @@ -30,11 +29,10 @@ #define CALL_FAR_l(new_seg, new_pc) \ old_cs = CS; \ old_pc = cpu_state.pc; \ - oxpc = cpu_state.pc; \ cpu_state.pc = new_pc; \ optype = CALL; \ cgate16 = cgate32 = 0; \ - if (msw & 1) loadcscall(new_seg); \ + if (msw & 1) loadcscall(new_seg, old_pc); \ else \ { \ loadcs(new_seg); \ @@ -158,11 +156,11 @@ static int opFF_w_a16(uint32_t fetchdat) case 0x28: /*JMP far*/ if (cpu_mod != 3) SEG_CHECK_READ(cpu_state.ea_seg); - oxpc = cpu_state.pc; + old_pc = cpu_state.pc; new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; + loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 0); PREFETCH_FLUSH(); @@ -249,11 +247,11 @@ static int opFF_w_a32(uint32_t fetchdat) case 0x28: /*JMP far*/ if (cpu_mod != 3) SEG_CHECK_READ(cpu_state.ea_seg); - oxpc = cpu_state.pc; + old_pc = cpu_state.pc; new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; + loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 1); PREFETCH_FLUSH(); @@ -341,11 +339,11 @@ static int opFF_l_a16(uint32_t fetchdat) case 0x28: /*JMP far*/ if (cpu_mod != 3) SEG_CHECK_READ(cpu_state.ea_seg); - oxpc = cpu_state.pc; + old_pc = cpu_state.pc; new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; + loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 0); PREFETCH_FLUSH(); @@ -432,11 +430,11 @@ static int opFF_l_a32(uint32_t fetchdat) case 0x28: /*JMP far*/ if (cpu_mod != 3) SEG_CHECK_READ(cpu_state.ea_seg); - oxpc = cpu_state.pc; + old_pc = cpu_state.pc; new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; + loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1); PREFETCH_FLUSH(); diff --git a/src/x86_ops_jump.h b/src/x86_ops_jump.h index a7c4fd5..94cad2d 100644 --- a/src/x86_ops_jump.h +++ b/src/x86_ops_jump.h @@ -270,9 +270,9 @@ static int opJMP_far_a16(uint32_t fetchdat) { uint16_t addr = getwordf(); uint16_t seg = getword(); if (cpu_state.abrt) return 1; - uint32_t oxpc = cpu_state.pc; + uint32_t old_pc = cpu_state.pc; cpu_state.pc = addr; - loadcsjmp(seg, oxpc); + loadcsjmp(seg, old_pc); CPU_BLOCK_END(); PREFETCH_RUN(11, 5, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); @@ -282,9 +282,9 @@ static int opJMP_far_a32(uint32_t fetchdat) { uint32_t addr = getlong(); uint16_t seg = getword(); if (cpu_state.abrt) return 1; - uint32_t oxpc = cpu_state.pc; + uint32_t old_pc = cpu_state.pc; cpu_state.pc = addr; - loadcsjmp(seg, oxpc); + loadcsjmp(seg, old_pc); CPU_BLOCK_END(); PREFETCH_RUN(11, 7, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); diff --git a/src/x86_ops_ret.h b/src/x86_ops_ret.h index b69180c..70ac327 100644 --- a/src/x86_ops_ret.h +++ b/src/x86_ops_ret.h @@ -4,7 +4,6 @@ pmoderetf(0, stack_offset); \ return 1; \ } \ - oxpc = cpu_state.pc; \ if (stack32) \ { \ cpu_state.pc = readmemw(ss, ESP); \ @@ -26,7 +25,6 @@ pmoderetf(1, stack_offset); \ return 1; \ } \ - oxpc = cpu_state.pc; \ if (stack32) \ { \ cpu_state.pc = readmeml(ss, ESP); \ @@ -108,7 +106,6 @@ static int opIRET_286(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; if (stack32) { cpu_state.pc = readmemw(ss, ESP); @@ -184,7 +181,6 @@ static int opIRET(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; if (stack32) { cpu_state.pc = readmemw(ss, ESP); @@ -230,7 +226,6 @@ static int opIRETD(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; if (stack32) { cpu_state.pc = readmeml(ss, ESP); diff --git a/src/x86seg.c b/src/x86seg.c index 7876ae0..bed02ad 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -5,7 +5,7 @@ #include "ibm.h" #include "mem.h" #include "x86.h" -#include "386.h" +#include "x86_flags.h" #include "386_common.h" #include "cpu.h" #include "config.h" @@ -32,8 +32,6 @@ int intgatesize; void taskswitch286(uint16_t seg, uint16_t *segdat, int is32); void taskswitch386(uint16_t seg, uint16_t *segdat); -int output; - /*NOT PRESENT is INT 0B GPF is INT 0D*/ @@ -60,8 +58,6 @@ void x86abort(const char *format, ...) exit(-1); } -uint8_t opcode2; - static void seg_reset(x86seg *s) { s->access = (0 << 5) | 2; @@ -129,7 +125,6 @@ void x86_doabrt(int x86_abrt) cpu_state.flags &= ~I_FLAG; cpu_state.flags &= ~T_FLAG; - oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); return; @@ -163,8 +158,6 @@ void x86_doabrt(int x86_abrt) SP-=4; } } -// ingpf = 0; -// abrt = gpf = 1; } void x86gpf(char *s, uint16_t error) { @@ -343,7 +336,7 @@ int loadseg(uint16_t seg, x86seg *s) { if (addr>=ldt.limit) { - pclog("Bigger than LDT limit %04X %04X %02X %02X %02X\n",seg,ldt.limit, opcode, opcode2, 0/*rmdat*/); + pclog("Bigger than LDT limit %04X %04X %02X\n",seg,ldt.limit, 0/*rmdat*/); // dumppic(); // dumpregs(); // exit(-1); @@ -548,7 +541,7 @@ void loadcs(uint16_t seg) if ((seg&3)>CPL) { x86gpf(NULL,seg&~3); - pclog("loadcs RPL > CPL %04X %04X %i %02X\n",segdat[2],seg,CPL,opcode); + pclog("loadcs RPL > CPL %04X %04X %i\n",segdat[2],seg,CPL); return; } if (CPL != DPL) @@ -592,7 +585,7 @@ void loadcs(uint16_t seg) switch (segdat[2]&0xF00) { default: - pclog("Bad CS %02X %02X %i special descriptor %03X %04X\n",opcode,0/*rmdat*/,optype,segdat[2]&0xF00,seg); + pclog("Bad CS %02X %i special descriptor %03X %04X\n",0/*rmdat*/,optype,segdat[2]&0xF00,seg); x86gpf(NULL,seg&~3); return; } @@ -615,7 +608,7 @@ void loadcs(uint16_t seg) } } -void loadcsjmp(uint16_t seg, uint32_t oxpc) +void loadcsjmp(uint16_t seg, uint32_t old_pc) { uint16_t segdat[4]; uint32_t addr; @@ -825,7 +818,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) case 0x100: /*286 Task gate*/ case 0x900: /*386 Task gate*/ // pclog("Task gate\n"); - cpu_state.pc=oxpc; + cpu_state.pc = old_pc; optype=JMP; cpl_override=1; taskswitch286(seg,segdat,segdat[2]&0x800); @@ -837,7 +830,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) return; default: - pclog("Bad JMP CS %02X %02X %i special descriptor %03X %04X\n",opcode,0/*rmdat*/,optype,segdat[2]&0xF00,seg); + pclog("Bad JMP CS %02X %i special descriptor %03X %04X\n",0/*rmdat*/,optype,segdat[2]&0xF00,seg); x86gpf(NULL,0); return; // dumpregs(); @@ -931,7 +924,7 @@ uint32_t POPL() return templ; } -void loadcscall(uint16_t seg) +void loadcscall(uint16_t seg, uint32_t old_pc) { uint16_t seg2; uint16_t segdat[4],segdat2[4],newss; @@ -1337,7 +1330,7 @@ void loadcscall(uint16_t seg) case 0x100: /*286 Task gate*/ case 0x900: /*386 Task gate*/ // pclog("Task gate\n"); - cpu_state.pc=oxpc; + cpu_state.pc = old_pc; cpl_override=1; taskswitch286(seg,segdat,segdat[2]&0x800); cpl_override=0; @@ -2070,7 +2063,6 @@ void pmodeiret(int is32) x86gpf(NULL,0); return; } - oxpc=cpu_state.pc; if (is32) { newpc=POPL(); @@ -2128,7 +2120,6 @@ void pmodeiret(int is32) cpl_override=0; return; } - oxpc=cpu_state.pc; flagmask=0xFFFF; if (CPL) flagmask&=~0x3000; if (IOPL Date: Thu, 7 Feb 2019 21:53:44 +0000 Subject: [PATCH 136/181] Second CPU sanitising pass. --- src/386.c | 73 ++----------------------------------------- src/386_common.h | 14 ++------- src/386_dynarec.c | 36 +-------------------- src/386_dynarec_ops.c | 2 -- src/808x.c | 6 +--- src/cpu.c | 2 ++ src/ibm.h | 4 --- src/pc.c | 1 - src/x86.h | 4 +++ src/x86_ops_rep.h | 2 -- 10 files changed, 13 insertions(+), 131 deletions(-) diff --git a/src/386.c b/src/386.c index 4568199..8b81393 100644 --- a/src/386.c +++ b/src/386.c @@ -12,53 +12,25 @@ #include "nmi.h" #include "386_common.h" +#include "codegen.h" +#undef CPU_BLOCK_END #define CPU_BLOCK_END() -extern int codegen_flags_changed; - -extern int nmi_enable; - uint32_t use32; int stack32; int optype; -uint32_t oldpc2; - int trap; - - -extern int cpl_override; - -int has_fpu; -extern int fpucount; -uint16_t ea_rseg; - -int is486; -int cgate32; - - - -uint8_t romext[32768]; -uint8_t *ram,*rom; - uint32_t rmdat; -uint32_t backupregs[16]; -extern int oddeven; -int inttype; - - -uint32_t oldecx; - uint32_t *eal_r, *eal_w; static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; if (cpu_rm == 4) { uint8_t sib = rmdat >> 8; @@ -85,7 +57,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) else if ((sib & 6) == 4 && !cpu_state.ssegs) { easeg = ss; - ea_rseg = SS; cpu_state.ea_seg = &cpu_state.seg_ss; } if (((sib >> 3) & 7) != 4) @@ -99,7 +70,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) if (cpu_rm == 5 && !cpu_state.ssegs) { easeg = ss; - ea_rseg = SS; cpu_state.ea_seg = &cpu_state.seg_ss; } if (cpu_mod == 1) @@ -131,8 +101,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; - if (!cpu_mod && cpu_rm == 6) + if (!cpu_mod && cpu_rm == 6) { cpu_state.eaaddr = getword(); } @@ -154,7 +123,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat) if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) { easeg = ss; - ea_rseg = SS; cpu_state.ea_seg = &cpu_state.seg_ss; } cpu_state.eaaddr &= 0xFFFF; @@ -178,19 +146,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) #define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 #define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++ #define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 -extern int xout; -int oldi; - -uint32_t testr[9]; -extern int dontprint; - -#undef NOTRM -#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ - { \ - x86_int(6); \ - return 0; \ - } #define OP_TABLE(name) ops_ ## name @@ -199,13 +155,6 @@ extern int dontprint; #include "x86_ops.h" -#undef NOTRM -#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ - { \ - x86_int(6); \ - break; \ - } - void exec386(int cycs) { uint8_t temp; @@ -226,16 +175,9 @@ void exec386(int cycs) // pclog("%i %02X\n", ins, ram[8]); while (cycdiff < cycle_period) { - /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX; - testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/ -/* testr[8]=flags;*/ -// oldpc2=oldpc; - cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; -dontprint=0; - cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; @@ -262,15 +204,6 @@ dontprint=0; flags_rebuild(); // pclog("Abort\n"); // if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt); -/* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc); - if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc); - if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc); - if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc); - if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc); - if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc); - if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc); - if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/ -/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/ tempi = cpu_state.abrt; cpu_state.abrt = 0; x86_doabrt(tempi); diff --git a/src/386_common.h b/src/386_common.h index cf12239..e49bdda 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -1,14 +1,9 @@ -extern uint16_t ea_rseg; - -#undef readmemb -#undef writememb - - #define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) +#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) +#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v - #define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v #define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v #define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v @@ -183,7 +178,6 @@ static inline uint16_t geteaw() { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; -// cycles-=3; if (eal_r) return *(uint16_t *)eal_r; return readmemw(easeg,cpu_state.eaaddr); @@ -193,7 +187,6 @@ static inline uint32_t geteal() { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].l; -// cycles-=3; if (eal_r) return *eal_r; return readmeml(easeg,cpu_state.eaaddr); @@ -237,6 +230,3 @@ static inline void seteaq(uint64_t v) #define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 #define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++ #define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 - - -void x86_int(int num); diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 43388fc..3f9f3f8 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -31,37 +31,15 @@ int cpu_block_end = 0; int nmi_enable = 1; -uint32_t oldpc2; - -int trap; - - - int cpl_override=0; -int has_fpu; int fpucount=0; -uint16_t ea_rseg; -int is486; -int cgate32; - - -uint8_t romext[32768]; -uint8_t *ram,*rom; - -uint32_t backupregs[16]; -int oddeven=0; -int inttype; - - -uint32_t oldecx; static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; if (cpu_rm == 4) { uint8_t sib = rmdat >> 8; @@ -88,7 +66,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) else if ((sib & 6) == 4 && !cpu_state.ssegs) { easeg = ss; - ea_rseg = SS; cpu_state.ea_seg = &cpu_state.seg_ss; } if (((sib >> 3) & 7) != 4) @@ -102,7 +79,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) if (cpu_rm == 5 && !cpu_state.ssegs) { easeg = ss; - ea_rseg = SS; cpu_state.ea_seg = &cpu_state.seg_ss; } if (cpu_mod == 1) @@ -134,8 +110,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; - if (!cpu_mod && cpu_rm == 6) + if (!cpu_mod && cpu_rm == 6) { cpu_state.eaaddr = getword(); } @@ -157,7 +132,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat) if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) { easeg = ss; - ea_rseg = SS; cpu_state.ea_seg = &cpu_state.seg_ss; } cpu_state.eaaddr &= 0xFFFF; @@ -423,9 +397,6 @@ int checkio(int port) return d&(1<<(port&7)); } -int xout=0; - - #define divexcp() { \ pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \ x86_int(0); \ @@ -482,11 +453,6 @@ void cpu_386_flags_rebuild() flags_rebuild(); } -int oldi; - -uint32_t testr[9]; -int dontprint=0; - #define OP_TABLE(name) ops_ ## name #define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index 1b77f71..249909f 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -18,7 +18,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { uint32_t addr = easeg + cpu_state.eaaddr; @@ -33,7 +32,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { uint32_t addr = easeg + cpu_state.eaaddr; diff --git a/src/808x.c b/src/808x.c index fa83679..f53b3df 100644 --- a/src/808x.c +++ b/src/808x.c @@ -40,8 +40,6 @@ void FETCHCOMPLETE(); #define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) -#undef readmemb -#undef readmemw uint8_t readmemb(uint32_t a) { if (a!=(cs+cpu_state.pc)) memcycs+=4; @@ -479,8 +477,6 @@ void makeznptable() } int timetolive=0; -extern uint32_t oldpc2; - int indump = 0; void dumpregs() @@ -568,7 +564,7 @@ void dumpregs() else printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,cpu_state.flags); - printf("%04X %04X\n",cpu_state.oldpc, oldpc2); + printf("%04X\n",cpu_state.oldpc); printf("%i ins\n",ins); if (is386) printf("In %s mode\n",(msw&1)?((cpu_state.eflags&VM_FLAG)?"V86":"protected"):"real"); diff --git a/src/cpu.c b/src/cpu.c index accff09..29d4da2 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -102,6 +102,8 @@ int is386; uint64_t tsc = 0; +int is486; + int timing_rr; int timing_mr, timing_mrl; int timing_rm, timing_rml; diff --git a/src/ibm.h b/src/ibm.h index 9b3a07a..7978dc2 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -32,10 +32,6 @@ int writelnext; extern int mmu_perm; -#define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a))) -#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) - uint8_t readmembl(uint32_t addr); void writemembl(uint32_t addr, uint8_t val); uint16_t readmemwl(uint32_t addr); diff --git a/src/pc.c b/src/pc.c index d574087..f770211 100644 --- a/src/pc.c +++ b/src/pc.c @@ -913,7 +913,6 @@ void saveconfig(char *fn) config_set_int(CFG_MACHINE, NULL, "video_speed", video_speed); config_set_string(CFG_MACHINE, NULL, "sndcard", sound_card_get_internal_name(sound_card_current)); config_set_int(CFG_MACHINE, NULL, "cpu_speed", cpuspeed); - config_set_int(CFG_MACHINE, NULL, "has_fpu", hasfpu); config_set_string(CFG_MACHINE, NULL, "disc_a", discfns[0]); config_set_string(CFG_MACHINE, NULL, "disc_b", discfns[1]); config_set_string(CFG_MACHINE, NULL, "hdd_controller", hdd_controller_name); diff --git a/src/x86.h b/src/x86.h index 5f0be4d..a656124 100644 --- a/src/x86.h +++ b/src/x86.h @@ -7,6 +7,8 @@ extern int oldcpl; extern int nmi_enable; +extern int trap; + extern int output; extern int timetolive; @@ -88,6 +90,8 @@ void loadcscall(uint16_t seg, uint32_t old_pc); void loadcsjmp(uint16_t seg, uint32_t old_pc); void pmoderetf(int is32, uint16_t off); void pmodeiret(int is32); + +void x86_int(int num); void x86_int_sw(int num); int x86_int_sw_rm(int num); diff --git a/src/x86_ops_rep.h b/src/x86_ops_rep.h index 4adfcb1..d19a8f2 100644 --- a/src/x86_ops_rep.h +++ b/src/x86_ops_rep.h @@ -1,5 +1,3 @@ -extern int trap; - #define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ static int opREP_INSB_ ## size(uint32_t fetchdat) \ { \ From 1b8a1e79af0c253ad41da035ed285f493b0faa9a Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 22:09:59 +0000 Subject: [PATCH 137/181] Move common 386+ functions and variables out of 386.c and 386_dynarec.c and into new 386_common.c. --- src/386.c | 10 -- src/386_common.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++ src/386_dynarec.c | 227 ------------------------------------------- src/Makefile.am | 2 +- 4 files changed, 243 insertions(+), 238 deletions(-) create mode 100644 src/386_common.c diff --git a/src/386.c b/src/386.c index 8b81393..48522c9 100644 --- a/src/386.c +++ b/src/386.c @@ -17,16 +17,6 @@ #undef CPU_BLOCK_END #define CPU_BLOCK_END() -uint32_t use32; -int stack32; -int optype; - -int trap; - -uint32_t rmdat; - -uint32_t *eal_r, *eal_w; - static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; diff --git a/src/386_common.c b/src/386_common.c new file mode 100644 index 0000000..d1c9326 --- /dev/null +++ b/src/386_common.c @@ -0,0 +1,242 @@ +#include "ibm.h" +#include "x86.h" +#include "386_common.h" +#include "x86_flags.h" +#include "codegen.h" + +uint32_t use32; +int stack32; +int optype; + +int trap; + +uint32_t rmdat; + +uint32_t *eal_r, *eal_w; + +int nmi_enable = 1; + +int cpl_override=0; + +int fpucount=0; + +uint16_t cpu_cur_status = 0; + + +void x86_int(int num) +{ + uint32_t addr; +// pclog("x86_int %02x %04x:%04x\n", num, CS,pc); + flags_rebuild(); + cpu_state.pc=cpu_state.oldpc; + if (msw&1) + { + pmodeint(num,0); + } + else + { + addr = (num << 2) + idt.base; + + if ((num << 2) + 3 > idt.limit) + { + if (idt.limit < 35) + { + cpu_state.abrt = 0; + softresetx86(); + cpu_set_edx(); + pclog("Triple fault in real mode - reset\n"); + } + else + x86_int(8); + } + else + { + if (stack32) + { + writememw(ss,ESP-2,cpu_state.flags); + writememw(ss,ESP-4,CS); + writememw(ss,ESP-6,cpu_state.pc); + ESP-=6; + } + else + { + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); + SP-=6; + } + + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; + cpu_state.pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + } + } + cycles-=70; + CPU_BLOCK_END(); +} + +void x86_int_sw(int num) +{ + uint32_t addr; +// pclog("x86_int_sw %02x %04x:%04x\n", num, CS,pc); +// pclog("x86_int\n"); + flags_rebuild(); + cycles -= timing_int; + if (msw&1) + { + pmodeint(num,1); + } + else + { + addr = (num << 2) + idt.base; + + if ((num << 2) + 3 > idt.limit) + { + x86_int(13); + } + else + { + if (stack32) + { + writememw(ss,ESP-2,cpu_state.flags); + writememw(ss,ESP-4,CS); + writememw(ss,ESP-6,cpu_state.pc); + ESP-=6; + } + else + { + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); + SP-=6; + } + + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; + cpu_state.pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + cycles -= timing_int_rm; + } + } + trap = 0; + CPU_BLOCK_END(); +} + +int x86_int_sw_rm(int num) +{ + uint32_t addr; + uint16_t new_pc, new_cs; + + flags_rebuild(); + cycles -= timing_int; + + addr = num << 2; + new_pc = readmemw(0, addr); + new_cs = readmemw(0, addr + 2); + + if (cpu_state.abrt) return 1; + + writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; } + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; } + SP-=6; + + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags &= ~T_FLAG; + cpu_state.pc = new_pc; + loadcs(new_cs); + + cycles -= timing_int_rm; + trap = 0; + CPU_BLOCK_END(); + + return 0; +} + +void x86illegal() +{ +// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); + +// if (output) +// { +// dumpregs(); +// exit(-1); +// } + x86_int(6); +} + +int checkio(int port) +{ + uint16_t t; + uint8_t d; + cpl_override = 1; + t = readmemw(tr.base, 0x66); + cpl_override = 0; +// pclog("CheckIO 1 %08X %04x %02x\n",tr.base, eflags, _cs.access); + if (cpu_state.abrt) return 0; +// pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3)); + if ((t+(port>>3))>tr.limit) return 1; + cpl_override = 1; + d = readmembl(tr.base + t + (port >> 3)); +// d=readmemb(tr.base,t+(port>>3)); + cpl_override = 0; +// pclog("%02X %02X\n",d,d&(1<<(port&7))); + return d&(1<<(port&7)); +} + +#define divexcp() { \ + pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \ + x86_int(0); \ +} + +int divl(uint32_t val) +{ + if (val==0) + { + divexcp(); + return 1; + } + uint64_t num=(((uint64_t)EDX)<<32)|EAX; + uint64_t quo=num/val; + uint32_t rem=num%val; + uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF); + if (quo!=(uint64_t)quo32) + { + divexcp(); + return 1; + } + EDX=rem; + EAX=quo32; + return 0; +} +int idivl(int32_t val) +{ + if (val==0) + { + divexcp(); + return 1; + } + int64_t num=(((uint64_t)EDX)<<32)|EAX; + int64_t quo=num/val; + int32_t rem=num%val; + int32_t quo32=(int32_t)(quo&0xFFFFFFFF); + if (quo!=(int64_t)quo32) + { + divexcp(); + return 1; + } + EDX=rem; + EAX=quo32; + return 0; +} + + +void cpu_386_flags_extract() +{ + flags_extract(); +} +void cpu_386_flags_rebuild() +{ + flags_rebuild(); +} diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3f9f3f8..3044b7c 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -18,22 +18,12 @@ #define CPU_BLOCK_END() cpu_block_end = 1 -uint16_t cpu_cur_status = 0; - -int cpu_reps, cpu_reps_latched; -int cpu_notreps, cpu_notreps_latched; - int inrecomp = 0; int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks; int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched; int cpu_block_end = 0; -int nmi_enable = 1; - -int cpl_override=0; - -int fpucount=0; static inline void fetch_ea_32_long(uint32_t rmdat) @@ -151,148 +141,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat) #include "x86_flags.h" -void x86_int(int num) -{ - uint32_t addr; -// pclog("x86_int %02x %04x:%04x\n", num, CS,pc); - flags_rebuild(); - cpu_state.pc=cpu_state.oldpc; - if (msw&1) - { - pmodeint(num,0); - } - else - { - addr = (num << 2) + idt.base; - - if ((num << 2) + 3 > idt.limit) - { - if (idt.limit < 35) - { - cpu_state.abrt = 0; - softresetx86(); - cpu_set_edx(); - pclog("Triple fault in real mode - reset\n"); - } - else - x86_int(8); - } - else - { - if (stack32) - { - writememw(ss,ESP-2,cpu_state.flags); - writememw(ss,ESP-4,CS); - writememw(ss,ESP-6,cpu_state.pc); - ESP-=6; - } - else - { - writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - } - - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - } - } - cycles-=70; - CPU_BLOCK_END(); -} - -void x86_int_sw(int num) -{ - uint32_t addr; -// pclog("x86_int_sw %02x %04x:%04x\n", num, CS,pc); -// pclog("x86_int\n"); - flags_rebuild(); - cycles -= timing_int; - if (msw&1) - { - pmodeint(num,1); - } - else - { - addr = (num << 2) + idt.base; - - if ((num << 2) + 3 > idt.limit) - { - x86_int(13); - } - else - { - if (stack32) - { - writememw(ss,ESP-2,cpu_state.flags); - writememw(ss,ESP-4,CS); - writememw(ss,ESP-6,cpu_state.pc); - ESP-=6; - } - else - { - writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - } - - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - cycles -= timing_int_rm; - } - } - trap = 0; - CPU_BLOCK_END(); -} - -int x86_int_sw_rm(int num) -{ - uint32_t addr; - uint16_t new_pc, new_cs; - - flags_rebuild(); - cycles -= timing_int; - - addr = num << 2; - new_pc = readmemw(0, addr); - new_cs = readmemw(0, addr + 2); - - if (cpu_state.abrt) return 1; - - writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; } - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; } - SP-=6; - - cpu_state.eflags &= ~VIF_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc = new_pc; - loadcs(new_cs); - - cycles -= timing_int_rm; - trap = 0; - CPU_BLOCK_END(); - - return 0; -} - -void x86illegal() -{ -// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); - -// if (output) -// { -// dumpregs(); -// exit(-1); -// } - x86_int(6); -} /*Prefetch emulation is a fairly simplistic model: - All instruction bytes must be fetched before it starts. @@ -378,81 +226,6 @@ static void prefetch_flush() #define PREFETCH_FLUSH() prefetch_flush() -int checkio(int port) -{ - uint16_t t; - uint8_t d; - cpl_override = 1; - t = readmemw(tr.base, 0x66); - cpl_override = 0; -// pclog("CheckIO 1 %08X %04x %02x\n",tr.base, eflags, _cs.access); - if (cpu_state.abrt) return 0; -// pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3)); - if ((t+(port>>3))>tr.limit) return 1; - cpl_override = 1; - d = readmembl(tr.base + t + (port >> 3)); -// d=readmemb(tr.base,t+(port>>3)); - cpl_override = 0; -// pclog("%02X %02X\n",d,d&(1<<(port&7))); - return d&(1<<(port&7)); -} - -#define divexcp() { \ - pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \ - x86_int(0); \ -} - -int divl(uint32_t val) -{ - if (val==0) - { - divexcp(); - return 1; - } - uint64_t num=(((uint64_t)EDX)<<32)|EAX; - uint64_t quo=num/val; - uint32_t rem=num%val; - uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF); - if (quo!=(uint64_t)quo32) - { - divexcp(); - return 1; - } - EDX=rem; - EAX=quo32; - return 0; -} -int idivl(int32_t val) -{ - if (val==0) - { - divexcp(); - return 1; - } - int64_t num=(((uint64_t)EDX)<<32)|EAX; - int64_t quo=num/val; - int32_t rem=num%val; - int32_t quo32=(int32_t)(quo&0xFFFFFFFF); - if (quo!=(int64_t)quo32) - { - divexcp(); - return 1; - } - EDX=rem; - EAX=quo32; - return 0; -} - - -void cpu_386_flags_extract() -{ - flags_extract(); -} -void cpu_386_flags_rebuild() -{ - flags_rebuild(); -} - #define OP_TABLE(name) ops_ ## name #define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) diff --git a/src/Makefile.am b/src/Makefile.am index 93f8f32..040b85e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,7 @@ wx-resources.cpp : pc.xrc -wxrc -c pc.xrc -o wx-resources.cpp # PCem -pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ +pcem_SOURCES = 386.c 386_common.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \ codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \ dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ From 5b58b202a1b04638ffb8853ff7c5a5caf026f7ef Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 7 Feb 2019 22:10:34 +0000 Subject: [PATCH 138/181] More CPU sanitisation. --- src/808x.c | 34 +++++++++++----------------------- src/Makefile.am | 10 +++++++++- src/ibm.h | 1 - src/mem.h | 1 - src/pc.c | 4 ---- 5 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/808x.c b/src/808x.c index f53b3df..83d06b6 100644 --- a/src/808x.c +++ b/src/808x.c @@ -29,13 +29,21 @@ uint64_t xt_cpu_multi; int nmi = 0; int nmi_auto_clear = 0; -int nextcyc=0; -int cycdiff; +int oldcpl; + +int tempc; +static int noint=0; + +int output=0; +int timetolive=0; +int ins=0; + int is8086=0; +int nextcyc=0; int memcycs; -int nopageerrors=0; +static int cycdiff; void FETCHCOMPLETE(); #define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) @@ -88,15 +96,6 @@ void writememl(uint32_t s, uint32_t a, uint32_t v) } -int oldcpl; - -int tempc; -uint16_t pc2,pc3; -static int noint=0; - -int output=0; - -int ins=0; //#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a)) int fetchcycles=0,memcycs,fetchclocks; @@ -475,7 +474,6 @@ void makeznptable() // makemod1table(); } -int timetolive=0; int indump = 0; @@ -492,7 +490,6 @@ void dumpregs() // savenvr(); // return; chdir(logs_path); - nopageerrors=1; /* f=fopen("rram3.dmp","wb"); for (c=0;c<0x8000000;c++) putc(readmemb(c+0x10000000),f); fclose(f);*/ @@ -599,12 +596,10 @@ void dumpregs() indump = 0; } -int resets = 0; int x86_was_reset = 0; void resetx86() { pclog("x86 reset\n"); - resets++; ins = 0; use32=0; cpu_cur_status = 0; @@ -1109,11 +1104,8 @@ void rep(int fv) static int inhlt=0; -int firstrepcycle; static int skipnextprint=0; -int instime=0; -//#if 0 void execx86(int cycs) { uint8_t temp,temp2; @@ -1133,10 +1125,6 @@ void execx86(int cycs) { uint8_t opcode; -// old83=old82; -// old82=old8; -// if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; } -// if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime); cycdiff=cycles; current_diff = 0; cycles-=nextcyc; diff --git a/src/Makefile.am b/src/Makefile.am index 040b85e..fdd7857 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -124,10 +124,18 @@ pcem_LDADD += wx.res endif if !HAS_OFF64T -pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell +#pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell endif if RELEASE_BUILD pcem_CFLAGS += -DRELEASE_BUILD pcem_CXXFLAGS += -DRELEASE_BUILD endif + +pcem_CFLAGS += -mtune=cortex-a53 +pcem_CXXFLAGS += -mtune=cortex-a53 +#pcem_LDFLAGS = -flto -O3 -mtune=cortex-a15 + +# pcem_CFLAGS += -fprofile-use +# pcem_CXXFLAGS += -fprofile-use +# pcem_LDFLAGS = -fprofile-use diff --git a/src/ibm.h b/src/ibm.h index 7978dc2..74498ef 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -209,7 +209,6 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128); uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; extern int ins,output; -extern int cycdiff; x86seg gdt,ldt,idt,tr; x86seg _oldds; diff --git a/src/mem.h b/src/mem.h index 3bffffd..e55aece 100644 --- a/src/mem.h +++ b/src/mem.h @@ -35,7 +35,6 @@ extern uint8_t *ram,*rom; extern uint8_t romext[32768]; extern int readlnum,writelnum; extern int memspeed[11]; -extern int nopageerrors; extern uint32_t biosmask; void mem_mapping_add(mem_mapping_t *mapping, diff --git a/src/pc.c b/src/pc.c index f770211..49d58ee 100644 --- a/src/pc.c +++ b/src/pc.c @@ -561,8 +561,6 @@ void runpc() cpu_recomp_evicted_latched = cpu_recomp_evicted; cpu_recomp_reuse_latched = cpu_recomp_reuse; cpu_recomp_removed_latched = cpu_recomp_removed; - cpu_reps_latched = cpu_reps; - cpu_notreps_latched = cpu_notreps; cpu_recomp_blocks = 0; cpu_state.cpu_recomp_ins = 0; @@ -572,8 +570,6 @@ void runpc() cpu_recomp_evicted = 0; cpu_recomp_reuse = 0; cpu_recomp_removed = 0; - cpu_reps = 0; - cpu_notreps = 0; updatestatus=1; readlnum=writelnum=0; From 255495265828f4af72eb2330872327ab7c000c22 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 8 Feb 2019 19:36:30 +0000 Subject: [PATCH 139/181] Remove unused checkio_perm() macro. --- src/386_common.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/386_common.h b/src/386_common.h index e49bdda..9f092bf 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -21,17 +21,6 @@ int checkio(int port); } \ } -#define checkio_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \ - { \ - int tempi = checkio(port); \ - if (cpu_state.abrt) break; \ - if (tempi) \ - { \ - x86gpf(NULL,0); \ - break; \ - } \ - } - #define SEG_CHECK_READ(seg) \ do \ { \ From 03b5a44aca8812c0b26948064510d3fa6bffc0d2 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 8 Feb 2019 21:17:56 +0000 Subject: [PATCH 140/181] More CPU sanitisation. --- src/386_common.c | 7 ++ src/808x.c | 41 ++++----- src/cpu.c | 4 +- src/cpu.h | 2 + src/gameport.c | 1 + src/ibm.h | 214 +------------------------------------------- src/mcr.c | 1 + src/mem.h | 2 + src/nvr.c | 1 + src/pc.c | 1 - src/sound_opl.c | 1 + src/sound_pas16.c | 1 + src/x86.h | 219 ++++++++++++++++++++++++++++++++++++++++++++-- src/x86seg.c | 5 -- 14 files changed, 248 insertions(+), 252 deletions(-) diff --git a/src/386_common.c b/src/386_common.c index d1c9326..df19e14 100644 --- a/src/386_common.c +++ b/src/386_common.c @@ -4,6 +4,11 @@ #include "x86_flags.h" #include "codegen.h" +x86seg gdt, ldt, idt, tr; + +uint32_t cr2, cr3, cr4; +uint32_t dr[8]; + uint32_t use32; int stack32; int optype; @@ -22,6 +27,8 @@ int fpucount=0; uint16_t cpu_cur_status = 0; +uint32_t pccache; +uint8_t *pccache2; void x86_int(int num) { diff --git a/src/808x.c b/src/808x.c index 83d06b6..cba4273 100644 --- a/src/808x.c +++ b/src/808x.c @@ -40,28 +40,31 @@ int ins=0; int is8086=0; -int nextcyc=0; -int memcycs; +static uint32_t oldds; +uint32_t oldss; + +static int nextcyc=0; +static int memcycs; static int cycdiff; -void FETCHCOMPLETE(); +static void FETCHCOMPLETE(); #define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) -uint8_t readmemb(uint32_t a) +static uint8_t readmemb(uint32_t a) { if (a!=(cs+cpu_state.pc)) memcycs+=4; if (readlookup2[(a)>>12]==-1) return readmembl(a); else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); } -uint8_t readmembf(uint32_t a) +static uint8_t readmembf(uint32_t a) { if (readlookup2[(a)>>12]==-1) return readmembl(a); else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); } -uint16_t readmemw(uint32_t s, uint16_t a) +static uint16_t readmemw(uint32_t s, uint16_t a) { if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086); if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s+a); @@ -77,32 +80,28 @@ void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE(); memcycs+=4; } cpu_rm=rmdat&7; \ if (cpu_mod!=3) fetcheal(); } -void writememb(uint32_t a, uint8_t v) +static void writememb(uint32_t a, uint8_t v) { memcycs+=4; if (writelookup2[(a)>>12]==-1) writemembl(a,v); else *(uint8_t *)(writelookup2[a >> 12] + a) = v; } -void writememw(uint32_t s, uint32_t a, uint16_t v) +static void writememw(uint32_t s, uint32_t a, uint16_t v) { memcycs+=(8>>is8086); if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s+a,v); else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v; } -void writememl(uint32_t s, uint32_t a, uint32_t v) -{ - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s+a,v); - else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v; -} //#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a)) -int fetchcycles=0,memcycs,fetchclocks; +static int fetchcycles=0,fetchclocks; + +static uint8_t prefetchqueue[6]; +static uint16_t prefetchpc; +static int prefetchw=0; -uint8_t prefetchqueue[6]; -uint16_t prefetchpc; -int prefetchw=0; static inline uint8_t FETCH() { uint8_t temp; @@ -187,7 +186,7 @@ static inline void FETCHADD(int c) // if (fetchcycles>24) fetchcycles=24; } -void FETCHCOMPLETE() +static void FETCHCOMPLETE() { // pclog("Fetchcomplete %i %i %i\n",fetchcycles&3,fetchcycles,prefetchw); if (!(fetchcycles&3)) return; @@ -604,7 +603,6 @@ void resetx86() use32=0; cpu_cur_status = 0; stack32=0; - cpu_hasCX8 = 0; // i86_Reset(); // cs=0xFFFF0; msw=0; @@ -665,7 +663,6 @@ void softresetx86() cr4 = 0; cpu_state.eflags=0; cgate32=0; - cpu_hasCX8 = 0; if (AT) { loadcs(0xF000); @@ -845,7 +842,7 @@ int current_diff = 0; between the two frequencies, use fixed point arithmetic when updating TSC.*/ static uint64_t tsc_frac = 0; -void clockhardware() +static void clockhardware() { int diff = cycdiff - cycles - current_diff; @@ -864,7 +861,7 @@ static int takeint = 0; int firstrepcycle=1; -void rep(int fv) +static void rep(int fv) { uint8_t temp; int c=CX; diff --git a/src/cpu.c b/src/cpu.c index 29d4da2..3963646 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -99,11 +99,11 @@ int cpu_waitstates; int cpu_cache_int_enabled, cpu_cache_ext_enabled; int is386; +int is486; +int CPUID; uint64_t tsc = 0; -int is486; - int timing_rr; int timing_mr, timing_mrl; int timing_rm, timing_rml; diff --git a/src/cpu.h b/src/cpu.h index 02a1340..ba22f12 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -143,6 +143,8 @@ void cyrix_write(uint16_t addr, uint8_t val, void *priv); uint8_t cyrix_read(uint16_t addr, void *priv); extern int is8086; +extern int is486; +extern int CPUID; void cpu_CPUID(); void cpu_RDMSR(); diff --git a/src/gameport.c b/src/gameport.c index fbf142a..d8eb6c4 100644 --- a/src/gameport.c +++ b/src/gameport.c @@ -4,6 +4,7 @@ #include "io.h" #include "plat-joystick.h" #include "timer.h" +#include "x86.h" #include "gameport.h" #include "joystick_ch_flightstick_pro.h" diff --git a/src/ibm.h b/src/ibm.h index 74498ef..ca63e29 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -63,221 +63,9 @@ extern int readlnum,writelnum; /*Processor*/ -#define EAX cpu_state.regs[0].l -#define ECX cpu_state.regs[1].l -#define EDX cpu_state.regs[2].l -#define EBX cpu_state.regs[3].l -#define ESP cpu_state.regs[4].l -#define EBP cpu_state.regs[5].l -#define ESI cpu_state.regs[6].l -#define EDI cpu_state.regs[7].l -#define AX cpu_state.regs[0].w -#define CX cpu_state.regs[1].w -#define DX cpu_state.regs[2].w -#define BX cpu_state.regs[3].w -#define SP cpu_state.regs[4].w -#define BP cpu_state.regs[5].w -#define SI cpu_state.regs[6].w -#define DI cpu_state.regs[7].w -#define AL cpu_state.regs[0].b.l -#define AH cpu_state.regs[0].b.h -#define CL cpu_state.regs[1].b.l -#define CH cpu_state.regs[1].b.h -#define DL cpu_state.regs[2].b.l -#define DH cpu_state.regs[2].b.h -#define BL cpu_state.regs[3].b.l -#define BH cpu_state.regs[3].b.h +extern int ins, output, timetolive; -typedef union -{ - uint32_t l; - uint16_t w; - struct - { - uint8_t l,h; - } b; -} x86reg; - -typedef struct -{ - uint32_t base; - uint32_t limit; - uint8_t access; - uint16_t seg; - uint32_t limit_low, limit_high; - int checked; /*Non-zero if selector is known to be valid*/ -} x86seg; - -typedef union MMX_REG -{ - uint64_t q; - int64_t sq; - uint32_t l[2]; - int32_t sl[2]; - uint16_t w[4]; - int16_t sw[4]; - uint8_t b[8]; - int8_t sb[8]; - float f[2]; -} MMX_REG; - -struct -{ - x86reg regs[8]; - - uint8_t tag[8]; - - x86seg *ea_seg; - uint32_t eaaddr; - - int flags_op; - uint32_t flags_res; - uint32_t flags_op1, flags_op2; - - uint32_t pc; - uint32_t oldpc; - uint32_t op32; - - int TOP; - - union - { - struct - { - int8_t rm, mod, reg; - } rm_mod_reg; - uint32_t rm_mod_reg_data; - } rm_data; - - int8_t ssegs; - int8_t ismmx; - int8_t abrt; - - int _cycles; - int cpu_recomp_ins; - - uint16_t npxs, npxc; - - double ST[8]; - - uint16_t MM_w4[8]; - - MMX_REG MM[8]; - - uint32_t old_fp_control, new_fp_control; -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ - uint16_t old_fp_control2, new_fp_control2; -#endif -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__ - uint32_t trunc_fp_control; -#endif - x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs; - - union - { - uint32_t l; - uint16_t w; - } CR0; - - uint16_t flags, eflags; -} cpu_state; - -#define cycles cpu_state._cycles - -extern uint16_t cpu_cur_status; - -/*The flags below must match in both cpu_cur_status and block->status for a block - to be valid*/ -#define CPU_STATUS_USE32 (1 << 0) -#define CPU_STATUS_STACK32 (1 << 1) -#define CPU_STATUS_PMODE (1 << 2) -#define CPU_STATUS_V86 (1 << 3) -#define CPU_STATUS_FLAGS 0xff - -/*If the flags below are set in cpu_cur_status, they must be set in block->status. - Otherwise they are ignored*/ -#define CPU_STATUS_NOTFLATDS (1 << 8) -#define CPU_STATUS_NOTFLATSS (1 << 9) -#define CPU_STATUS_MASK 0xff00 - -#define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; - -COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128); - -#define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128) - -uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; - -extern int ins,output; - -x86seg gdt,ldt,idt,tr; -x86seg _oldds; - -uint32_t pccache; -uint8_t *pccache2; -/*Segments - - _cs,_ds,_es,_ss are the segment structures - CS,DS,ES,SS is the 16-bit data - cs,ds,es,ss are defines to the bases*/ -#define CS cpu_state.seg_cs.seg -#define DS cpu_state.seg_ds.seg -#define ES cpu_state.seg_es.seg -#define SS cpu_state.seg_ss.seg -#define FS cpu_state.seg_fs.seg -#define GS cpu_state.seg_gs.seg -#define cs cpu_state.seg_cs.base -#define ds cpu_state.seg_ds.base -#define es cpu_state.seg_es.base -#define ss cpu_state.seg_ss.base -//#define seg_fs _fs.base -#define gs cpu_state.seg_gs.base - -#define CPL ((cpu_state.seg_cs.access>>5)&3) - -int loadseg(uint16_t seg, x86seg *s); -void loadcs(uint16_t seg); - -#define cr0 cpu_state.CR0.l -#define msw cpu_state.CR0.w - -uint32_t cr2, cr3, cr4; -uint32_t dr[8]; - -#define C_FLAG 0x0001 -#define P_FLAG 0x0004 -#define A_FLAG 0x0010 -#define Z_FLAG 0x0040 -#define N_FLAG 0x0080 -#define T_FLAG 0x0100 -#define I_FLAG 0x0200 -#define D_FLAG 0x0400 -#define V_FLAG 0x0800 -#define NT_FLAG 0x4000 -#define VM_FLAG 0x0002 /*In EFLAGS*/ -#define VIF_FLAG 0x0008 /*In EFLAGS*/ -#define VIP_FLAG 0x0010 /*In EFLAGS*/ - -#define WP_FLAG 0x10000 /*In CR0*/ - -#define CR4_VME (1 << 0) -#define CR4_PVI (1 << 1) -#define CR4_PSE (1 << 4) - -#define IOPL ((cpu_state.flags >> 12) & 3) - -#define IOPLp ((!(msw&1)) || (CPL<=IOPL)) -//#define IOPLp 1 - -//#define IOPLV86 ((!(msw&1)) || (CPL<=IOPL)) extern int cycles_lost; -extern int is486; -extern int insc; -extern int fpucount; -extern float mips,flops; -extern int cgate16; -extern int CPUID; - -extern int cpl_override; /*Timer*/ typedef struct PIT_nr diff --git a/src/mcr.c b/src/mcr.c index 81293c2..6c7d746 100644 --- a/src/mcr.c +++ b/src/mcr.c @@ -2,6 +2,7 @@ This chip was used as part of many 386 chipsets It controls memory addressing and shadowing*/ #include "ibm.h" +#include "x86.h" int nextreg6; uint8_t mcr22; diff --git a/src/mem.h b/src/mem.h index e55aece..79d0da4 100644 --- a/src/mem.h +++ b/src/mem.h @@ -1,6 +1,8 @@ #ifndef _MEM_H_ #define _MEM_H_ +#include "x86.h" + typedef struct mem_mapping_t { struct mem_mapping_t *prev, *next; diff --git a/src/nvr.c b/src/nvr.c index edabac9..fe89377 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -11,6 +11,7 @@ #include "model.h" #include "nmi.h" #include "t1000.h" +#include "x86.h" int oldromset; int nvrmask=63; diff --git a/src/pc.c b/src/pc.c index 49d58ee..a259bc9 100644 --- a/src/pc.c +++ b/src/pc.c @@ -66,7 +66,6 @@ int start_in_fullscreen = 0; static int override_drive_a = 0, override_drive_b = 0; -int CPUID; int vid_resize, vid_api; int cycles_lost = 0; diff --git a/src/sound_opl.c b/src/sound_opl.c index 33f6fd9..368a1d8 100644 --- a/src/sound_opl.c +++ b/src/sound_opl.c @@ -5,6 +5,7 @@ #include "sound.h" #include "sound_opl.h" #include "sound_dbopl.h" +#include "x86.h" /*Interfaces between PCem and the actual OPL emulator*/ diff --git a/src/sound_pas16.c b/src/sound_pas16.c index 7f44fe7..d55b921 100644 --- a/src/sound_pas16.c +++ b/src/sound_pas16.c @@ -12,6 +12,7 @@ #include "sound_pas16.h" #include "sound_sb_dsp.h" #include "timer.h" +#include "x86.h" /* Original PAS uses 2 x OPL2 diff --git a/src/x86.h b/src/x86.h index a656124..a9365c0 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,32 +1,226 @@ +#ifndef _X86_H_ +#define _X86_H_ + +#define EAX cpu_state.regs[0].l +#define ECX cpu_state.regs[1].l +#define EDX cpu_state.regs[2].l +#define EBX cpu_state.regs[3].l +#define ESP cpu_state.regs[4].l +#define EBP cpu_state.regs[5].l +#define ESI cpu_state.regs[6].l +#define EDI cpu_state.regs[7].l +#define AX cpu_state.regs[0].w +#define CX cpu_state.regs[1].w +#define DX cpu_state.regs[2].w +#define BX cpu_state.regs[3].w +#define SP cpu_state.regs[4].w +#define BP cpu_state.regs[5].w +#define SI cpu_state.regs[6].w +#define DI cpu_state.regs[7].w +#define AL cpu_state.regs[0].b.l +#define AH cpu_state.regs[0].b.h +#define CL cpu_state.regs[1].b.l +#define CH cpu_state.regs[1].b.h +#define DL cpu_state.regs[2].b.l +#define DH cpu_state.regs[2].b.h +#define BL cpu_state.regs[3].b.l +#define BH cpu_state.regs[3].b.h + +typedef union +{ + uint32_t l; + uint16_t w; + struct + { + uint8_t l,h; + } b; +} x86reg; + +typedef struct +{ + uint32_t base; + uint32_t limit; + uint8_t access; + uint16_t seg; + uint32_t limit_low, limit_high; + int checked; /*Non-zero if selector is known to be valid*/ +} x86seg; + +typedef union MMX_REG +{ + uint64_t q; + int64_t sq; + uint32_t l[2]; + int32_t sl[2]; + uint16_t w[4]; + int16_t sw[4]; + uint8_t b[8]; + int8_t sb[8]; + float f[2]; +} MMX_REG; + +struct +{ + x86reg regs[8]; + + uint8_t tag[8]; + + x86seg *ea_seg; + uint32_t eaaddr; + + int flags_op; + uint32_t flags_res; + uint32_t flags_op1, flags_op2; + + uint32_t pc; + uint32_t oldpc; + uint32_t op32; + + int TOP; + + union + { + struct + { + int8_t rm, mod, reg; + } rm_mod_reg; + uint32_t rm_mod_reg_data; + } rm_data; + + int8_t ssegs; + int8_t ismmx; + int8_t abrt; + + int _cycles; + int cpu_recomp_ins; + + uint16_t npxs, npxc; + + double ST[8]; + + uint16_t MM_w4[8]; + + MMX_REG MM[8]; + + uint32_t old_fp_control, new_fp_control; +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ + uint16_t old_fp_control2, new_fp_control2; +#endif +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__ + uint32_t trunc_fp_control; +#endif + x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs; + + union + { + uint32_t l; + uint16_t w; + } CR0; + + uint16_t flags, eflags; +} cpu_state; + +#define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128) + +#define cycles cpu_state._cycles + +#define cr0 cpu_state.CR0.l +#define msw cpu_state.CR0.w + +/*Segments - + _cs,_ds,_es,_ss are the segment structures + CS,DS,ES,SS is the 16-bit data + cs,ds,es,ss are defines to the bases*/ +#define CS cpu_state.seg_cs.seg +#define DS cpu_state.seg_ds.seg +#define ES cpu_state.seg_es.seg +#define SS cpu_state.seg_ss.seg +#define FS cpu_state.seg_fs.seg +#define GS cpu_state.seg_gs.seg +#define cs cpu_state.seg_cs.base +#define ds cpu_state.seg_ds.base +#define es cpu_state.seg_es.base +#define ss cpu_state.seg_ss.base +//#define seg_fs _fs.base +#define gs cpu_state.seg_gs.base + +#define CPL ((cpu_state.seg_cs.access>>5)&3) + +#define C_FLAG 0x0001 +#define P_FLAG 0x0004 +#define A_FLAG 0x0010 +#define Z_FLAG 0x0040 +#define N_FLAG 0x0080 +#define T_FLAG 0x0100 +#define I_FLAG 0x0200 +#define D_FLAG 0x0400 +#define V_FLAG 0x0800 +#define NT_FLAG 0x4000 +#define VM_FLAG 0x0002 /*In EFLAGS*/ +#define VIF_FLAG 0x0008 /*In EFLAGS*/ +#define VIP_FLAG 0x0010 /*In EFLAGS*/ + +#define WP_FLAG 0x10000 /*In CR0*/ + +#define CR4_VME (1 << 0) +#define CR4_PVI (1 << 1) +#define CR4_PSE (1 << 4) + +#define IOPL ((cpu_state.flags >> 12) & 3) + +#define IOPLp ((!(msw&1)) || (CPL<=IOPL)) + +extern x86seg gdt, ldt, idt, tr; + +extern uint32_t cr2, cr3, cr4; +extern uint32_t dr[8]; + + +extern uint16_t cpu_cur_status; + +/*The flags below must match in both cpu_cur_status and block->status for a block + to be valid*/ +#define CPU_STATUS_USE32 (1 << 0) +#define CPU_STATUS_STACK32 (1 << 1) +#define CPU_STATUS_PMODE (1 << 2) +#define CPU_STATUS_V86 (1 << 3) +#define CPU_STATUS_FLAGS 0xff + +/*If the flags below are set in cpu_cur_status, they must be set in block->status. + Otherwise they are ignored*/ +#define CPU_STATUS_NOTFLATDS (1 << 8) +#define CPU_STATUS_NOTFLATSS (1 << 9) +#define CPU_STATUS_MASK 0xff00 + + extern uint32_t rmdat; #define fetchdat rmdat extern uint32_t easeg; +extern uint32_t *eal_r, *eal_w; extern int oldcpl; +extern uint32_t oldss; extern int nmi_enable; extern int trap; -extern int output; -extern int timetolive; - -extern uint8_t znptable8[256]; - extern uint32_t use32; extern int stack32; +extern uint8_t znptable8[256]; extern uint16_t *mod1add[2][8]; extern uint32_t *mod1seg[8]; -extern int cgate32; - -extern uint32_t *eal_r, *eal_w; +extern int cgate16, cgate32; +extern int cpl_override; extern int x86_was_reset; - +extern int insc; +extern int fpucount; +extern float mips,flops; #define setznp168 setznp16 @@ -71,6 +265,9 @@ void x86_doabrt(int x86_abrt); extern int codegen_flat_ds; extern int codegen_flat_ss; +extern uint32_t pccache; +extern uint8_t *pccache2; + void x86illegal(); void x86seg_reset(); @@ -86,6 +283,8 @@ void exec386(int cycs); void exec386_dynarec(int cycs); void pmodeint(int num, int soft); +int loadseg(uint16_t seg, x86seg *s); +void loadcs(uint16_t seg); void loadcscall(uint16_t seg, uint32_t old_pc); void loadcsjmp(uint16_t seg, uint32_t old_pc); void pmoderetf(int is32, uint16_t off); @@ -97,3 +296,5 @@ int x86_int_sw_rm(int num); int divl(uint32_t val); int idivl(int32_t val); + +#endif diff --git a/src/x86seg.c b/src/x86seg.c index bed02ad..21a3778 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -1653,11 +1653,6 @@ void pmoderetf(int is32, uint16_t off) } } -void restore_stack() -{ - ss=oldss; cpu_state.seg_ss.limit=oldsslimit; -} - void pmodeint(int num, int soft) { uint16_t segdat[4],segdat2[4],segdat3[4]; From ce4436054d54fadcf5419e77aab6f37a28d417f9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 8 Feb 2019 21:22:53 +0000 Subject: [PATCH 141/181] Replace cpu_has* flags with single cpu_features variable and cpu_has_feature() getter. --- src/codegen_timing_pentium.c | 10 ++-- src/cpu.c | 90 ++++++++++-------------------------- src/cpu.h | 20 +++++--- src/x86_ops_3dnow.h | 2 +- src/x86_ops_misc.h | 4 +- src/x86_ops_mmx.h | 4 +- src/x86_ops_mov_ctrl.h | 8 ++-- src/x86_ops_msr.h | 2 +- 8 files changed, 53 insertions(+), 87 deletions(-) diff --git a/src/codegen_timing_pentium.c b/src/codegen_timing_pentium.c index f21a70f..9690087 100644 --- a/src/codegen_timing_pentium.c +++ b/src/codegen_timing_pentium.c @@ -815,7 +815,7 @@ static inline int COUNT(uint64_t timings, uint64_t deps, int op_32) case CYCLES_RMW: return 3; case CYCLES_BRANCH: - return cpu_hasMMX ? 1 : 2; + return cpu_has_feature(CPU_FEATURE_MMX) ? 1 : 2; } fatal("Illegal COUNT %016llx\n", timings); @@ -949,13 +949,13 @@ void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; return; } - if (cpu_hasMMX && prefix == 0x0f) + if (cpu_has_feature(CPU_FEATURE_MMX) && prefix == 0x0f) { /*On Pentium MMX 0fh prefix is 'free'*/ last_prefix = prefix; return; } - if (cpu_hasMMX && (prefix == 0x66 || prefix == 0x67)) + if (cpu_has_feature(CPU_FEATURE_MMX) && (prefix == 0x66 || prefix == 0x67)) { /*On Pentium MMX 66h and 67h prefixes take 2 clocks*/ decode_delay_offset += 2; @@ -1239,7 +1239,7 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, else has_displacement = 0; - if (!has_displacement && (!cpu_hasMMX || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) + if (!has_displacement && (!cpu_has_feature(CPU_FEATURE_MMX) || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) { int t1 = u_pipe_timings[u_pipe_opcode] & CYCLES_MASK; int t2 = timings[opcode] & CYCLES_MASK; @@ -1292,7 +1292,7 @@ nopair: else has_displacement = 0; - if ((!has_displacement || cpu_hasMMX) && (!cpu_hasMMX || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) + if ((!has_displacement || cpu_has_feature(CPU_FEATURE_MMX)) && (!cpu_has_feature(CPU_FEATURE_MMX) || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) { /*Instruction might pair with next*/ u_pipe_full = 1; diff --git a/src/cpu.c b/src/cpu.c index 3963646..6e45f04 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -7,6 +7,8 @@ #include "pci.h" #include "codegen.h" +uint32_t cpu_features; + static int cpu_turbo_speed, cpu_nonturbo_speed; static int cpu_turbo = 1; @@ -82,12 +84,6 @@ int cpu_multi; int cpu_iscyrix; int cpu_16bitbus; int cpu_busspeed; -int cpu_hasrdtsc; -int cpu_hasMMX, cpu_hasMSR; -int cpu_hasCR4; -int cpu_hasCX8; -int cpu_hasVME; -int cpu_has3DNOW; int cpu_use_dynarec; int cpu_cyrix_alignment; @@ -580,12 +576,6 @@ void cpu_set() if (cpu_s->multi) cpu_busspeed = cpu_s->rspeed / cpu_s->multi; cpu_multi = cpu_s->multi; - cpu_hasrdtsc = 0; - cpu_hasMMX = 0; - cpu_hasMSR = 0; - cpu_hasCR4 = 0; - cpu_hasCX8 = 0; - cpu_has3DNOW = 0; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; has_vlb = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type <= CPU_Cx5x86); @@ -885,8 +875,7 @@ void cpu_set() break; case CPU_iDX4: - cpu_hasCR4 = 1; - cpu_hasVME = 1; + cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; case CPU_i486SX: case CPU_i486DX: @@ -1032,10 +1021,8 @@ void cpu_set() timing_mml = 3; timing_bt = 3-1; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4; msr.fcr = (1 << 8) | (1 << 16); - cpu_hasMMX = cpu_hasMSR = 1; - cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; /*unknown*/ timing_int_rm = 26; @@ -1072,10 +1059,8 @@ void cpu_set() timing_mml = 3; timing_bt = 3-1; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); - cpu_hasMMX = cpu_hasMSR = cpu_has3DNOW = 1; - cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; /*unknown*/ timing_int_rm = 26; @@ -1132,12 +1117,8 @@ void cpu_set() timing_jmp_pm = 3; timing_jmp_pm_gate = 18; timing_misaligned = 3; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 0; - cpu_hasMSR = 1; - cpu_hasCR4 = 1; - cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; codegen_timing_set(&codegen_timing_pentium); break; @@ -1173,12 +1154,8 @@ void cpu_set() timing_jmp_pm = 3; timing_jmp_pm_gate = 18; timing_misaligned = 3; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 1; - cpu_hasMSR = 1; - cpu_hasCR4 = 1; - cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; codegen_timing_set(&codegen_timing_pentium); break; @@ -1214,11 +1191,8 @@ void cpu_set() timing_jmp_pm_gate = 14; timing_misaligned = 2; cpu_cyrix_alignment = 1; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 0; - cpu_hasMSR = 0; - cpu_hasCR4 = 0; codegen_timing_set(&codegen_timing_686); CPUID = 0; /*Disabled on powerup by default*/ break; @@ -1254,11 +1228,8 @@ void cpu_set() timing_jmp_pm_gate = 14; timing_misaligned = 2; cpu_cyrix_alignment = 1; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 0; - cpu_hasMSR = 0; - cpu_hasCR4 = 0; codegen_timing_set(&codegen_timing_686); ccr4 = 0x80; break; @@ -1275,11 +1246,8 @@ void cpu_set() timing_mml = 2; timing_bt = 5-1; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 0; - cpu_hasMSR = 1; - cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; codegen_timing_set(&codegen_timing_686); break; @@ -1328,11 +1296,8 @@ void cpu_set() timing_jmp_pm_gate = 14; timing_misaligned = 2; cpu_cyrix_alignment = 1; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 1; - cpu_hasMSR = 1; - cpu_hasCR4 = 1; cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; codegen_timing_set(&codegen_timing_686); ccr4 = 0x80; @@ -1369,12 +1334,8 @@ void cpu_set() timing_jmp_pm = 3; timing_jmp_pm_gate = 18; timing_misaligned = 3; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 1; - cpu_hasMSR = 1; - cpu_hasCR4 = 1; - cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; codegen_timing_set(&codegen_timing_k6); break; @@ -1413,12 +1374,8 @@ void cpu_set() timing_jmp_pm = 3; timing_jmp_pm_gate = 18; timing_misaligned = 3; - cpu_hasrdtsc = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX | CPU_FEATURE_3DNOW; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_hasMMX = 1; - cpu_hasMSR = 1; - cpu_hasCR4 = 1; - cpu_hasVME = 1; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; codegen_timing_set(&codegen_timing_k6); break; @@ -1525,7 +1482,7 @@ void cpu_CPUID() EAX = 0x540; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_hasCX8) + if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) EDX |= CPUID_MMX; @@ -1556,7 +1513,7 @@ void cpu_CPUID() EAX = 0x580; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_hasCX8) + if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) EDX |= CPUID_MMX; @@ -1567,11 +1524,11 @@ void cpu_CPUID() case 0x80000001: EAX = 0x580; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_hasCX8) + if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) EDX |= CPUID_MMX; - if (cpu_has3DNOW) + if (cpu_has_feature(CPU_FEATURE_3DNOW)) EDX |= CPUID_3DNOW; break; @@ -2021,15 +1978,18 @@ void cpu_WRMSR() break; case 0x107: msr.fcr = EAX; - cpu_hasMMX = EAX & (1 << 9); + if (EAX & (1 << 9)) + cpu_features |= CPU_FEATURE_MMX; + else + cpu_features &= ~CPU_FEATURE_MMX; if (EAX & (1 << 1)) - cpu_hasCX8 = 1; + cpu_features |= CPU_FEATURE_CX8; else - cpu_hasCX8 = 0; + cpu_features &= ~CPU_FEATURE_CX8; if ((EAX & (1 << 20)) && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_WINCHIP2) - cpu_has3DNOW = 1; + cpu_features |= CPU_FEATURE_3DNOW; else - cpu_has3DNOW = 0; + cpu_features &= ~CPU_FEATURE_3DNOW; if (EAX & (1 << 29)) CPUID = 0; else diff --git a/src/cpu.h b/src/cpu.h index ba22f12..e3105ef 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -114,13 +114,19 @@ extern int cpu_multi; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int cpu_cyrix_alignment; -extern int cpu_hasrdtsc; -extern int cpu_hasMSR; -extern int cpu_hasMMX; -extern int cpu_hasCR4; -extern int cpu_hasVME; -extern int cpu_hasCX8; -extern int cpu_has3DNOW; +#define CPU_FEATURE_RDTSC (1 << 0) +#define CPU_FEATURE_MSR (1 << 1) +#define CPU_FEATURE_MMX (1 << 2) +#define CPU_FEATURE_CR4 (1 << 3) +#define CPU_FEATURE_VME (1 << 4) +#define CPU_FEATURE_CX8 (1 << 5) +#define CPU_FEATURE_3DNOW (1 << 6) + +extern uint32_t cpu_features; +static int cpu_has_feature(int feature) +{ + return cpu_features & feature; +} #define CR4_TSD (1 << 2) #define CR4_DE (1 << 3) diff --git a/src/x86_ops_3dnow.h b/src/x86_ops_3dnow.h index d57a3a3..304943f 100644 --- a/src/x86_ops_3dnow.h +++ b/src/x86_ops_3dnow.h @@ -19,7 +19,7 @@ static int opPREFETCH_a32(uint32_t fetchdat) static int opFEMMS(uint32_t fetchdat) { - ILLEGAL_ON(!cpu_hasMMX); + ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX)); if (cr0 & 4) { x86_int(7); diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index ca11638..aa81a2c 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -946,7 +946,7 @@ static int opCPUID(uint32_t fetchdat) static int opRDMSR(uint32_t fetchdat) { - if (cpu_hasMSR) + if (cpu_has_feature(CPU_FEATURE_MSR)) { cpu_RDMSR(); CLOCK_CYCLES(9); @@ -959,7 +959,7 @@ static int opRDMSR(uint32_t fetchdat) static int opWRMSR(uint32_t fetchdat) { - if (cpu_hasMSR) + if (cpu_has_feature(CPU_FEATURE_MSR)) { cpu_WRMSR(); CLOCK_CYCLES(9); diff --git a/src/x86_ops_mmx.h b/src/x86_ops_mmx.h index 4f361c6..95ed658 100644 --- a/src/x86_ops_mmx.h +++ b/src/x86_ops_mmx.h @@ -17,7 +17,7 @@ } #define MMX_ENTER() \ - if (!cpu_hasMMX) \ + if (!cpu_has_feature(CPU_FEATURE_MMX)) \ { \ cpu_state.pc = cpu_state.oldpc; \ x86illegal(); \ @@ -32,7 +32,7 @@ static int opEMMS(uint32_t fetchdat) { - if (!cpu_hasMMX) + if (!cpu_has_feature(CPU_FEATURE_MMX)) { cpu_state.pc = cpu_state.oldpc; x86illegal(); diff --git a/src/x86_ops_mov_ctrl.h b/src/x86_ops_mov_ctrl.h index 190dfdc..962d1b2 100644 --- a/src/x86_ops_mov_ctrl.h +++ b/src/x86_ops_mov_ctrl.h @@ -21,7 +21,7 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) cpu_state.regs[cpu_rm].l = cr3; break; case 4: - if (cpu_hasCR4) + if (cpu_has_feature(CPU_FEATURE_CR4)) { cpu_state.regs[cpu_rm].l = cr4; break; @@ -59,7 +59,7 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat) cpu_state.regs[cpu_rm].l = cr3; break; case 4: - if (cpu_hasCR4) + if (cpu_has_feature(CPU_FEATURE_CR4)) { cpu_state.regs[cpu_rm].l = cr4; break; @@ -144,7 +144,7 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) flushmmucache(); break; case 4: - if (cpu_hasCR4) + if (cpu_has_feature(CPU_FEATURE_CR4)) { cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; @@ -200,7 +200,7 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) flushmmucache(); break; case 4: - if (cpu_hasCR4) + if (cpu_has_feature(CPU_FEATURE_CR4)) { cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; diff --git a/src/x86_ops_msr.h b/src/x86_ops_msr.h index a3080a8..c2d3c3c 100644 --- a/src/x86_ops_msr.h +++ b/src/x86_ops_msr.h @@ -1,6 +1,6 @@ static int opRDTSC(uint32_t fetchdat) { - if (!cpu_hasrdtsc) + if (!cpu_has_feature(CPU_FEATURE_RDTSC)) { cpu_state.pc = cpu_state.oldpc; x86illegal(); From 84622584e203bcb738c4cda97294809f9afddada Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 8 Feb 2019 21:34:02 +0000 Subject: [PATCH 142/181] Move CPU tables to separate file. --- src/Makefile.am | 2 +- src/cpu.c | 427 ---------------------------------------------- src/cpu.h | 2 +- src/cpu_tables.c | 430 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 432 insertions(+), 429 deletions(-) create mode 100644 src/cpu_tables.c diff --git a/src/Makefile.am b/src/Makefile.am index fdd7857..b9f82d8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ wx-resources.cpp : pc.xrc pcem_SOURCES = 386.c 386_common.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \ codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \ -dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ +cpu_tables.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c ide_sff8038i.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \ laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c mvp3.c neat.c nmi.c nvr.c olivetti_m24.c \ diff --git a/src/cpu.c b/src/cpu.c index 6e45f04..42cbee1 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -120,433 +120,6 @@ static struct uint64_t fcr2, fcr3; } msr; -/*Available cpuspeeds : - 0 = 16 MHz - 1 = 20 MHz - 2 = 25 MHz - 3 = 33 MHz - 4 = 40 MHz - 5 = 50 MHz - 6 = 66 MHz - 7 = 75 MHz - 8 = 80 MHz - 9 = 90 MHz - 10 = 100 MHz - 11 = 120 MHz - 12 = 133 MHz - 13 = 150 MHz - 14 = 160 MHz - 15 = 166 MHz - 16 = 180 MHz - 17 = 200 MHz -*/ - -CPU cpus_8088[] = -{ - /*8088 standard*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_pcjr[] = -{ - /*8088 PCjr*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_europc[] = -{ - /*8088 EuroPC*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_8086[] = -{ - /*8086 standard*/ - {"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_pc1512[] = -{ - /*8086 Amstrad*/ - {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_286[] = -{ - /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_ibmat[] = -{ - /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1}, - {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_ibmxt286[] = -{ - /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_ps1_m2011[] = -{ - /*286*/ - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_ps2_m30_286[] = -{ - /*286*/ - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, - {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, - {"", -1, 0, 0, 0, 0} -}; - -CPU cpus_i386SX[] = -{ - /*i386SX*/ - {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_i386DX[] = -{ - /*i386DX*/ - {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2}, - {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_acer[] = -{ - /*i386SX*/ - {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4, 3}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Am386SX[] = -{ - /*Am386*/ - {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Am386DX[] = -{ - /*Am386*/ - {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_486SLC[] = -{ - /*Cx486SLC*/ - {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4}, - {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 2*2}, - {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3}, - {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_486DLC[] = -{ - /*Cx486DLC*/ - {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3, 3}, - {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3, 4}, - {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3, 5}, - {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6, 2*2}, - {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3}, - {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3}, - {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 2*4}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_i486[] = -{ - /*i486*/ - {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2}, - {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, - {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6}, - {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, - {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, - {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, - {"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, /*CPUID available on DX4, >= 75 MHz*/ - {"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*4}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ - {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, (5*3)/2}, - {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, (5*4)/2}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Am486[] = -{ - /*Am486/5x86*/ - {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ - {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ - {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, - {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, - {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 2*5}, - {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, - {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, - {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, - {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5}, - {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4}, - {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 4*5}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Cx486[] = -{ - /*Cx486/5x86*/ - {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, - {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, - {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 2*5}, - {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, - {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, - {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, - {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5}, - {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4}, - {"", -1, 0, 0, 0} -}; - - CPU cpus_6x86[] = - { - /*Cyrix 6x86*/ - {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 2*5}, - {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6}, - {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7}, - {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, - {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9}, - - /*Cyrix 6x86L*/ - {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7}, - {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, - {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9}, - - /*Cyrix 6x86MX*/ - {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2}, - {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2}, - {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, (7*8)/2}, - {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 3*10}, - {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 3*10}, - {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*11}, - {"", -1, 0, 0, 0} - }; - - - -CPU cpus_WinChip[] = -{ - /*IDT WinChip*/ - {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, (3*6)/2}, - {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*7)/2}, - {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*8)/2}, - {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*7}, - {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*8}, - {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*7)/2}, - {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2}, - {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7}, - {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, - {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, (7*8)/2}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_WinChip_SS7[] = -{ - /*IDT WinChip (Super Socket 7)*/ - {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, - {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, - {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, - {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, - {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, - {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, - {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24}, - {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 28}, - {"WinChip 2A/266", CPU_WINCHIP2, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28}, - {"WinChip 2A/300", CPU_WINCHIP2, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Pentium5V[] = -{ - /*Intel Pentium (5V, socket 4)*/ - {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8}, - {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, - {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_PentiumS5[] = -{ - /*Intel Pentium (Socket 5)*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2}, - {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2}, - {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, - {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, - {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, - {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Pentium[] = -{ - /*Intel Pentium*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2}, - {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2}, - {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, - {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, - {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, - {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, - {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2}, - {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, - {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, - {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, - {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, - {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2}, - {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 4*8}, - {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, (9*8)/2}, - {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, - {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, - {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_K6_S7[] = -{ - /*AMD K6*/ - {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6-2/300 AFR-66", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_K6_SS7[] = -{ - /*AMD K6*/ - {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6-2/300", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"K6-2/333", CPU_K6_2, 28, 333333333, 5, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, - {"K6-2/350", CPU_K6_2, 28, 350000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 42}, - {"K6-2/366", CPU_K6_2, 28, 366666666, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 44}, - {"K6-2/380", CPU_K6_2, 28, 380000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 46}, - {"K6-2/400", CPU_K6_2, 28, 400000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, - {"K6-2/450", CPU_K6_2, 28, 450000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-2/475", CPU_K6_2, 28, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, - {"K6-2/500", CPU_K6_2, 28, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, - {"K6-2/533", CPU_K6_2, 28, 533333333, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, - {"K6-2/550", CPU_K6_2, 28, 550000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, - {"K6-2+/450", CPU_K6_2P, 28, 450000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-2+/475", CPU_K6_2P, 28, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, - {"K6-2+/500", CPU_K6_2P, 28, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, - {"K6-2+/533", CPU_K6_2P, 28, 533333333, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, - {"K6-2+/550", CPU_K6_2P, 28, 550000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, - {"K6-III/400", CPU_K6_3, 28, 400000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, - {"K6-III/450", CPU_K6_3, 28, 450000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-III+/400", CPU_K6_3P, 28, 400000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, - {"K6-III+/450", CPU_K6_3P, 28, 450000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-III+/475", CPU_K6_3P, 28, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, - {"K6-III+/500", CPU_K6_3P, 28, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, - {"", -1, 0, 0, 0} -}; - void cpu_set_edx() { EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; diff --git a/src/cpu.h b/src/cpu.h index e3105ef..2e8cc4f 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -123,7 +123,7 @@ extern int cpu_cyrix_alignment; #define CPU_FEATURE_3DNOW (1 << 6) extern uint32_t cpu_features; -static int cpu_has_feature(int feature) +static inline int cpu_has_feature(int feature) { return cpu_features & feature; } diff --git a/src/cpu_tables.c b/src/cpu_tables.c new file mode 100644 index 0000000..ea5e2d1 --- /dev/null +++ b/src/cpu_tables.c @@ -0,0 +1,430 @@ +#include "ibm.h" +#include "cpu.h" + +/*Available cpuspeeds : + 0 = 16 MHz + 1 = 20 MHz + 2 = 25 MHz + 3 = 33 MHz + 4 = 40 MHz + 5 = 50 MHz + 6 = 66 MHz + 7 = 75 MHz + 8 = 80 MHz + 9 = 90 MHz + 10 = 100 MHz + 11 = 120 MHz + 12 = 133 MHz + 13 = 150 MHz + 14 = 160 MHz + 15 = 166 MHz + 16 = 180 MHz + 17 = 200 MHz +*/ + +CPU cpus_8088[] = +{ + /*8088 standard*/ + {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_pcjr[] = +{ + /*8088 PCjr*/ + {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_europc[] = +{ + /*8088 EuroPC*/ + {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_8086[] = +{ + /*8086 standard*/ + {"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_pc1512[] = +{ + /*8086 Amstrad*/ + {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_286[] = +{ + /*286*/ + {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, + {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_ibmat[] = +{ + /*286*/ + {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1}, + {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_ibmxt286[] = +{ + /*286*/ + {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_ps1_m2011[] = +{ + /*286*/ + {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_ps2_m30_286[] = +{ + /*286*/ + {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, + {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, + {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, + {"", -1, 0, 0, 0, 0} +}; + +CPU cpus_i386SX[] = +{ + /*i386SX*/ + {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, + {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_i386DX[] = +{ + /*i386DX*/ + {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2}, + {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_acer[] = +{ + /*i386SX*/ + {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4, 3}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Am386SX[] = +{ + /*Am386*/ + {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, + {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4}, + {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Am386DX[] = +{ + /*Am386*/ + {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, + {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_486SLC[] = +{ + /*Cx486SLC*/ + {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, + {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, + {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4}, + {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 2*2}, + {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3}, + {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_486DLC[] = +{ + /*Cx486DLC*/ + {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3, 3}, + {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3, 4}, + {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3, 5}, + {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6, 2*2}, + {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3}, + {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3}, + {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 2*4}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_i486[] = +{ + /*i486*/ + {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2}, + {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, + {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, + {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, + {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, + {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6}, + {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, + {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, + {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, + {"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, /*CPUID available on DX4, >= 75 MHz*/ + {"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*4}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ + {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, (5*3)/2}, + {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, (5*4)/2}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Am486[] = +{ + /*Am486/5x86*/ + {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, + {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ + {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ + {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, + {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, + {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, + {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 2*5}, + {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, + {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, + {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, + {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5}, + {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4}, + {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 4*5}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Cx486[] = +{ + /*Cx486/5x86*/ + {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, + {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, + {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, + {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, + {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, + {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 2*5}, + {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, + {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, + {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4}, + {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5}, + {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4}, + {"", -1, 0, 0, 0} +}; + + CPU cpus_6x86[] = + { + /*Cyrix 6x86*/ + {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 2*5}, + {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6}, + {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7}, + {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, + {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9}, + + /*Cyrix 6x86L*/ + {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7}, + {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, + {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9}, + + /*Cyrix 6x86MX*/ + {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2}, + {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2}, + {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, (7*8)/2}, + {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 3*10}, + {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 3*10}, + {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*11}, + {"", -1, 0, 0, 0} + }; + + + +CPU cpus_WinChip[] = +{ + /*IDT WinChip*/ + {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, (3*6)/2}, + {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*7)/2}, + {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*8)/2}, + {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*7}, + {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*8}, + {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*7)/2}, + {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2}, + {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7}, + {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, + {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, (7*8)/2}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_WinChip_SS7[] = +{ + /*IDT WinChip (Super Socket 7)*/ + {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7}, + {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8}, + {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9}, + {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, + {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, + {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24}, + {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 28}, + {"WinChip 2A/266", CPU_WINCHIP2, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28}, + {"WinChip 2A/300", CPU_WINCHIP2, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Pentium5V[] = +{ + /*Intel Pentium (5V, socket 4)*/ + {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7}, + {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8}, + {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, + {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_PentiumS5[] = +{ + /*Intel Pentium (Socket 5)*/ + {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2}, + {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2}, + {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6}, + {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2}, + {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, + {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, + {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, + {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Pentium[] = +{ + /*Intel Pentium*/ + {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2}, + {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2}, + {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6}, + {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2}, + {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, + {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, + {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, + {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, + {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2}, + {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7}, + {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8}, + {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, + {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, + {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2}, + {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 4*8}, + {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, (9*8)/2}, + {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, + {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, + {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_K6_S7[] = +{ + /*AMD K6*/ + {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6-2/300 AFR-66", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_K6_SS7[] = +{ + /*AMD K6*/ + {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6-2/300", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"K6-2/333", CPU_K6_2, 28, 333333333, 5, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, + {"K6-2/350", CPU_K6_2, 28, 350000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 42}, + {"K6-2/366", CPU_K6_2, 28, 366666666, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 44}, + {"K6-2/380", CPU_K6_2, 28, 380000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 46}, + {"K6-2/400", CPU_K6_2, 28, 400000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, + {"K6-2/450", CPU_K6_2, 28, 450000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-2/475", CPU_K6_2, 28, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, + {"K6-2/500", CPU_K6_2, 28, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + {"K6-2/533", CPU_K6_2, 28, 533333333, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, + {"K6-2/550", CPU_K6_2, 28, 550000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, + {"K6-2+/450", CPU_K6_2P, 28, 450000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-2+/475", CPU_K6_2P, 28, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, + {"K6-2+/500", CPU_K6_2P, 28, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + {"K6-2+/533", CPU_K6_2P, 28, 533333333, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, + {"K6-2+/550", CPU_K6_2P, 28, 550000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, + {"K6-III/400", CPU_K6_3, 28, 400000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, + {"K6-III/450", CPU_K6_3, 28, 450000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-III+/400", CPU_K6_3P, 28, 400000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, + {"K6-III+/450", CPU_K6_3P, 28, 450000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, + {"K6-III+/475", CPU_K6_3P, 28, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, + {"K6-III+/500", CPU_K6_3P, 28, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + {"", -1, 0, 0, 0} +}; + From 3f2d9ecf870e64a11c60ab49c2ee1f652734e11c Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 10 Feb 2019 12:32:25 +0000 Subject: [PATCH 143/181] Optimise out redundant uOPs, where the output register is never read. --- src/codegen_ir.c | 5 ++ src/codegen_ir_defs.h | 69 ++++++++++++------------ src/codegen_reg.c | 119 ++++++++++++++++++++++++++++++++++++------ src/codegen_reg.h | 64 +++++++++++++++++++---- 4 files changed, 200 insertions(+), 57 deletions(-) diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 556cb8c..56d58f7 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -21,6 +21,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) int jump_target_at_end = -1; int c; + codegen_reg_mark_as_required(); + codegen_reg_process_dead_list(ir); block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); block_pos = 0; codegen_backend_prologue(block); @@ -45,6 +47,9 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) } } + if ((uop->type & UOP_MASK) == UOP_INVALID) + continue; + if (uop->type & UOP_TYPE_PARAMS_REGS) { codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index a69f346..74b0043 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -312,6 +312,8 @@ #define UOP_MAX 0xc6 +#define UOP_INVALID 0xff + #define UOP_MASK 0xffff typedef struct uop_t @@ -338,7 +340,7 @@ typedef struct ir_data_t int wr_pos; } ir_data_t; -static inline uop_t *uop_alloc(ir_data_t *ir) +static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type) { uop_t *uop; @@ -353,7 +355,10 @@ static inline uop_t *uop_alloc(ir_data_t *ir) uop->src_reg_c = invalid_ir_reg; uop->jump_list_next = -1; - + + if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) + codegen_reg_mark_as_required(); + return uop; } @@ -366,7 +371,7 @@ static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop) static inline int uop_gen(uint32_t uop_type, ir_data_t *ir) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; @@ -375,7 +380,7 @@ static inline int uop_gen(uint32_t uop_type, ir_data_t *ir) static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -385,7 +390,7 @@ static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -393,7 +398,7 @@ static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int ar static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg); @@ -404,86 +409,86 @@ static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->imm_data = imm; } static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->p = p; } static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg); - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->imm_data = imm; } static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->imm_data = imm; } static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); uop->src_reg_b = codegen_reg_read(src_reg_b); uop->src_reg_c = codegen_reg_read(src_reg_c); - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg); - uop->dest_reg_a = codegen_reg_write(dest_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); uop->imm_data = imm; } static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -494,7 +499,7 @@ static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -504,7 +509,7 @@ static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int sr static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -514,7 +519,7 @@ static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_re static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -525,7 +530,7 @@ static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int sr static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->imm_data = imm; @@ -533,7 +538,7 @@ static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->p = p; @@ -541,7 +546,7 @@ static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->p = p; @@ -550,7 +555,7 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -559,7 +564,7 @@ static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); @@ -569,7 +574,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p) { - uop_t *uop = uop_alloc(ir); + uop_t *uop = uop_alloc(ir, uop_type); uop->type = uop_type; uop->src_reg_a = codegen_reg_read(src_reg_a); diff --git a/src/codegen_reg.c b/src/codegen_reg.c index f352d0a..dda256c 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -4,8 +4,10 @@ #include "codegen_ir_defs.h" #include "codegen_reg.h" +uint16_t reg_dead_list = 0; + uint8_t reg_last_version[IREG_COUNT]; -uint8_t reg_version_refcount[IREG_COUNT][256]; +reg_version_t reg_version[IREG_COUNT][256]; ir_reg_t invalid_ir_reg = {IREG_INVALID}; @@ -175,6 +177,19 @@ struct [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE}, }; +void codegen_reg_mark_as_required() +{ + int reg; + + for (reg = 0; reg < IREG_COUNT; reg++) + { + int last_version = reg_last_version[reg]; + + if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT) + reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED; + } +} + static int reg_is_native_size(ir_reg_t ir_reg) { int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; @@ -220,7 +235,7 @@ void codegen_reg_reset() for (c = 0; c < IREG_COUNT; c++) { reg_last_version[c] = 0; - reg_version_refcount[c][0] = 0; + reg_version[c][0].refcount = 0; } for (c = 0; c < CODEGEN_HOST_REGS; c++) { @@ -232,6 +247,8 @@ void codegen_reg_reset() host_fp_reg_set.regs[c] = invalid_ir_reg; host_fp_reg_set.dirty[c] = 0; } + + reg_dead_list = 0; } static inline int ir_reg_is_invalid(ir_reg_t ir_reg) @@ -239,9 +256,9 @@ static inline int ir_reg_is_invalid(ir_reg_t ir_reg) return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } -static inline int ir_get_get_refcount(ir_reg_t ir_reg) +static inline int ir_get_refcount(ir_reg_t ir_reg) { - return reg_version_refcount[IREG_GET_REG(ir_reg.reg)][ir_reg.version]; + return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount; } static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg) @@ -342,7 +359,7 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); void *p = ireg_data[ir_reg].p; - if (!reg_version_refcount[ir_reg][reg_set->regs[c].version] && + if (!reg_version[ir_reg][reg_set->regs[c].version].refcount && ireg_data[ir_reg].is_volatile) return; @@ -463,10 +480,30 @@ static void alloc_dest_reg(ir_reg_t ir_reg, int dest_reference) { if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { - if (reg_set->regs[c].version == ir_reg.version || (reg_set->regs[c].version == (ir_reg.version-1) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == dest_reference)) + if (reg_set->regs[c].version == ir_reg.version) + { reg_set->locked |= (1 << c); + } else + { + /*The immediate prior version may have been + optimised out, so search backwards to find the + last valid version*/ + int prev_version = ir_reg.version-1; +// pclog("prev_version search from %i\n", prev_version); + while (prev_version >= 0) + { + reg_version_t *regv = ®_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version]; + + if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference) + { + reg_set->locked |= (1 << c); + return; + } + prev_version--; + } fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference); + } return; } } @@ -513,7 +550,13 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version) break; - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]) + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version) + { + reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++; + break; + } + + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount) fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); } @@ -522,7 +565,7 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in /*No unused registers. Search for an unlocked register with no pending reads*/ for (c = 0; c < reg_set->nr_regs; c++) { - if (!(reg_set->locked & (1 << c)) && !ir_get_get_refcount(reg_set->regs[c])) + if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c])) break; } if (c == reg_set->nr_regs) @@ -548,13 +591,13 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in // else // pclog(" already loaded %i\n", c); - reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]--; - if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == (uint8_t)-1) + reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--; + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t)-1) fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); if (host_reg_idx) *host_reg_idx = c; -// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], host_regs[c].reg,host_regs[c].version, c); +// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], reg_set->regs[c].reg,reg_set->regs[c].version, c); return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg); } @@ -570,11 +613,11 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; parent_reg.version = ir_reg.version - 1; - reg_version_refcount[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1]++; + reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++; codegen_reg_alloc_read_reg(block, parent_reg, &c); - if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version != ir_reg.version-1) + if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version-1) fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, reg_set->regs[c].reg,reg_set->regs[c].version, ir_reg.reg,ir_reg.version); @@ -591,9 +634,9 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { - if (reg_set->regs[c].version == ir_reg.version-1) + if (reg_set->regs[c].version <= ir_reg.version-1) { - if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] != 0) + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); break; } @@ -682,3 +725,49 @@ void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) reg_set->dirty[c] = 0; } } + +/*Process dead register list, and optimise out register versions and uOPs where + possible*/ +void codegen_reg_process_dead_list(ir_data_t *ir) +{ + while (reg_dead_list) + { + int version = reg_dead_list & 0xff; + int reg = reg_dead_list >> 8; + reg_version_t *regv = ®_version[reg][version]; + uop_t *uop = &ir->uops[regv->parent_uop]; + + /*Barrier uOPs should be preserved*/ + if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))) + { +// pclog(" codegen_process_dead_list: reg=%i version=%i uop=%i\n", reg, version, regv->parent_uop); + uop->type = UOP_INVALID; + /*Adjust refcounts on source registers. If these drop to + zero then those registers can be considered for removal*/ + if (uop->src_reg_a.reg != IREG_INVALID) + { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version); + } + if (uop->src_reg_b.reg != IREG_INVALID) + { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version); + } + if (uop->src_reg_c.reg != IREG_INVALID) + { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version); + } + regv->flags |= REG_FLAGS_DEAD; + } + + reg_dead_list = regv->next; + } +} diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 448518e..01272bc 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -272,7 +272,36 @@ static inline int ireg_seg_limit_high(x86seg *seg) } extern uint8_t reg_last_version[IREG_COUNT]; -extern uint8_t reg_version_refcount[IREG_COUNT][256]; + +/*This version of the register must be calculated, regardless of whether it is + apparently required or not. Do not optimise out.*/ +#define REG_FLAGS_REQUIRED (1 << 0) +/*This register and the parent uOP have been optimised out.*/ +#define REG_FLAGS_DEAD (1 << 1) + +typedef struct +{ + /*Refcount of pending reads on this register version*/ + uint8_t refcount; + /*Flags*/ + uint8_t flags; + /*uOP that generated this register version*/ + uint16_t parent_uop; + /*Pointer to next register version in dead register list*/ + uint16_t next; +} reg_version_t; + +extern reg_version_t reg_version[IREG_COUNT][256]; + +/*Head of dead register list; a list of register versions that are not used and + can be optimised out*/ +extern uint16_t reg_dead_list; + +static inline void add_to_dead_list(reg_version_t *regv, int reg, int version) +{ + regv->next = reg_dead_list; + reg_dead_list = version | (reg << 8); +} typedef struct { @@ -289,37 +318,50 @@ typedef uint16_t ir_host_reg_t; static inline ir_reg_t codegen_reg_read(int reg) { ir_reg_t ireg; + reg_version_t *version; if (IREG_GET_REG(reg) == IREG_INVALID) fatal("codegen_reg_read - IREG_INVALID\n"); ireg.reg = reg; ireg.version = reg_last_version[IREG_GET_REG(reg)]; - reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]++; - if (!reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]) + version = ®_version[IREG_GET_REG(ireg.reg)][ireg.version]; + version->flags = 0; + version->refcount++; + if (!version->refcount) fatal("codegen_reg_read - refcount overflow\n"); - else if (reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version] > REG_VERSION_MAX) + else if (version->refcount > REG_VERSION_MAX) CPU_BLOCK_END(); - +// pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]); return ireg; } -static inline ir_reg_t codegen_reg_write(int reg) +static inline ir_reg_t codegen_reg_write(int reg, int uop_nr) { ir_reg_t ireg; - + int last_version = reg_last_version[IREG_GET_REG(reg)]; + reg_version_t *version; + if (IREG_GET_REG(reg) == IREG_INVALID) fatal("codegen_reg_write - IREG_INVALID\n"); ireg.reg = reg; - ireg.version = reg_last_version[IREG_GET_REG(reg)] + 1; + ireg.version = last_version + 1; + + if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount && + !(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED)) + add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version); + reg_last_version[IREG_GET_REG(reg)]++; if (!reg_last_version[IREG_GET_REG(reg)]) fatal("codegen_reg_write - version overflow\n"); else if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) CPU_BLOCK_END(); - reg_version_refcount[IREG_GET_REG(reg)][ireg.version] = 0; - + version = ®_version[IREG_GET_REG(reg)][ireg.version]; + version->refcount = 0; + version->flags = 0; + version->parent_uop = uop_nr; +// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK); return ireg; } @@ -337,4 +379,6 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx); ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); +void codegen_reg_mark_as_required(); +void codegen_reg_process_dead_list(struct ir_data_t *ir); #endif From a73081f0bd23c82ce13ca9c2986ddb8c860ada7c Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 13 Feb 2019 21:11:27 +0000 Subject: [PATCH 144/181] Fix ARM and ARM64 build errors. --- src/codegen_backend_arm.c | 10 +++++----- src/codegen_backend_arm64.c | 10 +++++----- src/codegen_backend_arm64_ops.c | 2 +- src/codegen_backend_arm_ops.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c index fc77eba..0c1c2c8 100644 --- a/src/codegen_backend_arm.c +++ b/src/codegen_backend_arm.c @@ -77,7 +77,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) MOV R1, #0 MOV PC, LR * STR LR, [SP, -4]! - BL readmemb386l + BL readmembl LDRB R1, cpu_state.abrt LDR PC, [SP], #4 */ @@ -116,7 +116,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); if (size == 1) - host_arm_BL(block, (uintptr_t)readmemb386l); + host_arm_BL(block, (uintptr_t)readmembl); else if (size == 2) host_arm_BL(block, (uintptr_t)readmemwl); else if (size == 4) @@ -149,7 +149,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) MOV R1, #0 MOV PC, LR * STR LR, [SP, -4]! - BL readmemb386l + BL readmembl LDRB R1, cpu_state.abrt LDR PC, [SP], #4 */ @@ -192,7 +192,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) else if (size == 8) host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); if (size == 1) - host_arm_BL(block, (uintptr_t)writememb386l); + host_arm_BL(block, (uintptr_t)writemembl); else if (size == 2) host_arm_BL(block, (uintptr_t)writememwl); else if (size == 4) @@ -304,7 +304,7 @@ void codegen_backend_init() block_current = 0; block_pos = 0; block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL); + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); block->data = codeblock_allocator_get_ptr(block->head_mem_block); block_write_data = block->data; build_loadstore_routines(&codeblock[block_current]); diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 4a2885a..7497a0b 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -82,7 +82,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) MOV W1, #0 RET * STP X29, X30, [SP, #-16] - BL readmemb386l + BL readmembl LDRB R1, cpu_state.abrt LDP X29, X30, [SP, #-16] RET @@ -116,7 +116,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); if (size == 1) - host_arm64_call(block, (uintptr_t)readmemb386l); + host_arm64_call(block, (uintptr_t)readmembl); else if (size == 2) host_arm64_call(block, (uintptr_t)readmemwl); else if (size == 4) @@ -151,7 +151,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) MOV W1, #0 RET * STP X29, X30, [SP, #-16] - BL writememb386l + BL writemembl LDRB R1, cpu_state.abrt LDP X29, X30, [SP, #-16] RET @@ -189,7 +189,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) else if (size == 8) host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); if (size == 1) - host_arm64_call(block, (uintptr_t)writememb386l); + host_arm64_call(block, (uintptr_t)writemembl); else if (size == 2) host_arm64_call(block, (uintptr_t)writememwl); else if (size == 4) @@ -301,7 +301,7 @@ void codegen_backend_init() block_current = 0; block_pos = 0; block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL); + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); block->data = codeblock_allocator_get_ptr(block->head_mem_block); block_write_data = block->data; build_loadstore_routines(block); diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 0a7e24d..eaf5089 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -282,7 +282,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) static void codegen_allocate_new_block(codeblock_t *block) { /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); uint32_t offset = (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]; diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 17355cc..b6a6142 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -212,7 +212,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) static void codegen_allocate_new_block(codeblock_t *block) { /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block); + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); uint32_t offset = ((uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]) - 8; From 01e86135ab2b2c71a9f00987c0295c17dcd83bde Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 13 Feb 2019 22:12:53 +0000 Subject: [PATCH 145/181] Tweak FDC command timing and add register access waitstates. Fixes floppy in Windows 98 with VA-503. --- src/fdc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/fdc.c b/src/fdc.c index f958bd3..308599f 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -9,6 +9,7 @@ #include "io.h" #include "pic.h" #include "timer.h" +#include "x86.h" static int fdc_reset_stat = 0; /*FDC*/ @@ -320,6 +321,8 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) // pclog("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready); int drive; + cycles -= ISA_CYCLES(8); + switch (addr&7) { case 1: return; @@ -550,7 +553,7 @@ bad_command: // pclog("Got all params %02X\n", fdc.command); fdc.stat=0x30; discint=fdc.command&0x1F; - timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); + timer_set_delay_u64(&fdc.timer, 256 * TIMER_USEC); // fdc.drive = fdc.params[0] & 3; disc_drivesel = fdc.drive & 1; fdc_reset_stat = 0; @@ -674,6 +677,9 @@ uint8_t fdc_read(uint16_t addr, void *priv) { uint8_t temp; int drive; + + cycles -= ISA_CYCLES(8); + // /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %02x %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,fdc.stat,ins); switch (addr&7) { From 063ffb4eab45a70422cef0b16a03447abb6c6cc3 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 14 Feb 2019 19:39:47 +0000 Subject: [PATCH 146/181] Update Makefile.mingw-wx-sdl2. --- src/Makefile.mingw-wx-sdl2 | 52 +++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 3bfb669..aab0c0d 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -6,25 +6,43 @@ WXVERSION = 31 WXINCLUDE = C:/MinGW/include/wx/ CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing CXXFLAGS = $(CFLAGS) -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl.o cdrom-image.o \ - cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o \ - device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \ - i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ - keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o \ - mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o \ - scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ - sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ - sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ - sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ - vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o \ - vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ +OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o \ + cbm_io.o cdrom-ioctl.o cdrom-image.o cmd640.o codegen.o codegen_accumulate.o codegen_allocator.o \ + codegen_backend.o codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \ + codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o codegen_ir.o codegen_ops.o \ + codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \ + codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_jump.o \ + codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \ + codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ + codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \ + codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ + codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o device.o \ + dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o \ + fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o \ + ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \ + joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ + keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \ + mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \ + mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \ + piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o \ + scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \ + sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ + sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ + sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ + sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ + vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \ + vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \ + vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ - vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ - vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o \ - wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o \ - wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \ - wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o wx.res + vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \ + vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o \ + vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o wx-main.o \ + wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \ + wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \ + wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \ + wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o \ + wx-joystickconfig.o wx-createdisc.o wx.res DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o From ab124776a021ebce5e841836d06f8c456c3cbc86 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 16 Mar 2019 14:53:26 +0000 Subject: [PATCH 147/181] Rework self modifying code handling. Code blocks now have a varying level of granularity in the page and dirty masks. Most blocks have 64-byte granularity, but blocks that are repeatedly modified drop to 1-byte granularity. This reduces the maximum size of the affected block significantly, but reduces recompilation due to data located too close to code. If the block is still marked as dirty, then it is recompiled without any immediate instruction parameters being baked into the recompiled code, instead being fetched from the RAM array as needed. This severely reduces recompilation rates on some SMC-heavy games, eg Duke Nukem 3D, System Shock, Screamer etc, giving a major speedup. --- src/386_common.h | 16 + src/386_dynarec.c | 34 +- src/Makefile.am | 2 +- src/Makefile.mingw-wx-sdl2 | 4 +- src/codegen.c | 93 ++++-- src/codegen.h | 37 ++- src/codegen_backend.c | 420 +++++++++++++++++++++---- src/codegen_backend_arm64_uops.c | 62 ++++ src/codegen_backend_arm_uops.c | 63 ++++ src/codegen_backend_x86-64_ops.c | 55 +++- src/codegen_backend_x86-64_ops.h | 2 + src/codegen_backend_x86-64_uops.c | 59 +++- src/codegen_backend_x86_ops.c | 17 + src/codegen_backend_x86_ops.h | 2 + src/codegen_backend_x86_uops.c | 59 +++- src/codegen_ir_defs.h | 10 + src/codegen_ops_3dnow.c | 15 + src/codegen_ops_arith.c | 501 +++++++++++++++++++++++++----- src/codegen_ops_branch.c | 7 + src/codegen_ops_helpers.c | 26 ++ src/codegen_ops_helpers.h | 24 ++ src/codegen_ops_jump.c | 11 + src/codegen_ops_logic.c | 85 ++++- src/codegen_ops_misc.c | 14 +- src/codegen_ops_mmx_arith.c | 1 + src/codegen_ops_mmx_cmp.c | 1 + src/codegen_ops_mmx_loadstore.c | 6 +- src/codegen_ops_mmx_logic.c | 8 +- src/codegen_ops_mmx_pack.c | 1 + src/codegen_ops_mmx_shift.c | 6 + src/codegen_ops_mov.c | 71 ++++- src/codegen_ops_shift.c | 133 +++++++- src/codegen_ops_stack.c | 6 + src/codegen_reg.h | 2 + src/mem.c | 85 ++++- src/mem.h | 14 +- 36 files changed, 1719 insertions(+), 233 deletions(-) create mode 100644 src/codegen_ops_helpers.c diff --git a/src/386_common.h b/src/386_common.h index 9f092bf..80da16d 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -1,3 +1,6 @@ +#ifndef _386_COMMON_H_ +#define _386_COMMON_H_ + #define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) #define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) @@ -128,6 +131,17 @@ static inline uint32_t fastreadl(uint32_t a) return val; } +static inline void *get_ram_ptr(uint32_t a) +{ + if ((a >> 12) == pccache) + return &pccache2[a]; + else + { + uint8_t *t = getpccache(a); + return &t[a]; + } +} + static inline uint8_t getbyte() { cpu_state.pc++; @@ -219,3 +233,5 @@ static inline void seteaq(uint64_t v) #define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 #define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++ #define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 + +#endif diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3044b7c..2817727 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -320,8 +320,10 @@ void exec386_dynarec(int cycs) if (!valid_block) { uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask) + int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f); + + if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask)) { /*Walk page tree to see if we find the correct block*/ codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); @@ -339,12 +341,21 @@ void exec386_dynarec(int cycs) } } + if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) + { + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; + if (block->flags & CODEBLOCK_BYTE_MASK) + block->flags |= CODEBLOCK_NO_IMMEDIATES; + else + block->flags |= CODEBLOCK_BYTE_MASK; + } if (valid_block && (block->page_mask & *block->dirty_mask)) { - codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr); - page->dirty_mask[(phys_addr >> 10) & 3] = 0; + codegen_check_flush(page, page->dirty_mask, phys_addr); if (block->pc == BLOCK_PC_INVALID) valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; } if (valid_block && block->page_mask2) { @@ -355,16 +366,17 @@ void exec386_dynarec(int cycs) allow the first page to be interpreted and for the page fault to occur when the page boundary is actually crossed.*/ - uint32_t phys_addr_2 = get_phys_noabrt(block->pc + 0x400); + uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400)); page_t *page_2 = &pages[phys_addr_2 >> 12]; if ((block->phys_2 ^ phys_addr_2) & ~0xfff) valid_block = 0; else if (block->page_mask2 & *block->dirty_mask2) { - codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2); - page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0; + codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); if (block->pc == BLOCK_PC_INVALID) valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; } } if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) @@ -390,7 +402,8 @@ void exec386_dynarec(int cycs) else if (valid_block && !cpu_state.abrt) { uint32_t start_pc = cpu_state.pc; - + const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; + cpu_block_end = 0; x86_was_reset = 0; @@ -434,7 +447,7 @@ void exec386_dynarec(int cycs) will prevent any block from spanning more than 2 pages. In practice this limit will never be hit, as host block size is only 2kB*/ - if ((cpu_state.pc - start_pc) > 1000) + if ((cpu_state.pc - start_pc) >= max_block_size) CPU_BLOCK_END(); if (trap) @@ -465,6 +478,7 @@ void exec386_dynarec(int cycs) { /*Mark block but do not recompile*/ uint32_t start_pc = cpu_state.pc; + const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; cpu_block_end = 0; x86_was_reset = 0; @@ -505,7 +519,7 @@ void exec386_dynarec(int cycs) will prevent any block from spanning more than 2 pages. In practice this limit will never be hit, as host block size is only 2kB*/ - if ((cpu_state.pc - start_pc) > 1000) + if ((cpu_state.pc - start_pc) >= max_block_size) CPU_BLOCK_END(); if (trap) diff --git a/src/Makefile.am b/src/Makefile.am index b9f82d8..9b2795b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc # PCem pcem_SOURCES = 386.c 386_common.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \ -cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \ +cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_helpers.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \ codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \ cpu_tables.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \ hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c ide_sff8038i.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index aab0c0d..435aaf5 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -3,7 +3,7 @@ CPP = g++ CC = gcc WINDRES = windres.exe WXVERSION = 31 -WXINCLUDE = C:/MinGW/include/wx/ +WXINCLUDE = e:/MinGWget/include/wx/ CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing CXXFLAGS = $(CFLAGS) OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o \ @@ -11,7 +11,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer38 codegen_backend.o codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \ codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o codegen_ir.o codegen_ops.o \ codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \ - codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_jump.o \ + codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \ codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \ codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \ diff --git a/src/codegen.c b/src/codegen.c index 3db8d60..23ea678 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -11,6 +11,7 @@ #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_ops.h" +#include "codegen_ops_helpers.h" int has_ea; @@ -85,6 +86,7 @@ void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { + uint32_t old_pc = *op_pc; // pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat); if (!cpu_mod && cpu_rm == 6) { @@ -145,12 +147,16 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin } } + codegen_mark_code_present(ir->block, cs+old_pc, (*op_pc)-old_pc); return op_ea_seg; } static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { + codeblock_t *block = ir->block; + uint32_t old_pc = (*op_pc) + 1; uint32_t new_eaaddr; + int extra_bytes = 0; if (cpu_rm == 4) { @@ -162,13 +168,23 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin case 0: if ((sib & 7) == 5) { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + extra_bytes = 1; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 5; + } (*op_pc) += 4; } else { uop_MOV(ir, IREG_eaaddr, sib & 7); + extra_bytes = 1; } break; case 1: @@ -176,12 +192,22 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); (*op_pc)++; + extra_bytes = 2; break; case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + extra_bytes = 1; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 5; + } (*op_pc) += 4; + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); break; } if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ @@ -215,29 +241,54 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin { if (!cpu_mod && cpu_rm == 5) { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - uop_MOV(ir, IREG_eaaddr, cpu_rm); - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_mod == 1) + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8)); - (*op_pc)++; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); } else { new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); - (*op_pc) += 4; + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 4; + } + + (*op_pc) += 4; + } + else + { + uop_MOV(ir, IREG_eaaddr, cpu_rm); + if (cpu_mod) + { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_mod == 1) + { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8)); + (*op_pc)++; + extra_bytes = 1; + } + else + { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0); + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); + extra_bytes = 4; + } + (*op_pc) += 4; + } } } } + + if (extra_bytes) + codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes); + return op_ea_seg; } @@ -583,6 +634,7 @@ generate_call: opcode_mask = 0xff; } } + codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off); // pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) { @@ -654,6 +706,7 @@ generate_call: uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); uop_CALL_INSTRUCTION_FUNC(ir, op); + codegen_mark_code_present(block, cs+cpu_state.pc, 8); last_op_32 = op_32; last_op_ea_seg = op_ea_seg; diff --git a/src/codegen.h b/src/codegen.h index 1438dab..9365e44 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -73,6 +73,14 @@ extern uint8_t *block_write_data; #define CODEBLOCK_WAS_RECOMPILED 4 /*Code block is in free list and is not valid*/ #define CODEBLOCK_IN_FREE_LIST 8 +/*Code block spans two pages, page_mask2 and dirty_mask2 are valid*/ +#define CODEBLOCK_HAS_PAGE2 0x10 +/*Code block is using a byte mask for code present and dirty*/ +#define CODEBLOCK_BYTE_MASK 0x20 +/*Code block is in dirty list*/ +#define CODEBLOCK_IN_DIRTY_LIST 0x40 +/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/ +#define CODEBLOCK_NO_IMMEDIATES 0x80 #define BLOCK_PC_INVALID 0xffffffff @@ -277,10 +285,33 @@ static inline void codeblock_tree_delete(codeblock_t *block) } } -#define PAGE_MASK_INDEX_MASK 3 -#define PAGE_MASK_INDEX_SHIFT 10 #define PAGE_MASK_MASK 63 -#define PAGE_MASK_SHIFT 4 +#define PAGE_MASK_SHIFT 6 + +void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len); + +static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len) +{ + if (len == 1) + { + if (block->flags & CODEBLOCK_BYTE_MASK) + { + if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/ + block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK)); + else + block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK)); + } + else + { + if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/ + block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); + else + block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); + } + } + else + codegen_mark_code_present_multibyte(block, start_pc, len); +} void codegen_init(); void codegen_close(); diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 4874233..0f76cbe 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -55,9 +55,22 @@ uint32_t instr_counts[256*256]; static uint16_t block_free_list; static void delete_block(codeblock_t *block); +static void delete_dirty_block(codeblock_t *block); + +/*Temporary list of code blocks that have recently been evicted. This allows for + some historical state to be kept when a block is the target of self-modifying + code. + + The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is + exceeded the oldest entry will be moved to the free list.*/ +static uint16_t block_dirty_list_head, block_dirty_list_tail; +static int dirty_list_size = 0; +#define DIRTY_LIST_MAX_SIZE 64 static void block_free_list_add(codeblock_t *block) { + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("block_free_list_add: block=%p in dirty list\n", block); if (block_free_list) block->next = block_free_list; else @@ -67,23 +80,92 @@ static void block_free_list_add(codeblock_t *block) // pclog("block_free_list_add: %p %p\n", block, block->next); } +static void block_dirty_list_add(codeblock_t *block) +{ + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("block_dirty_list_add: block=%p already in dirty list\n", block); +// pclog("block_dirty_list_add: block=%i size=%i %i head=%i tail=%i\n", get_block_nr(block), dirty_list_size, dirty_list_check_size(), block_dirty_list_head, block_dirty_list_tail); + if (block_dirty_list_head != BLOCK_INVALID) + { + codeblock_t *old_head = &codeblock[block_dirty_list_head]; + + block->next = block_dirty_list_head; + block->prev = BLOCK_INVALID; + block_dirty_list_head = old_head->prev = get_block_nr(block); +// pclog(" next=%p,%i prev=%i\n", old_head, block->next, old_head->prev); + } + else + { + /*List empty*/ + block->prev = block->next = BLOCK_INVALID; + block_dirty_list_head = block_dirty_list_tail = get_block_nr(block); + } + block->flags |= CODEBLOCK_IN_DIRTY_LIST; +// pclog(" block_dirty_list_add: %p flags = %x\n", block, block->flags); + dirty_list_size++; + if (dirty_list_size > DIRTY_LIST_MAX_SIZE) + { + /*Evict oldest block to the free list*/ + codeblock_t *evict_block = &codeblock[block_dirty_list_tail]; + + if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST)) + fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags); + if (!block_dirty_list_tail) + fatal("block_dirty_list_add - !block_dirty_list_tail\n"); + if (evict_block->prev == BLOCK_INVALID) + fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n"); + + block_dirty_list_tail = evict_block->prev; + codeblock[evict_block->prev].next = BLOCK_INVALID; + + dirty_list_size--; + evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; +// pclog(" block_dirty_list_add: %p flags = %x\n", evict_block, evict_block->flags); + delete_dirty_block(evict_block); + } + +// pclog("block_free_list_add: %p %p\n", block, block->next); +} + +static void block_dirty_list_remove(codeblock_t *block) +{ + codeblock_t *prev_block = &codeblock[block->prev]; + codeblock_t *next_block = &codeblock[block->next]; + + if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST)) + fatal("block_dirty_list_remove: block=%p not in dirty list\n", block); + + /*Is block head of list*/ + if (block->prev == BLOCK_INVALID) + block_dirty_list_head = block->next; + else + prev_block->next = block->next; + + /*Is block tail of list?*/ + if (block->next == BLOCK_INVALID) + block_dirty_list_tail = block->prev; + else + next_block->prev = block->prev; + + dirty_list_size--; + if (dirty_list_size < 0) + fatal("remove - dirty_list_size < 0!\n"); + block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; +// pclog(" block_dirty_list_remove: %p flags = %x\n", block, block->flags); +} + int codegen_purge_purgable_list() { if (purgable_page_list_head) { page_t *page = &pages[purgable_page_list_head]; - int c; -// pclog("Purge page %08x\n", purgable_page_list_head); - for (c = 0; c < 4; c++) + + if (page->code_present_mask & page->dirty_mask) { -// pclog(" Check %016llx %016llx\n", page->code_present_mask[c], page->dirty_mask[c]); - if (page->code_present_mask[c] & page->dirty_mask[c]) - { - codegen_check_flush(page, page->dirty_mask[c], (purgable_page_list_head << 12) + (c << 10)); -// pclog(" Check %08x %i\n", (purgable_page_list_head << 12) + (c << 10), block_free_list); - if (block_free_list) - return 1; - } + codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12); + + if (block_free_list) + return 1; } } return 0; @@ -95,6 +177,27 @@ static codeblock_t *block_free_list_get() while (!block_free_list) { + /*Free list is empty, check the dirty list*/ + if (block_dirty_list_tail) + { + if (dirty_list_size <= 0) + fatal("get - dirty_list_size <= 0!\n"); + + /*Reuse oldest block*/ + block = &codeblock[block_dirty_list_tail]; + +// pclog("block_free_list_get: remove block=%p size=%i\n", block, dirty_list_size); + block_dirty_list_tail = block->prev; + if (block->prev == BLOCK_INVALID) + block_dirty_list_head = BLOCK_INVALID; + else + codeblock[block->prev].next = BLOCK_INVALID; + dirty_list_size--; + block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; + delete_dirty_block(block); + block_free_list = get_block_nr(block); + break; + } /*Free list is empty - free up a block*/ if (!codegen_purge_purgable_list()) codegen_delete_random_block(0); @@ -103,6 +206,7 @@ static codeblock_t *block_free_list_get() block = &codeblock[block_free_list]; block_free_list = block->next; block->flags &= ~CODEBLOCK_IN_FREE_LIST; +// pclog(" block_free_list_get: %p flags = %x\n", block, block->flags); block->next = 0; // pclog("block_free_list_get: %p %p\n", block, block_free_list); return block; @@ -118,6 +222,8 @@ void codegen_init() block_free_list = 0; for (c = 0; c < BLOCK_SIZE; c++) block_free_list_add(&codeblock[c]); + block_dirty_list_head = block_dirty_list_tail = 0; + dirty_list_size = 0; #ifdef DEBUG_EXTRA memset(instr_counts, 0, sizeof(instr_counts)); #endif @@ -200,22 +306,23 @@ void dump_block() static void add_to_block_list(codeblock_t *block) { - uint16_t block_prev_nr = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + uint16_t block_prev_nr = pages[block->phys >> 12].block; uint16_t block_nr = get_block_nr(block); +//pclog("Add to block list %p %08x %llx %x\n", block, block->phys, block->page_mask2, block->flags); if (!block->page_mask) - fatal("add_to_block_list - mask = 0\n"); + fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2); if (block_prev_nr) { block->next = block_prev_nr; codeblock[block_prev_nr].prev = block_nr; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block_nr; + pages[block->phys >> 12].block = block_nr; } else { block->next = BLOCK_INVALID; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block_nr; + pages[block->phys >> 12].block = block_nr; } if (block->next) @@ -226,26 +333,31 @@ static void add_to_block_list(codeblock_t *block) if (block->page_mask2) { - block_prev_nr = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + block->flags |= CODEBLOCK_HAS_PAGE2; + + block_prev_nr = pages[block->phys_2 >> 12].block_2; if (block_prev_nr) { block->next_2 = block_prev_nr; codeblock[block_prev_nr].prev_2 = block_nr; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block_nr; + pages[block->phys_2 >> 12].block_2 = block_nr; } else { block->next_2 = BLOCK_INVALID; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block_nr; + pages[block->phys_2 >> 12].block_2 = block_nr; } } +// pclog(" add_to_block_list: %p flags = %x\n", block, block->flags); } static void remove_from_block_list(codeblock_t *block, uint32_t pc) { if (!block->page_mask) return; + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("remove_from_block_list: in dirty list\n"); if (block->prev) { @@ -255,18 +367,21 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) } else { - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; + pages[block->phys >> 12].block = block->next; if (block->next) codeblock[block->next].prev = BLOCK_INVALID; else mem_flush_write_page(block->phys, 0); } - if (!block->page_mask2) + + if (!(block->flags & CODEBLOCK_HAS_PAGE2)) { if (block->prev_2 || block->next_2) - fatal("Invalid block_2\n"); + fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys); return; } + block->flags &= ~CODEBLOCK_HAS_PAGE2; +// pclog(" remove_from_block_list: %p flags = %x\n", block, block->flags); if (block->prev_2) { @@ -277,7 +392,7 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) else { // pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; + pages[block->phys_2 >> 12].block_2 = block->next_2; if (block->next_2) codeblock[block->next_2].prev_2 = BLOCK_INVALID; else @@ -285,6 +400,22 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) } } +static void invalidate_block(codeblock_t *block) +{ + uint32_t old_pc = block->pc; + + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("invalidate_block: already in dirty list\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Invalidating deleted block\n"); + + remove_from_block_list(block, old_pc); + block_dirty_list_add(block); + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; +} + static void delete_block(codeblock_t *block) { uint32_t old_pc = block->pc; @@ -297,13 +428,29 @@ static void delete_block(codeblock_t *block) block->pc = BLOCK_PC_INVALID; codeblock_tree_delete(block); - remove_from_block_list(block, old_pc); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block_dirty_list_remove(block); + else + remove_from_block_list(block, old_pc); if (block->head_mem_block) codegen_allocator_free(block->head_mem_block); block->head_mem_block = NULL; block_free_list_add(block); } +static void delete_dirty_block(codeblock_t *block) +{ + if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) + codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; + + if (block->pc == BLOCK_PC_INVALID) + fatal("Deleting deleted block\n"); + block->pc = BLOCK_PC_INVALID; + + codeblock_tree_delete(block); + block_free_list_add(block); +} + void codegen_delete_block(codeblock_t *block) { if (block->pc != BLOCK_PC_INVALID) @@ -332,16 +479,19 @@ void codegen_delete_random_block(int required_mem_block) void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) { - uint16_t block_nr = page->block[(phys_addr >> 10) & 3]; + uint16_t block_nr = page->block; + int remove_from_evict_list = 0; + int c; while (block_nr) { codeblock_t *block = &codeblock[block_nr]; uint16_t next_block = block->next; - if (mask & block->page_mask) + if (*block->dirty_mask & block->page_mask) { - delete_block(block); +// pclog("Delete block from codegen_check_flush %08x %08x %016llx %016llx %016llx %02x\n", phys_addr, block->pc, *block->dirty_mask, block->page_mask, *block->dirty_mask & block->page_mask, block->flags); + invalidate_block(block); cpu_recomp_evicted++; } if (block_nr == next_block) @@ -349,16 +499,17 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) block_nr = next_block; } - block_nr = page->block_2[(phys_addr >> 10) & 3]; + block_nr = page->block_2; while (block_nr) { codeblock_t *block = &codeblock[block_nr]; uint16_t next_block = block->next_2; - - if (mask & block->page_mask2) + + if (*block->dirty_mask2 & block->page_mask2) { - delete_block(block); +// pclog("Delete block from codegen_check_flush2 %08x %08x\n", phys_addr, block->pc);*/ + invalidate_block(block); cpu_recomp_evicted++; } if (block_nr == next_block) @@ -366,13 +517,19 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) block_nr = next_block; } - page->code_present_mask[(phys_addr >> 10) & 3] &= ~mask; - page->dirty_mask[(phys_addr >> 10) & 3] &= ~mask; + if (page->code_present_mask & page->dirty_mask) + remove_from_evict_list = 1; + page->code_present_mask &= ~page->dirty_mask; + page->dirty_mask = 0; - if (!(page->code_present_mask[0] & page->dirty_mask[0]) && - !(page->code_present_mask[1] & page->dirty_mask[1]) && - !(page->code_present_mask[2] & page->dirty_mask[2]) && - !(page->code_present_mask[3] & page->dirty_mask[3])) + for (c = 0; c < 64; c++) + { + if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c]) + remove_from_evict_list = 0; + page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c]; + page->byte_dirty_mask[c] = 0; + } + if (remove_from_evict_list) page_remove_from_evict_list(page); } @@ -380,10 +537,9 @@ void codegen_block_init(uint32_t phys_addr) { codeblock_t *block; page_t *page = &pages[phys_addr >> 12]; - - if (!page->block[(phys_addr >> 10) & 3]) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); + if (!page->block) + mem_flush_write_page(phys_addr, cs+cpu_state.pc); block = block_free_list_get(); if (!block) fatal("codegen_block_init: block_free_list_get() returned NULL\n"); @@ -396,16 +552,17 @@ void codegen_block_init(uint32_t phys_addr) block->pc = cs + cpu_state.pc; block->_cs = cs; block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask = &page->dirty_mask; block->dirty_mask2 = NULL; block->next = block->prev = BLOCK_INVALID; block->next_2 = block->prev_2 = BLOCK_INVALID; - block->page_mask = 0; + block->page_mask = block->page_mask2 = 0; block->flags = CODEBLOCK_STATIC_TOP; +// pclog(" block_init: %p flags = %x\n", block, block->flags); block->status = cpu_cur_status; recomp_page = block->phys & ~0xfff; - +// pclog("codegen_block_init: %08x\n", block->pc); codeblock_tree_add(block); } @@ -419,8 +576,8 @@ ir_data_t *codegen_get_ir_data() void codegen_block_start_recompile(codeblock_t *block) { page_t *page = &pages[block->phys >> 12]; - - if (!page->block[(block->phys >> 10) & 3]) + + if (!page->block) mem_flush_write_page(block->phys, cs+cpu_state.pc); block_num = HASH(block->phys); @@ -433,6 +590,9 @@ void codegen_block_start_recompile(codeblock_t *block) block->data = codeblock_allocator_get_ptr(block->head_mem_block); block->status = cpu_cur_status; + + block->page_mask = block->page_mask2 = 0; + block->ins = 0; cpu_block_end = 0; @@ -465,7 +625,14 @@ void codegen_block_start_recompile(codeblock_t *block) codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); + if (block->flags & CODEBLOCK_BYTE_MASK) + { + block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK]; + block->dirty_mask2 = NULL; + } + ir_data = codegen_ir_init(); + ir_data->block = block; codegen_reg_reset(); codegen_accumulate_reset(); codegen_generate_reset(); @@ -482,40 +649,104 @@ void codegen_block_remove() recomp_page = -1; } -void codegen_block_generate_end_mask() +void codegen_block_generate_end_mask_recompile() +{ + codeblock_t *block = &codeblock[block_current]; + page_t *p; +//pclog("gen_end_mask: %08x %08x %016llx %016llx\n", block->pc, codegen_endpc, block->page_mask,block->page_mask2); + + p = &pages[block->phys >> 12]; + if (block->flags & CODEBLOCK_BYTE_MASK) + { + int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + + p->byte_code_present_mask[offset] |= block->page_mask; + } + else + p->code_present_mask |= block->page_mask; + + if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + + block->phys_2 = -1; + block->next_2 = block->prev_2 = BLOCK_INVALID; + if (block->page_mask2) + { + block->phys_2 = get_phys_noabrt(codegen_endpc); + if (block->phys_2 != -1) + { + page_t *page_2 = &pages[block->phys_2 >> 12]; + + if (block->flags & CODEBLOCK_BYTE_MASK) + { + int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + + page_2->byte_code_present_mask[offset] |= block->page_mask2; + block->dirty_mask2 = &page_2->byte_dirty_mask[offset]; + } + else + { + page_2->code_present_mask |= block->page_mask2; + block->dirty_mask2 = &page_2->dirty_mask; + } + if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2)) + page_add_to_evict_list(page_2); + + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, codegen_endpc); + + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) + { +// pclog(" next_2->pc=%08x\n", block->next_2->pc); + if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); + } + } + } + +// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask); + recomp_page = -1; +} + +void codegen_block_generate_end_mask_mark() { codeblock_t *block = &codeblock[block_current]; uint32_t start_pc; uint32_t end_pc; page_t *p; + if (block->flags & CODEBLOCK_BYTE_MASK) + fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n"); + block->page_mask = 0; - start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ codegen_endpc) & ~0x3ff) - end_pc = 0x3ff & ~15; + start_pc = (block->pc & 0xfff) & ~63; + if ((block->pc ^ codegen_endpc) & ~0xfff) + end_pc = 0xfff & ~63; else - end_pc = (codegen_endpc & 0x3ff) & ~15; + end_pc = (codegen_endpc & 0xfff) & ~63; if (end_pc < start_pc) - end_pc = 0x3ff; + end_pc = 0xfff; start_pc >>= PAGE_MASK_SHIFT; end_pc >>= PAGE_MASK_SHIFT; - + // pclog("block_end: %08x %08x\n", start_pc, end_pc); for (; start_pc <= end_pc; start_pc++) - { + { block->page_mask |= ((uint64_t)1 << start_pc); // pclog(" %08x %llx\n", start_pc, block->page_mask); } - + p = &pages[block->phys >> 12]; - p->code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; - if ((p->dirty_mask[(block->phys >> 10) & 3] & block->page_mask) && !page_in_evict_list(p)) + p->code_present_mask |= block->page_mask; + if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p)) page_add_to_evict_list(p); block->phys_2 = -1; block->page_mask2 = 0; block->next_2 = block->prev_2 = BLOCK_INVALID; - if ((block->pc ^ codegen_endpc) & ~0x3ff) + if ((block->pc ^ codegen_endpc) & ~0xfff) { block->phys_2 = get_phys_noabrt(codegen_endpc); if (block->phys_2 != -1) @@ -523,14 +754,15 @@ void codegen_block_generate_end_mask() page_t *page_2 = &pages[block->phys_2 >> 12]; start_pc = 0; - end_pc = (codegen_endpc & 0x3ff) >> PAGE_MASK_SHIFT; + end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT; for (; start_pc <= end_pc; start_pc++) block->page_mask2 |= ((uint64_t)1 << start_pc); - page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - if ((page_2->dirty_mask[(block->phys_2 >> 10) & 3] & block->page_mask2) && !page_in_evict_list(page_2)) + + page_2->code_present_mask |= block->page_mask2; + if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2)) page_add_to_evict_list(page_2); - if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) + if (!pages[block->phys_2 >> 12].block_2) mem_flush_write_page(block->phys_2, codegen_endpc); if (!block->page_mask2) @@ -542,7 +774,7 @@ void codegen_block_generate_end_mask() fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); } - block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = &page_2->dirty_mask; } } @@ -554,7 +786,7 @@ void codegen_block_end() { codeblock_t *block = &codeblock[block_current]; - codegen_block_generate_end_mask(); + codegen_block_generate_end_mask_mark(); add_to_block_list(block); } @@ -562,10 +794,13 @@ void codegen_block_end_recompile(codeblock_t *block) { codegen_timing_block_end(); - remove_from_block_list(block, block->pc); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block_dirty_list_remove(block); + else + remove_from_block_list(block, block->pc); block->next = block->prev = BLOCK_INVALID; block->next_2 = block->prev_2 = BLOCK_INVALID; - codegen_block_generate_end_mask(); + codegen_block_generate_end_mask_recompile(); add_to_block_list(block); // pclog("End block %i\n", block_num); @@ -580,3 +815,60 @@ void codegen_flush() { return; } + +void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len) +{ + if (len) + { + uint32_t end_pc = start_pc + (len-1); + + if (block->flags & CODEBLOCK_BYTE_MASK) + { + uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK; + uint32_t end_pc_masked = start_pc & PAGE_MASK_MASK; + + if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/ + { + for (; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask2 |= ((uint64_t)1 << start_pc_masked); + } + else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/ + { + for (; start_pc_masked <= 63; start_pc_masked++) + block->page_mask |= ((uint64_t)1 << start_pc_masked); + for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask2 |= ((uint64_t)1 << start_pc_masked); + } + else /*First page only*/ + { + for (; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask |= ((uint64_t)1 << start_pc_masked); + } + } + else + { + uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT; + uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT; + start_pc_shifted &= PAGE_MASK_MASK; + end_pc_shifted &= PAGE_MASK_MASK; + + if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/ + { + for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask2 |= ((uint64_t)1 << start_pc_shifted); + } + else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/ + { + for (; start_pc_shifted <= 63; start_pc_shifted++) + block->page_mask |= ((uint64_t)1 << start_pc_shifted); + for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask2 |= ((uint64_t)1 << start_pc_shifted); + } + else /*First page only*/ + { + for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask |= ((uint64_t)1 << start_pc_shifted); + } + } + } +} diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 47a6b3a..0f56360 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1413,6 +1413,66 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); + if (REG_IS_L(dest_size)) + { + host_arm64_LDR_IMM_W(block, dest_reg, REG_TEMP, 0); + } + else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); + if (REG_IS_L(dest_size)) + { + host_arm64_LDRB_IMM_W(block, dest_reg, REG_TEMP, 0); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size)) + { + host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); + if (REG_IS_L(dest_size)) + { + host_arm64_LDRH_IMM(block, dest_reg, REG_TEMP, 0); + } + else if (REG_IS_W(dest_size)) + { + host_arm64_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -2765,6 +2825,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index a47488d..402a7d7 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1534,6 +1534,66 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); + if (REG_IS_L(dest_size)) + { + host_arm_LDR_IMM(block, dest_reg, REG_TEMP, 0); + } + else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); + if (REG_IS_L(dest_size)) + { + host_arm_LDRB_IMM(block, dest_reg, REG_TEMP, 0); + } + else if (REG_IS_W(dest_size)) + { + host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size)) + { + host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); + if (REG_IS_L(dest_size)) + { + host_arm_LDRH_IMM(block, dest_reg, REG_TEMP, 0); + } + else if (REG_IS_W(dest_size)) + { + host_arm_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} static int codegen_OR(codeblock_t *block, uop_t *uop) { @@ -2914,6 +2974,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index a4a8680..cd634bd 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1058,6 +1058,29 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ } +void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + else + { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t)p); + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } +} void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); @@ -1080,7 +1103,37 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) } } else - fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset); + { + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t)p); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } +} +void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + else + { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t)p); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x41, 0x0f, 0xb7, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } } void host_x86_NOP(codeblock_t *block) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index eaee044..8d0c07a 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -110,7 +110,9 @@ void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p); void host_x86_NOP(codeblock_t *block); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index da8e8e4..d0768a2 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1269,6 +1269,60 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); return 0; } +static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); + } + else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); + } + else if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); + } + else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); + } + else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} static int codegen_MOVSX(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2681,7 +2735,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - + [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index ce64b33..f6a9bda 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -788,6 +788,23 @@ void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } +void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + + if (offset >= -128 && offset < 127) + { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } + else + { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t)p); + } +} void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) { int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 08b7e9f..1ef8df8 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -108,7 +108,9 @@ void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg); void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p); +void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p); void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index f3ace1e..096497c 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1256,6 +1256,60 @@ static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); return 0; } +static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); + } + else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); + } + else if (REG_IS_B(dest_size)) + { + host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); + } + else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) + { + host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); + } + else if (REG_IS_W(dest_size)) + { + host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); + } + else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} static int codegen_MOVSX(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2680,7 +2734,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - + [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, + [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 74b0043..7880c7a 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -76,6 +76,12 @@ #define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26) /*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ #define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27) +/*UOP_MOV_REG_PTR - dest_reg = *p*/ +#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28) +/*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/ +#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29) +/*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/ +#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a) /*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ #define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) /*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ @@ -338,6 +344,7 @@ typedef struct ir_data_t { uop_t uops[UOP_NR_MAX]; int wr_pos; + struct codeblock_t *block; } ir_data_t; static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type) @@ -667,6 +674,9 @@ static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, in #define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) #define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) #define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p) +#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p) +#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p) #define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) #define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) #define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) diff --git a/src/codegen_ops_3dnow.c b/src/codegen_ops_3dnow.c index ad846e4..7a2af83 100644 --- a/src/codegen_ops_3dnow.c +++ b/src/codegen_ops_3dnow.c @@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; \ \ uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ if ((fetchdat & 0xc0) == 0xc0) \ { \ int src_reg = fetchdat & 7; \ @@ -32,6 +33,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + codegen_mark_code_present(block, cs+op_pc+1, 1); \ return op_pc + 2; \ } @@ -49,6 +51,7 @@ uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -65,6 +68,7 @@ uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } @@ -73,6 +77,7 @@ uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -89,6 +94,7 @@ uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg)); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } @@ -97,6 +103,7 @@ uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -113,6 +120,7 @@ uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } @@ -121,6 +129,7 @@ uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -136,6 +145,7 @@ uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -143,6 +153,7 @@ uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -159,6 +170,7 @@ uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -166,6 +178,7 @@ uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -182,6 +195,7 @@ uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } @@ -189,5 +203,6 @@ uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c index ca0b980..08bb5f1 100644 --- a/src/codegen_ops_arith.c +++ b/src/codegen_ops_arith.c @@ -7,6 +7,7 @@ #include "codegen_ir.h" #include "codegen_ops.h" #include "codegen_ops_arith.h" +#include "codegen_ops_helpers.h" static inline void get_cf(ir_data_t *ir, int dest_reg) { @@ -26,6 +27,7 @@ uint32_t ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -41,6 +43,7 @@ uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -56,12 +59,14 @@ uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV(ir, IREG_flags_res, IREG_EAX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; -//return 0; + + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -95,6 +100,7 @@ uint32_t ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -131,6 +137,7 @@ uint32_t ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -164,6 +171,7 @@ uint32_t ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -200,6 +208,7 @@ uint32_t ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -232,6 +241,7 @@ uint32_t ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -276,6 +286,7 @@ uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -289,18 +300,29 @@ uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + codegen_mark_code_present(block, cs+op_pc, 4); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; return op_pc + 4; } @@ -308,6 +330,7 @@ uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -339,6 +362,7 @@ uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -372,6 +396,7 @@ uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -403,6 +428,7 @@ uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -436,6 +462,7 @@ uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -466,6 +493,7 @@ uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -507,6 +535,7 @@ uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -520,6 +549,7 @@ uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -532,12 +562,14 @@ uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -569,6 +601,7 @@ uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -600,6 +633,7 @@ uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -631,6 +665,7 @@ uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -662,6 +697,7 @@ uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -692,6 +728,7 @@ uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -732,6 +769,7 @@ uint32_t ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -747,6 +785,7 @@ uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -762,12 +801,14 @@ uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV(ir, IREG_flags_res, IREG_EAX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -801,6 +842,7 @@ uint32_t ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -837,6 +879,7 @@ uint32_t ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -870,6 +913,7 @@ uint32_t ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -907,6 +951,7 @@ uint32_t ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -939,6 +984,7 @@ uint32_t ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); get_cf(ir, IREG_temp1); if ((fetchdat & 0xc0) == 0xc0) { @@ -984,6 +1030,7 @@ uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -997,15 +1044,27 @@ uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_EAX); @@ -1016,6 +1075,7 @@ uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -1047,6 +1107,7 @@ uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1080,6 +1141,7 @@ uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -1111,6 +1173,7 @@ uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1145,6 +1208,7 @@ uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -1175,6 +1239,7 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1208,23 +1273,43 @@ uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + int skip_immediate = 0; + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; uint8_t imm = fastreadb(cs + op_pc + 1); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp0_B, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; @@ -1232,8 +1317,16 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch case 0x10: /*ADC*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); @@ -1242,38 +1335,68 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch case 0x18: /*SBB*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x28: /*SUB*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); break; case 0x38: /*CMP*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } + else + { + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); break; @@ -1372,27 +1495,49 @@ uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch } codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + int skip_immediate = 0; + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; uint16_t imm = fastreadw(cs + op_pc + 1); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp0_W, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; @@ -1400,8 +1545,16 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x10: /*ADC*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); @@ -1410,38 +1563,68 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x18: /*SBB*/ get_cf(ir, IREG_temp1); uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x28: /*SUB*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); break; case 0x38: /*CMP*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } + else + { + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); break; @@ -1462,65 +1645,103 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_check_seg_write(block, ir, target_seg); imm = fastreadw(cs + op_pc + 1); uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp2_W, cs+op_pc+1); + } switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); break; case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); break; case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); @@ -1528,8 +1749,16 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x38: /*CMP*/ uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_temp2_W); + } + else + { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + } uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); break; @@ -1540,27 +1769,49 @@ uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs+op_pc+1, 2); return op_pc + 3; } uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + int skip_immediate = 0; + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; uint32_t imm = fastreadl(cs + op_pc + 1); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; @@ -1568,8 +1819,16 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x10: /*ADC*/ get_cf(ir, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); @@ -1578,37 +1837,67 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x18: /*SBB*/ get_cf(ir, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x28: /*SUB*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); break; case 0x38: /*CMP*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } + else + { + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); break; @@ -1630,19 +1919,34 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet imm = fastreadl(cs + op_pc + 1); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp2, cs+op_pc+1); + } + switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); @@ -1650,44 +1954,68 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x10: /*ADC*/ get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x18: /*SBB*/ get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); break; case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); uop_MOV(ir, IREG_flags_res, IREG_temp1); break; case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); uop_MOV(ir, IREG_flags_res, IREG_temp0); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); @@ -1695,8 +2023,16 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet case 0x38: /*CMP*/ uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_temp2); + } + else + { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + } uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); break; @@ -1706,11 +2042,14 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs+op_pc+1, 4); return op_pc + 5; } uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -1875,10 +2214,12 @@ uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -2041,6 +2382,7 @@ uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } @@ -2121,6 +2463,7 @@ uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + codegen_mark_code_present(block, cs+op_pc, 1); rebuild_c(ir); if ((fetchdat & 0xc0) == 0xc0) diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index fdc0569..35e5c46 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -529,6 +529,7 @@ uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u dest_addr &= 0xffff; \ ropJ ## cond ## _common(block, ir, dest_addr); \ \ + codegen_mark_code_present(block, cs+op_pc, 1); \ return op_pc+1; \ } \ uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -538,6 +539,7 @@ uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, \ ropJ ## cond ## _common(block, ir, dest_addr); \ \ + codegen_mark_code_present(block, cs+op_pc, 2); \ return op_pc+2; \ } \ uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -547,6 +549,7 @@ uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, \ ropJ ## cond ## _common(block, ir, dest_addr); \ \ + codegen_mark_code_present(block, cs+op_pc, 4); \ return op_pc+4; \ } @@ -585,6 +588,7 @@ uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc+1; } @@ -611,6 +615,7 @@ uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc+1; } @@ -647,6 +652,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc+1; } uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -682,5 +688,6 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc+1; } diff --git a/src/codegen_ops_helpers.c b/src/codegen_ops_helpers.c new file mode 100644 index 0000000..8ccd1fb --- /dev/null +++ b/src/codegen_ops_helpers.c @@ -0,0 +1,26 @@ +#include "ibm.h" +#include "x86.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_ir_defs.h" +#include "codegen_reg.h" +#include "codegen_ops_helpers.h" + +void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +{ + /*Word access that crosses two pages. Perform reads from both pages, shift and combine*/ + uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr)); + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1)); + uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8); + uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W); +} + +void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +{ + /*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/ + uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3)); + uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3)); + uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8); + uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8); + uop_OR(ir, dest_reg, dest_reg, IREG_temp3); +} diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index 0da73b6..e1e2bbc 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -1,3 +1,4 @@ +#include "386_common.h" #include "codegen_backend.h" static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) @@ -85,3 +86,26 @@ static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *s else uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout); } + +static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +{ + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); +} + +void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr); +static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +{ + if ((addr & 0xfff) == 0xfff) + LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr); + else + uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr)); +} + +void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr); +static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +{ + if ((addr & 0xfff) >= 0xffd) + LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr); + else + uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr)); +} diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index c2c7eb6..dd417e4 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -17,6 +17,7 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f dest_addr &= 0xffff; uop_MOV_IMM(ir, IREG_pc, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 1); return -1; } uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -27,6 +28,7 @@ uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t dest_addr &= 0xffff; uop_MOV_IMM(ir, IREG_pc, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 2); return -1; } uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -35,6 +37,7 @@ uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t uint32_t dest_addr = op_pc+4+offset; uop_MOV_IMM(ir, IREG_pc, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 4); return -1; } @@ -49,6 +52,7 @@ uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); uop_CALL_FUNC(ir, loadcsjmp); + codegen_mark_code_present(block, cs+op_pc, 4); return -1; } uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -62,6 +66,7 @@ uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); uop_CALL_FUNC(ir, loadcsjmp); + codegen_mark_code_present(block, cs+op_pc, 6); return -1; } @@ -80,6 +85,7 @@ uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t SUB_SP(ir, 2); uop_MOV_IMM(ir, IREG_pc, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 2); return -1; } uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -95,6 +101,7 @@ uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t SUB_SP(ir, 4); uop_MOV_IMM(ir, IREG_pc, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 4); return -1; } @@ -146,6 +153,7 @@ uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 ADD_SP(ir, 2+offset); uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + codegen_mark_code_present(block, cs+op_pc, 2); return -1; } uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -163,6 +171,7 @@ uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 } ADD_SP(ir, 4+offset); + codegen_mark_code_present(block, cs+op_pc, 2); return -1; } @@ -243,6 +252,7 @@ uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_CALL_FUNC(ir, loadcs); ADD_SP(ir, 4+offset); + codegen_mark_code_present(block, cs+op_pc, 2); return -1; } uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -271,5 +281,6 @@ uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_CALL_FUNC(ir, loadcs); ADD_SP(ir, 8+offset); + codegen_mark_code_present(block, cs+op_pc, 2); return -1; } diff --git a/src/codegen_ops_logic.c b/src/codegen_ops_logic.c index 8f402f1..015031f 100644 --- a/src/codegen_ops_logic.c +++ b/src/codegen_ops_logic.c @@ -6,6 +6,7 @@ #include "codegen.h" #include "codegen_ir.h" #include "codegen_ops.h" +#include "codegen_ops_helpers.h" #include "codegen_ops_logic.h" uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -17,6 +18,7 @@ uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -28,13 +30,23 @@ uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_EAX); @@ -45,6 +57,7 @@ uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -72,6 +85,7 @@ uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -102,6 +116,7 @@ uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -129,6 +144,7 @@ uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -159,6 +175,7 @@ uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -186,6 +203,7 @@ uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -222,6 +240,7 @@ uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -233,23 +252,35 @@ uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_EAX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -277,6 +308,7 @@ uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -307,6 +339,7 @@ uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -334,6 +367,7 @@ uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -364,6 +398,7 @@ uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -391,6 +426,7 @@ uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -426,6 +462,7 @@ uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -436,22 +473,34 @@ uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + } - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -479,6 +528,7 @@ uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -506,6 +556,7 @@ uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -538,6 +589,7 @@ uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AL); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -549,23 +601,35 @@ uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOVZX(ir, IREG_flags_res, IREG_AX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } + else + { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); uop_MOV(ir, IREG_flags_res, IREG_EAX); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -593,6 +657,7 @@ uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -623,6 +688,7 @@ uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -650,6 +716,7 @@ uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -680,6 +747,7 @@ uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -707,6 +775,7 @@ uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c index 2db4c32..13e0e64 100644 --- a/src/codegen_ops_misc.c +++ b/src/codegen_ops_misc.c @@ -16,6 +16,7 @@ uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f if ((fetchdat & 0xc0) == 0xc0) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W); @@ -28,6 +29,7 @@ uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f if ((fetchdat & 0xc0) == 0xc0) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr); @@ -43,6 +45,7 @@ uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch if (fetchdat & 0x20) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) reg = IREG_8(fetchdat & 7); else @@ -67,6 +70,7 @@ uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc+2; case 0x10: /*NOT*/ @@ -111,6 +115,7 @@ uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe if (fetchdat & 0x20) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) reg = IREG_16(fetchdat & 7); else @@ -135,6 +140,7 @@ uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 2); return op_pc+3; case 0x10: /*NOT*/ @@ -179,6 +185,7 @@ uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe if (fetchdat & 0x20) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) reg = IREG_32(fetchdat & 7); else @@ -202,6 +209,7 @@ uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); codegen_flags_changed = 1; + codegen_mark_code_present(block, cs+op_pc+1, 4); return op_pc+5; case 0x10: /*NOT*/ @@ -267,6 +275,7 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { if ((fetchdat & 0x38) == 0x28) @@ -284,7 +293,7 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); src_reg = IREG_temp0_W; } - + switch (fetchdat & 0x38) { case 0x00: /*INC*/ @@ -373,6 +382,7 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { if ((fetchdat & 0x38) == 0x28) @@ -510,6 +520,7 @@ uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u if ((fetchdat & 0xc0) == 0xc0) \ return 0; \ \ + codegen_mark_code_present(block, cs+op_pc, 1); \ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ codegen_check_seg_read(block, ir, target_seg); \ @@ -531,6 +542,7 @@ uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u if ((fetchdat & 0xc0) == 0xc0) \ return 0; \ \ + codegen_mark_code_present(block, cs+op_pc, 1); \ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ codegen_check_seg_read(block, ir, target_seg); \ diff --git a/src/codegen_ops_mmx_arith.c b/src/codegen_ops_mmx_arith.c index cd23e3c..1629fe6 100644 --- a/src/codegen_ops_mmx_arith.c +++ b/src/codegen_ops_mmx_arith.c @@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; \ \ uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ if ((fetchdat & 0xc0) == 0xc0) \ { \ int src_reg = fetchdat & 7; \ diff --git a/src/codegen_ops_mmx_cmp.c b/src/codegen_ops_mmx_cmp.c index f56f413..b7fe44d 100644 --- a/src/codegen_ops_mmx_cmp.c +++ b/src/codegen_ops_mmx_cmp.c @@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; \ \ uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ if ((fetchdat & 0xc0) == 0xc0) \ { \ int src_reg = fetchdat & 7; \ diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c index e3c33e0..ac591e8 100644 --- a/src/codegen_ops_mmx_loadstore.c +++ b/src/codegen_ops_mmx_loadstore.c @@ -15,6 +15,7 @@ uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -32,13 +33,13 @@ uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } return op_pc + 1; - } uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int src_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -64,6 +65,7 @@ uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -80,7 +82,6 @@ uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } return op_pc + 1; - } uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -88,6 +89,7 @@ uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int src_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; diff --git a/src/codegen_ops_mmx_logic.c b/src/codegen_ops_mmx_logic.c index 428a591..744f22b 100644 --- a/src/codegen_ops_mmx_logic.c +++ b/src/codegen_ops_mmx_logic.c @@ -15,6 +15,7 @@ uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -32,13 +33,13 @@ uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } return op_pc + 1; - } uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -56,13 +57,13 @@ uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe } return op_pc + 1; - } uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -80,13 +81,13 @@ uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetc } return op_pc + 1; - } uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { int dest_reg = (fetchdat >> 3) & 7; uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -104,5 +105,4 @@ uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } return op_pc + 1; - } diff --git a/src/codegen_ops_mmx_pack.c b/src/codegen_ops_mmx_pack.c index 7bf1941..e625217 100644 --- a/src/codegen_ops_mmx_pack.c +++ b/src/codegen_ops_mmx_pack.c @@ -16,6 +16,7 @@ uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t int dest_reg = (fetchdat >> 3) & 7; \ \ uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ if ((fetchdat & 0xc0) == 0xc0) \ { \ int src_reg = fetchdat & 7; \ diff --git a/src/codegen_ops_mmx_shift.c b/src/codegen_ops_mmx_shift.c index ad0f597..3086f4d 100644 --- a/src/codegen_ops_mmx_shift.c +++ b/src/codegen_ops_mmx_shift.c @@ -17,6 +17,7 @@ uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int shift = fastreadb(cs + op_pc + 1); uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); switch (op) { case 0x10: /*PSRLW*/ @@ -33,6 +34,7 @@ uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -42,6 +44,7 @@ uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int shift = fastreadb(cs + op_pc + 1); uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); switch (op) { case 0x10: /*PSRLD*/ @@ -58,6 +61,7 @@ uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -67,6 +71,7 @@ uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ int shift = fastreadb(cs + op_pc + 1); uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs+op_pc, 1); switch (op) { case 0x10: /*PSRLQ*/ @@ -83,5 +88,6 @@ uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c index 669523d..26cd4e5 100644 --- a/src/codegen_ops_mov.c +++ b/src/codegen_ops_mov.c @@ -14,6 +14,7 @@ uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -22,14 +23,21 @@ uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - fetchdat = fastreadl(cs + op_pc); - - uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); - + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc); + } + else + { + fetchdat = fastreadl(cs + op_pc); + uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); + codegen_mark_code_present(block, cs+op_pc, 4); + } return op_pc + 4; } @@ -39,6 +47,9 @@ uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; +// if (block->phys == 0x49a400) +// pclog("ropMOVb_rmarkcode %08x 1\n", cs+op_pc); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -61,6 +72,7 @@ uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -83,6 +95,7 @@ uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -105,6 +118,7 @@ uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -126,6 +140,7 @@ uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -147,6 +162,7 @@ uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -178,6 +194,7 @@ uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 codegen_check_seg_read(block, ir, op_ea_seg); uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr); + codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -193,20 +210,37 @@ uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 codegen_check_seg_read(block, ir, op_ea_seg); uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr); + codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t addr; + uint32_t addr = 0; if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); + { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc); + } + else + { + addr = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 4); + } + } else + { addr = fastreadw(cs + op_pc); + codegen_mark_code_present(block, cs+op_pc, 2); + } uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); codegen_check_seg_read(block, ir, op_ea_seg); - uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); + if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200)) + uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr); + else + uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); return op_pc + ((op_32 & 0x200) ? 4 : 2); } @@ -224,6 +258,7 @@ uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 codegen_check_seg_write(block, ir, op_ea_seg); uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL); + codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -239,6 +274,7 @@ uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 codegen_check_seg_write(block, ir, op_ea_seg); uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX); + codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); return op_pc + ((op_32 & 0x200) ? 4 : 2); } uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -254,6 +290,7 @@ uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 codegen_check_seg_write(block, ir, op_ea_seg); uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX); + codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); return op_pc + ((op_32 & 0x200) ? 4 : 2); } @@ -262,6 +299,7 @@ uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uint8_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -278,6 +316,7 @@ uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); } + codegen_mark_code_present(block, cs+op_pc+1, 1); return op_pc + 2; } uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -285,6 +324,7 @@ uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uint16_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -301,6 +341,7 @@ uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); } + codegen_mark_code_present(block, cs+op_pc+1, 2); return op_pc + 3; } uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -308,6 +349,7 @@ uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ x86seg *target_seg; uint32_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -324,6 +366,7 @@ uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); } + codegen_mark_code_present(block, cs+op_pc+1, 4); return op_pc + 5; } @@ -331,6 +374,7 @@ uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg; + codegen_mark_code_present(block, cs+op_pc, 1); switch (fetchdat & 0x38) { case 0x00: /*ES*/ @@ -377,6 +421,7 @@ uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg; + codegen_mark_code_present(block, cs+op_pc, 1); switch (fetchdat & 0x38) { case 0x00: /*ES*/ @@ -423,7 +468,8 @@ uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_ { int src_reg; x86seg *rseg; - + + codegen_mark_code_present(block, cs+op_pc, 1); switch (fetchdat & 0x38) { case 0x00: /*ES*/ @@ -468,6 +514,7 @@ uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -490,6 +537,7 @@ uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -512,6 +560,7 @@ uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -535,6 +584,7 @@ uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -557,6 +607,7 @@ uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32 { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -579,6 +630,7 @@ uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 { int dest_reg = (fetchdat >> 3) & 7; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int src_reg = fetchdat & 7; @@ -624,6 +676,7 @@ uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f { int reg1 = IREG_8((fetchdat >> 3) & 7); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int reg2 = IREG_8(fetchdat & 7); @@ -651,6 +704,7 @@ uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int reg1 = IREG_16((fetchdat >> 3) & 7); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int reg2 = IREG_16(fetchdat & 7); @@ -678,6 +732,7 @@ uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int reg1 = IREG_32((fetchdat >> 3) & 7); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int reg2 = IREG_32(fetchdat & 7); diff --git a/src/codegen_ops_shift.c b/src/codegen_ops_shift.c index d4b5b56..7410d4d 100644 --- a/src/codegen_ops_shift.c +++ b/src/codegen_ops_shift.c @@ -7,6 +7,7 @@ #include "codegen_backend.h" #include "codegen_ir.h" #include "codegen_ops.h" +#include "codegen_ops_helpers.h" #include "codegen_ops_shift.h" static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) @@ -236,6 +237,81 @@ static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc return op_pc + 1; } +static uint32_t shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count_reg) +{ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } + else + { + switch (fetchdat & 0x38) + { + case 0x20: case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -245,6 +321,7 @@ uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -253,7 +330,8 @@ uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); } imm = fastreadb(cs + op_pc + 1) & 0x1f; - + codegen_mark_code_present(block, cs+op_pc+1, 1); + if (imm) return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1; return op_pc+1; @@ -266,6 +344,7 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -274,7 +353,8 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); } imm = fastreadb(cs + op_pc + 1) & 0x1f; - + codegen_mark_code_present(block, cs+op_pc+1, 1); + if (imm) return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1; return op_pc+1; @@ -282,11 +362,11 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { x86seg *target_seg = NULL; - uint8_t imm; if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -294,10 +374,23 @@ uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet codegen_check_seg_write(block, ir, target_seg); uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); } - imm = fastreadb(cs + op_pc + 1) & 0x1f; + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1); - if (imm) - return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; + uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + return shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; + } + else + { + uint8_t imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs+op_pc+1, 1); + + if (imm) + return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; + } return op_pc+1; } @@ -308,6 +401,7 @@ uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -325,6 +419,7 @@ uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -342,6 +437,7 @@ uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ return 0; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); @@ -363,7 +459,8 @@ uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - + + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -455,6 +552,7 @@ uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -546,6 +644,7 @@ uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { int dest_reg = fetchdat & 7; @@ -633,13 +732,15 @@ uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 int src_reg = (fetchdat >> 3) & 7; uint8_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); } imm = fastreadb(cs + op_pc + 1) & 0x1f; - + codegen_mark_code_present(block, cs+op_pc+1, 1); + if (!imm) return op_pc+2; @@ -670,6 +771,7 @@ uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); } + return op_pc+2; } uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -678,13 +780,15 @@ uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 int src_reg = (fetchdat >> 3) & 7; uint8_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); } imm = fastreadb(cs + op_pc + 1) & 0x1f; - + codegen_mark_code_present(block, cs+op_pc+1, 1); + if (!imm) return op_pc+2; @@ -715,6 +819,7 @@ uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); } + return op_pc+2; } uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -723,13 +828,15 @@ uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 int src_reg = (fetchdat >> 3) & 7; uint8_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); } imm = fastreadb(cs + op_pc + 1) & 0x1f; - + codegen_mark_code_present(block, cs+op_pc+1, 1); + if (!imm) return op_pc+2; @@ -760,6 +867,7 @@ uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); } + return op_pc+2; } uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -768,13 +876,15 @@ uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 int src_reg = (fetchdat >> 3) & 7; uint8_t imm; + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) != 0xc0) { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); } imm = fastreadb(cs + op_pc + 1) & 0x1f; - + codegen_mark_code_present(block, cs+op_pc+1, 1); + if (!imm) return op_pc+2; @@ -805,5 +915,6 @@ uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MOV_IMM(ir, IREG_flags_op2, imm); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); } + return op_pc+2; } diff --git a/src/codegen_ops_stack.c b/src/codegen_ops_stack.c index 29d2bda..c3c8a46 100644 --- a/src/codegen_ops_stack.c +++ b/src/codegen_ops_stack.c @@ -75,6 +75,7 @@ uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); SUB_SP(ir, 2); + codegen_mark_code_present(block, cs+op_pc, 2); return op_pc + 2; } uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -87,6 +88,7 @@ uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint3 uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); SUB_SP(ir, 4); + codegen_mark_code_present(block, cs+op_pc, 4); return op_pc + 4; } @@ -100,6 +102,7 @@ uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uin uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); SUB_SP(ir, 2); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -112,6 +115,7 @@ uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uin uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); SUB_SP(ir, 4); + codegen_mark_code_present(block, cs+op_pc, 1); return op_pc + 1; } @@ -119,6 +123,7 @@ uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { if (stack32) @@ -154,6 +159,7 @@ uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe { uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) { if (stack32) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 01272bc..6be5cfe 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -167,10 +167,12 @@ enum IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, + IREG_temp3_W = IREG_temp3 + IREG_SIZE_W, IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, IREG_temp2_B = IREG_temp2 + IREG_SIZE_B, + IREG_temp3_B = IREG_temp3 + IREG_SIZE_B, IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, diff --git a/src/mem.c b/src/mem.c index 9c6c536..dd3186d 100644 --- a/src/mem.c +++ b/src/mem.c @@ -46,6 +46,9 @@ int cachesize=256; uint8_t *ram, *rom = NULL; uint8_t romext[32768]; +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; + uint32_t mem_logical_addr; int mmuflush=0; @@ -401,7 +404,7 @@ void addwritelookup(uint32_t virt, uint32_t phys) // if (page_lookup[virt >> 12] && (writelookup2[virt>>12] != 0xffffffff)) // fatal("Bad write mapping\n"); - if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) + if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; else writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; @@ -926,15 +929,23 @@ void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + // pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask, mask); p->mem[addr & 0xfff] = val; - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) { // pclog("ramb add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); } + p->byte_dirty_mask[byte_offset] |= byte_mask; + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + { +// pclog(" ramb add %08x %016llx %016llx\n", addr, p->byte_code_present_mask[byte_offset], byte_mask); + page_add_to_evict_list(p); + } } } void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) @@ -942,13 +953,34 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + if ((addr & 0xf) == 0xf) mask |= (mask << 1); // pclog("mem_write_ramw_page: %08x %04x %08x %016llx %016llx %016llx %08x %08x %p\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask, p->evict_prev, p->evict_next, p); *(uint16_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + { +// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } + if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) + { + p->byte_dirty_mask[byte_offset+1] |= 1; + if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) + { +// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } + } + else + byte_mask |= (byte_mask << 1); + + p->byte_dirty_mask[byte_offset] |= byte_mask; + + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) { // pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); @@ -960,17 +992,31 @@ void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int index = (addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); + if ((addr & 0xf) >= 0xd) mask |= (mask << 1); // pclog("mem_write_raml_page: %08x %08x %08x %016llx %016llx %016llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask); *(uint32_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + p->byte_dirty_mask[byte_offset] |= byte_mask; + if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) { // pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); } + if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) + { + uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); + + p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; + if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) + { +// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask); + page_add_to_evict_list(p); + } + } } } @@ -1082,10 +1128,10 @@ void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); page_t *p = &pages[start_addr >> 12]; - int index = (start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK; + //pclog("mem_invalidate: %08x\n", start_addr); - p->dirty_mask[index] |= mask; - if ((p->code_present_mask[index] & mask) && !page_in_evict_list(p)) + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) { // pclog("invalidate add %08x %016llx %016llx\n", start_addr, p->code_present_mask[index], mask); page_add_to_evict_list(p); @@ -1371,6 +1417,13 @@ void mem_alloc() ram = malloc(mem_size * 1024); memset(ram, 0, mem_size * 1024); + free(byte_dirty_mask); + byte_dirty_mask = malloc((mem_size * 1024) / 8); + memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); + free(byte_code_present_mask); + byte_code_present_mask = malloc((mem_size * 1024) / 8); + memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); + free(pages); pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); @@ -1381,6 +1434,8 @@ void mem_alloc() pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; } memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); @@ -1431,8 +1486,8 @@ void mem_reset_page_blocks() pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; - pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = BLOCK_INVALID; - pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = BLOCK_INVALID; + pages[c].block = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; } } diff --git a/src/mem.h b/src/mem.h index 79d0da4..429973a 100644 --- a/src/mem.h +++ b/src/mem.h @@ -112,6 +112,13 @@ mem_mapping_t bios_high_mapping[8]; extern mem_mapping_t ram_high_mapping; extern mem_mapping_t ram_remapped_mapping; +extern uint64_t *byte_dirty_mask; +extern uint64_t *byte_code_present_mask; + +#define PAGE_BYTE_MASK_SHIFT 6 +#define PAGE_BYTE_MASK_OFFSET_MASK 63 +#define PAGE_BYTE_MASK_MASK 63 + #define EVICT_NOT_IN_LIST ((uint32_t)-1) typedef struct page_t { @@ -121,14 +128,17 @@ typedef struct page_t uint8_t *mem; - uint16_t block[4], block_2[4]; + uint16_t block, block_2; /*Head of codeblock tree associated with this page*/ uint16_t head; - uint64_t code_present_mask[4], dirty_mask[4]; + uint64_t code_present_mask, dirty_mask; uint32_t evict_prev, evict_next; + + uint64_t *byte_dirty_mask; + uint64_t *byte_code_present_mask; } page_t; extern page_t *pages; From cd9e228b6d237e46d130f6d346db72c5ec816ca6 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 16 Mar 2019 15:46:48 +0000 Subject: [PATCH 148/181] Move CODEBLOCK_IN_DIRTY_LIST check to after checking if block needs to be flushed. Improves performance in Eradicator. --- src/386_dynarec.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 2817727..d904612 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -341,14 +341,6 @@ void exec386_dynarec(int cycs) } } - if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) - { - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; - if (block->flags & CODEBLOCK_BYTE_MASK) - block->flags |= CODEBLOCK_NO_IMMEDIATES; - else - block->flags |= CODEBLOCK_BYTE_MASK; - } if (valid_block && (block->page_mask & *block->dirty_mask)) { codegen_check_flush(page, page->dirty_mask, phys_addr); @@ -379,6 +371,14 @@ void exec386_dynarec(int cycs) block->flags &= ~CODEBLOCK_WAS_RECOMPILED; } } + if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) + { + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; + if (block->flags & CODEBLOCK_BYTE_MASK) + block->flags |= CODEBLOCK_NO_IMMEDIATES; + else + block->flags |= CODEBLOCK_BYTE_MASK; + } if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) { /*FPU top-of-stack does not match the value this block was compiled From 4b99070fc066d50bef15fd78d835a1e6b75fee39 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 16 Mar 2019 15:47:49 +0000 Subject: [PATCH 149/181] Flush accumulators before call to non-recompiled instruction. --- src/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.c b/src/codegen.c index 23ea678..5ffa2cc 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -692,7 +692,7 @@ generate_call: #ifdef DEBUG_EXTRA uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); #endif - + codegen_accumulate_flush(ir); if (op_table == x86_dynarec_opcodes_3DNOW) uop_MOV_IMM(ir, IREG_pc, next_pc); else From 52f5f43d82d85fc5f44d36c8bb47eec2e811b3d7 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 22 Mar 2019 20:31:29 +0000 Subject: [PATCH 150/181] Fix PC value following FSTCW/FSTSW. --- src/codegen_ops_fpu_misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen_ops_fpu_misc.c b/src/codegen_ops_fpu_misc.c index 58902ac..2848ba9 100644 --- a/src/codegen_ops_fpu_misc.c +++ b/src/codegen_ops_fpu_misc.c @@ -69,7 +69,7 @@ uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC); - return op_pc; + return op_pc+1; } uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -82,7 +82,7 @@ uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe codegen_check_seg_write(block, ir, target_seg); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS); - return op_pc; + return op_pc+1; } uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { From b35cf7de0976f064d2c8d6a6350262a84b8223a9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 22 Mar 2019 20:31:57 +0000 Subject: [PATCH 151/181] Fix codegen timing flush at end of a block. --- src/codegen_backend.c | 1 + src/codegen_timing_k6.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 0f76cbe..106b896 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -793,6 +793,7 @@ void codegen_block_end() void codegen_block_end_recompile(codeblock_t *block) { codegen_timing_block_end(); + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); if (block->flags & CODEBLOCK_IN_DIRTY_LIST) block_dirty_list_remove(block); diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c index 8499cfa..518a565 100644 --- a/src/codegen_timing_k6.c +++ b/src/codegen_timing_k6.c @@ -2339,7 +2339,11 @@ void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint void codegen_timing_k6_block_end() { if (decode_buffer.nr_uops) + { + int old_last_complete_timestamp = last_complete_timestamp; decode_flush(); + codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); + } } int codegen_timing_k6_jump_cycles() From 7e099c277e1e38ff4f56c4cd7a9eb9cf07a7b1d8 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 25 Mar 2019 19:07:51 +0000 Subject: [PATCH 152/181] Added basic loop unrolling. Blocks that end in a JMP, LOOP or conditional branch to a previous instruction in the block will be unrolled up to 10 times. --- src/codegen_ir.c | 52 ++++ src/codegen_ir.h | 1 + src/codegen_ir_defs.h | 4 + src/codegen_ops_branch.c | 588 +++++++++++++++++++++++++++++--------- src/codegen_ops_helpers.c | 45 +++ src/codegen_ops_helpers.h | 15 + src/codegen_ops_jump.c | 15 +- src/codegen_reg.c | 7 +- src/codegen_reg.h | 15 +- 9 files changed, 594 insertions(+), 148 deletions(-) diff --git a/src/codegen_ir.c b/src/codegen_ir.c index 56d58f7..e3a9377 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -8,19 +8,71 @@ extern int has_ea; static ir_data_t ir_block; +static int codegen_unroll_start, codegen_unroll_count; + ir_data_t *codegen_ir_init() { ir_block.wr_pos = 0; // pclog("codegen_ir_init %04x:%04x\n", CS,cpu_state.pc); + codegen_unroll_count = 0; + return &ir_block; } +void codegen_ir_set_unroll(int count, int start) +{ + codegen_unroll_count = count; + codegen_unroll_start = start; +} + +static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) +{ + uop_t *new_uop = uop_alloc(ir, uop->type); + +// pclog(" uop type %08x\n", uop->type); + if (!ir_reg_is_invalid(uop->src_reg_a)) + new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg); + if (!ir_reg_is_invalid(uop->src_reg_b)) + new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg); + if (!ir_reg_is_invalid(uop->src_reg_c)) + new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg); + if (!ir_reg_is_invalid(uop->dest_reg_a)) + new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos-1); + + new_uop->type = uop->type; + new_uop->imm_data = uop->imm_data; + new_uop->p = uop->p; + new_uop->pc = uop->pc; + + if (uop->jump_dest_uop != -1) + { + new_uop->jump_dest_uop = uop->jump_dest_uop + offset; + } +} + void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) { int jump_target_at_end = -1; int c; + if (codegen_unroll_count) + { + int unroll_count; + int unroll_end = ir->wr_pos; + + for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) + { + int offset = ir->wr_pos - codegen_unroll_start; +// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count); + for (c = codegen_unroll_start; c < unroll_end; c++) + { +// pclog(" Duplicate uop %i\n", c); + duplicate_uop(ir, &ir->uops[c], offset); + } + } + } + codegen_reg_mark_as_required(); codegen_reg_process_dead_list(ir); block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); diff --git a/src/codegen_ir.h b/src/codegen_ir.h index aafeca6..b560256 100644 --- a/src/codegen_ir.h +++ b/src/codegen_ir.h @@ -2,4 +2,5 @@ ir_data_t *codegen_ir_init(); +void codegen_ir_set_unroll(int count, int start); void codegen_ir_compile(ir_data_t *ir, codeblock_t *block); diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 7880c7a..82d0af9 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -336,6 +336,7 @@ typedef struct uop_t int jump_dest_uop; int jump_list_next; void *jump_dest; + uint32_t pc; } uop_t; #define UOP_NR_MAX 4096 @@ -361,6 +362,9 @@ static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type) uop->src_reg_b = invalid_ir_reg; uop->src_reg_c = invalid_ir_reg; + uop->pc = cpu_state.oldpc; + + uop->jump_dest_uop = -1; uop->jump_list_next = -1; if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index 35e5c46..d22093a 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -19,7 +19,7 @@ static int VF_SET_01() return VF_SET() ? 1 : 0; } -static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; @@ -27,7 +27,7 @@ static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) { case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Overflow is always zero*/ - return; + return 0; case FLAGS_SUB8: case FLAGS_DEC8: jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); @@ -50,8 +50,9 @@ static void ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return 0; } -static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; @@ -61,7 +62,7 @@ static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) /*Overflow is always zero*/ uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); - return; + return 0; case FLAGS_SUB8: case FLAGS_DEC8: jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); @@ -84,43 +85,59 @@ static void ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return 0; } -static void ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; + int do_unroll = (CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Carry is always zero*/ - return; + return 0; case FLAGS_SUB8: - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; } -static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; + int do_unroll = (!CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { @@ -128,140 +145,266 @@ static void ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) /*Carry is always zero*/ uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); - return; + return 0; case FLAGS_SUB8: - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; } -static void ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; } else { - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); + return 0; } -void ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; } else { - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } + else + { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); + return 0; } -static void ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop, jump_uop2 = -1; + int do_unroll = ((CF_SET() || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Carry is always zero, so test zero only*/ - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); break; case FLAGS_SUB8: - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + if (do_unroll) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } + else + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } break; } - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); + if (do_unroll) + { + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 1; + } + else + { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; + } } -static void ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop, jump_uop2 = -1; + int do_unroll = ((!CF_SET() && !ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: /*Carry is always zero, so test zero only*/ - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); break; case FLAGS_SUB8: - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + if (do_unroll) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + else + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); + if (do_unroll) + { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } + else + { + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 0; + } } -static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; + int do_unroll = (NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { @@ -273,7 +416,10 @@ static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) case FLAGS_SAR8: case FLAGS_INC8: case FLAGS_DEC8: - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); break; case FLAGS_ZN16: @@ -284,7 +430,10 @@ static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) case FLAGS_SAR16: case FLAGS_INC16: case FLAGS_DEC16: - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); break; case FLAGS_ZN32: @@ -295,22 +444,30 @@ static void ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) case FLAGS_SAR32: case FLAGS_INC32: case FLAGS_DEC32: - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); break; case FLAGS_UNKNOWN: default: uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; } -static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; + int do_unroll = (!NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { @@ -322,7 +479,10 @@ static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) case FLAGS_SAR8: case FLAGS_INC8: case FLAGS_DEC8: - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); break; case FLAGS_ZN16: @@ -333,7 +493,10 @@ static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) case FLAGS_SAR16: case FLAGS_INC16: case FLAGS_DEC16: - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); break; case FLAGS_ZN32: @@ -344,21 +507,28 @@ static void ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) case FLAGS_SAR32: case FLAGS_INC32: case FLAGS_DEC32: - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); break; case FLAGS_UNKNOWN: default: uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; } -static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; @@ -367,8 +537,9 @@ static void ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return 0; } -static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; @@ -377,146 +548,267 @@ static void ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return 0; } -static void ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; + int do_unroll = ((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_ZN8: /*V flag is always clear. Condition is true if N is set*/ - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); break; case FLAGS_ZN16: - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); break; case FLAGS_ZN32: - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); break; case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + if (do_unroll) + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + else + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); + if (do_unroll) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; } -static void ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop; - + int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_ZN8: /*V flag is always clear. Condition is true if N is set*/ - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); break; case FLAGS_ZN16: - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); break; case FLAGS_ZN32: - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); break; case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + if (do_unroll) + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + else + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); + if (do_unroll) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; } -static void ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop, jump_uop2 = -1; + int do_unroll = (((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + if (do_unroll) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + } + else + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + } break; } - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); + if (do_unroll) + { + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 1; + } + else + { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; + } } -static void ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr) +static int ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { int jump_uop, jump_uop2 = -1; + int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && !ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); break; case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); break; case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); break; case FLAGS_UNKNOWN: default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + if (do_unroll) + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + } + else + { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + } break; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); + if (do_unroll) + { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } + else + { + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 0; + } } #define ropJ(cond) \ @@ -524,33 +816,36 @@ uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, u { \ uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); \ uint32_t dest_addr = op_pc + 1 + offset; \ + int ret; \ \ if (!(op_32 & 0x100)) \ dest_addr &= 0xffff; \ - ropJ ## cond ## _common(block, ir, dest_addr); \ + ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+1); \ \ codegen_mark_code_present(block, cs+op_pc, 1); \ - return op_pc+1; \ + return ret ? dest_addr : (op_pc+1); \ } \ uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); \ uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ + int ret; \ \ - ropJ ## cond ## _common(block, ir, dest_addr); \ + ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+2); \ \ codegen_mark_code_present(block, cs+op_pc, 2); \ - return op_pc+2; \ + return ret ? dest_addr : (op_pc+2); \ } \ uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ { \ uint32_t offset = fastreadl(cs + op_pc); \ uint32_t dest_addr = op_pc + 4 + offset; \ + int ret; \ \ - ropJ ## cond ## _common(block, ir, dest_addr); \ + ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+4); \ \ codegen_mark_code_present(block, cs+op_pc, 4); \ - return op_pc+4; \ + return ret ? dest_addr : (op_pc+4); \ } ropJ(O) @@ -596,27 +891,48 @@ uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet { uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); uint32_t dest_addr = op_pc + 1 + offset; + uint32_t ret_addr; int jump_uop; if (!(op_32 & 0x100)) dest_addr &= 0xffff; - if (op_32 & 0x200) + if (((op_32 & 0x200) ? ECX : CX) != 1 && codegen_can_unroll(block, ir, op_pc+1, dest_addr)) { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + if (op_32 & 0x200) + { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); + } + else + { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); + } + uop_MOV_IMM(ir, IREG_pc, op_pc+1); + ret_addr = dest_addr; + CPU_BLOCK_END(); } else { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + if (op_32 & 0x200) + { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } + else + { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + ret_addr = op_pc+1; } - uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; + return ret_addr; } uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) diff --git a/src/codegen_ops_helpers.c b/src/codegen_ops_helpers.c index 8ccd1fb..fdde53b 100644 --- a/src/codegen_ops_helpers.c +++ b/src/codegen_ops_helpers.c @@ -2,6 +2,7 @@ #include "x86.h" #include "386_common.h" #include "codegen.h" +#include "codegen_ir.h" #include "codegen_ir_defs.h" #include "codegen_reg.h" #include "codegen_ops_helpers.h" @@ -24,3 +25,47 @@ void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8); uop_OR(ir, dest_reg, dest_reg, IREG_temp3); } + +#define UNROLL_MAX_REG_REFERENCES 200 +#define UNROLL_MAX_UOPS 1000 +#define UNROLL_MAX_COUNT 10 +int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) +{ + int start; + int max_unroll; + + /*Check that dest instruction was actually compiled into block*/ + for (start = 0; start < ir->wr_pos; start++) + { +// pclog(" uOP %i %08x %08x\n", c, ir->uops[c].pc, dest_addr); + if (ir->uops[start].pc == dest_addr) + break; + if (ir->uops[start].pc > dest_addr) + { +// pclog("Went past dest_addr. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start); + return 0; + } + } + /*Couldn't find any uOPs corresponding to the destination instruction*/ + if (start == ir->wr_pos) + { + /*Is instruction jumping to itself?*/ + if (dest_addr != cpu_state.oldpc) + { +// pclog("Couldn't find start. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start); + return 0; + } + } + + max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6); + if (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount)) + max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount); + if (max_unroll > UNROLL_MAX_COUNT) + max_unroll = UNROLL_MAX_COUNT; + if (max_unroll <= 1) + return 0; + + codegen_ir_set_unroll(max_unroll, start); + + return 1; +} diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h index e1e2bbc..ae3e5ed 100644 --- a/src/codegen_ops_helpers.h +++ b/src/codegen_ops_helpers.h @@ -109,3 +109,18 @@ static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, else uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr)); } + +int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr); +static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) +{ + if (block->flags & CODEBLOCK_BYTE_MASK) + return 0; + + /*Is dest within block?*/ + if (dest_addr > next_pc) + return 0; + if ((cs+dest_addr) < block->pc) + return 0; + + return codegen_can_unroll_full(block, ir, next_pc, dest_addr); +} diff --git a/src/codegen_ops_jump.c b/src/codegen_ops_jump.c index dd417e4..5e4cda4 100644 --- a/src/codegen_ops_jump.c +++ b/src/codegen_ops_jump.c @@ -16,9 +16,10 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f if (!(op_32 & 0x100)) dest_addr &= 0xffff; - uop_MOV_IMM(ir, IREG_pc, dest_addr); + if (offset < 0) + codegen_can_unroll(block, ir, op_pc+1, dest_addr); codegen_mark_code_present(block, cs+op_pc, 1); - return -1; + return dest_addr; } uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -27,18 +28,20 @@ uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t dest_addr &= 0xffff; - uop_MOV_IMM(ir, IREG_pc, dest_addr); + if (offset < 0) + codegen_can_unroll(block, ir, op_pc+1, dest_addr); codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + return dest_addr; } uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { uint32_t offset = fastreadl(cs + op_pc); uint32_t dest_addr = op_pc+4+offset; - uop_MOV_IMM(ir, IREG_pc, dest_addr); + if (offset < 0) + codegen_can_unroll(block, ir, op_pc+1, dest_addr); codegen_mark_code_present(block, cs+op_pc, 4); - return -1; + return dest_addr; } uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) diff --git a/src/codegen_reg.c b/src/codegen_reg.c index dda256c..eb07cfb 100644 --- a/src/codegen_reg.c +++ b/src/codegen_reg.c @@ -4,6 +4,7 @@ #include "codegen_ir_defs.h" #include "codegen_reg.h" +int max_version_refcount; uint16_t reg_dead_list = 0; uint8_t reg_last_version[IREG_COUNT]; @@ -249,11 +250,7 @@ void codegen_reg_reset() } reg_dead_list = 0; -} - -static inline int ir_reg_is_invalid(ir_reg_t ir_reg) -{ - return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); + max_version_refcount = 0; } static inline int ir_get_refcount(ir_reg_t ir_reg) diff --git a/src/codegen_reg.h b/src/codegen_reg.h index 6be5cfe..bd790a9 100644 --- a/src/codegen_reg.h +++ b/src/codegen_reg.h @@ -315,7 +315,10 @@ extern ir_reg_t invalid_ir_reg; typedef uint16_t ir_host_reg_t; +extern int max_version_refcount; + #define REG_VERSION_MAX 250 +#define REG_REFCOUNT_MAX 250 static inline ir_reg_t codegen_reg_read(int reg) { @@ -332,8 +335,10 @@ static inline ir_reg_t codegen_reg_read(int reg) version->refcount++; if (!version->refcount) fatal("codegen_reg_read - refcount overflow\n"); - else if (version->refcount > REG_VERSION_MAX) + else if (version->refcount > REG_REFCOUNT_MAX) CPU_BLOCK_END(); + if (version->refcount > max_version_refcount) + max_version_refcount = version->refcount; // pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]); return ireg; } @@ -359,6 +364,9 @@ static inline ir_reg_t codegen_reg_write(int reg, int uop_nr) fatal("codegen_reg_write - version overflow\n"); else if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) CPU_BLOCK_END(); + if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount) + max_version_refcount = reg_last_version[IREG_GET_REG(reg)]; + version = ®_version[IREG_GET_REG(reg)][ireg.version]; version->refcount = 0; version->flags = 0; @@ -367,6 +375,11 @@ static inline ir_reg_t codegen_reg_write(int reg, int uop_nr) return ireg; } +static inline int ir_reg_is_invalid(ir_reg_t ir_reg) +{ + return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); +} + struct ir_data_t; void codegen_reg_reset(); From 61722f120c27bd2027b0e1c566e807a095f721ae Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 25 Mar 2019 19:59:46 +0000 Subject: [PATCH 153/181] Fix block mask calculation. Fixes rendering errors in Blood. --- src/codegen_backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 106b896..8239e94 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -826,7 +826,7 @@ void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, if (block->flags & CODEBLOCK_BYTE_MASK) { uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK; - uint32_t end_pc_masked = start_pc & PAGE_MASK_MASK; + uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK; if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/ { From 56a01a0e04e18656a8402c5d4b35b935382b3b04 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 26 Mar 2019 22:02:00 +0000 Subject: [PATCH 154/181] Provide dummy timing for unknown (usually illegal) opcodes in K6 timing code. --- src/codegen_timing_k6.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c index 518a565..5d5aa8e 100644 --- a/src/codegen_timing_k6.c +++ b/src/codegen_timing_k6.c @@ -2330,9 +2330,10 @@ void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint } } - if (!ins_table[opcode]) - fatal("!ins_table opcode=%02x last_prefix=%02x\n", opcode, last_prefix); - decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); + if (ins_table[opcode]) + decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); + else + decode_instruction(&vector_alu1_op, 0, fetchdat, op_32, bit8); codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); } From efef231d7d7e1245d1bf40cd1def071e037b69b9 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 28 Mar 2019 20:37:55 +0000 Subject: [PATCH 155/181] Restore correct CS value when aborting in stack operations in CALL far instructions. --- src/x86_ops_call.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/x86_ops_call.h b/src/x86_ops_call.h index 4c2e117..8b6087d 100644 --- a/src/x86_ops_call.h +++ b/src/x86_ops_call.h @@ -16,14 +16,14 @@ if (cgate32) \ { \ uint32_t old_esp = ESP; \ - PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ + PUSH_L(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ + PUSH_L(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ } \ else \ { \ uint32_t old_esp = ESP; \ - PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ + PUSH_W(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ + PUSH_W(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ } #define CALL_FAR_l(new_seg, new_pc) \ @@ -44,14 +44,14 @@ if (cgate16) \ { \ uint32_t old_esp = ESP; \ - PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ + PUSH_W(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ + PUSH_W(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ } \ else \ { \ uint32_t old_esp = ESP; \ - PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ + PUSH_L(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ + PUSH_L(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ } From b77bce1efd874b84caf4ebc458188ce22c0e57aa Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 28 Mar 2019 20:38:33 +0000 Subject: [PATCH 156/181] Clear page_mask2 when the second page in a block is inaccessible. --- src/codegen_backend.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 8239e94..19e32f6 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -704,6 +704,13 @@ void codegen_block_generate_end_mask_recompile() fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); } } + else + { + /*Second page not present. page_mask2 is most likely set only because + the recompiler didn't know how long the last instruction was, so + clear it*/ + block->page_mask2 = 0; + } } // pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask); @@ -776,6 +783,13 @@ void codegen_block_generate_end_mask_mark() block->dirty_mask2 = &page_2->dirty_mask; } + else + { + /*Second page not present. page_mask2 is most likely set only because + the recompiler didn't know how long the last instruction was, so + clear it*/ + block->page_mask2 = 0; + } } // pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask); From 8b197e22da0e6353f43847931ce1528cb419514a Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 29 Mar 2019 21:06:01 +0000 Subject: [PATCH 157/181] Improved interpreter implementations of ROL and ROR. --- src/x86_ops_shift.h | 109 +++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 71 deletions(-) diff --git a/src/x86_ops_shift.h b/src/x86_ops_shift.h index 1a31316..c248593 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -6,31 +6,20 @@ switch (rmdat & 0x38) \ { \ case 0x00: /*ROL b, c*/ \ - while (c > 0) \ - { \ - temp2 = (temp & 0x80) ? 1 : 0; \ - temp = (temp << 1) | temp2; \ - c--; \ - } \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \ + temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \ + seteab(temp); if (cpu_state.abrt) return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 1) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 7)) & 1) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR b,CL*/ \ - while (c > 0) \ - { \ - temp2 = temp & 1; \ - temp >>= 1; \ - if (temp2) temp |= 0x80; \ - c--; \ - } \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ + temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \ + seteab(temp); if (cpu_state.abrt) return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 0x80) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -98,32 +87,21 @@ switch (rmdat & 0x38) \ { \ case 0x00: /*ROL w, c*/ \ - while (c > 0) \ - { \ - temp2 = (temp & 0x8000) ? 1 : 0; \ - temp = (temp << 1) | temp2; \ - c--; \ - } \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \ + seteaw(temp); if (cpu_state.abrt) return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 1) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 15)) & 1) cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ - case 0x08: /*ROR w, c*/ \ - while (c > 0) \ - { \ - temp2 = temp & 1; \ - temp >>= 1; \ - if (temp2) temp |= 0x8000; \ - c--; \ - } \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + case 0x08: /*ROR w,CL*/ \ + temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \ + seteaw(temp); if (cpu_state.abrt) return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 0x8000) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x10: /*RCL w, c*/ \ @@ -190,33 +168,22 @@ switch (rmdat & 0x38) \ { \ case 0x00: /*ROL l, c*/ \ - while (c > 0) \ - { \ - temp2 = (temp & 0x80000000) ? 1 : 0; \ - temp = (temp << 1) | temp2; \ - c--; \ - } \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ + temp = (temp << c) | (temp >> (32-c)); \ + seteal(temp); if (cpu_state.abrt) return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 1) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 31)) & 1) cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ - case 0x08: /*ROR l, c*/ \ - while (c > 0) \ - { \ - temp2 = temp & 1; \ - temp >>= 1; \ - if (temp2) temp |= 0x80000000; \ - c--; \ - } \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ + case 0x08: /*ROR l,CL*/ \ + temp = (temp >> c) | (temp << (32-c)); \ + seteal(temp); if (cpu_state.abrt) return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 0x80000000) cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x10: /*RCL l, c*/ \ temp2 = CF_SET(); \ From e2a1ae696f954286cbc53c507f51aed938803446 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 30 Mar 2019 14:41:02 +0000 Subject: [PATCH 158/181] Added lazy flags for ROL and ROR. --- src/codegen_ops_branch.c | 12 +++---- src/x86_flags.h | 73 +++++++++++++++++++++++++++++++++++++++- src/x86_ops_shift.h | 26 ++++---------- 3 files changed, 85 insertions(+), 26 deletions(-) diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index d22093a..e41b9ee 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -189,7 +189,7 @@ static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, u if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); @@ -205,7 +205,7 @@ static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, u } else { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); @@ -226,7 +226,7 @@ int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_ if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); @@ -242,7 +242,7 @@ int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_ } else { - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); @@ -954,7 +954,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); @@ -990,7 +990,7 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } - if (!codegen_flags_changed || (cpu_state.flags_op == FLAGS_UNKNOWN)) + if (!codegen_flags_changed || !flags_res_valid()) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); diff --git a/src/x86_flags.h b/src/x86_flags.h index 4332fad..49170f3 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -28,6 +28,14 @@ enum FLAGS_SAR16, FLAGS_SAR32, + FLAGS_ROL8, + FLAGS_ROL16, + FLAGS_ROL32, + + FLAGS_ROR8, + FLAGS_ROR16, + FLAGS_ROR32, + FLAGS_INC8, FLAGS_INC16, FLAGS_INC32, @@ -81,6 +89,12 @@ static inline int ZF_SET() case FLAGS_SBC32: return !cpu_state.flags_res; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & Z_FLAG; } @@ -127,6 +141,12 @@ static inline int NF_SET() case FLAGS_SBC32: return cpu_state.flags_res & 0x80000000; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & N_FLAG; } @@ -169,6 +189,12 @@ static inline int PF_SET() case FLAGS_SBC32: return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & P_FLAG; } @@ -226,7 +252,21 @@ static inline int VF_SET() return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000)); case FLAGS_SHR32: return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000)); - + + case FLAGS_ROL8: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 7)) & 1; + case FLAGS_ROL16: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 15)) & 1; + case FLAGS_ROL32: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 31)) & 1; + + case FLAGS_ROR8: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40; + case FLAGS_ROR16: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x4000; + case FLAGS_ROR32: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40000000; + case FLAGS_UNKNOWN: return cpu_state.flags & V_FLAG; } @@ -283,6 +323,12 @@ static inline int AF_SET() return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) || ((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0); + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: return cpu_state.flags & A_FLAG; } @@ -344,6 +390,18 @@ static inline int CF_SET() case FLAGS_ZN16: case FLAGS_ZN32: return 0; + + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + return cpu_state.flags_res & 1; + + case FLAGS_ROR8: + return (cpu_state.flags_res & 0x80) ? 1 : 0; + case FLAGS_ROR16: + return (cpu_state.flags_res & 0x8000) ? 1 :0; + case FLAGS_ROR32: + return (cpu_state.flags_res & 0x80000000) ? 1 : 0; case FLAGS_DEC8: case FLAGS_DEC16: @@ -396,6 +454,15 @@ static inline void flags_rebuild_c() } } +static inline int flags_res_valid() +{ + if (cpu_state.flags_op == FLAGS_UNKNOWN || + (cpu_state.flags_op >= FLAGS_ROL8 && cpu_state.flags_op <= FLAGS_ROR32)) + return 0; + + return 1; +} + static inline void setznp8(uint8_t val) { cpu_state.flags_op = FLAGS_ZN8; @@ -418,6 +485,10 @@ static inline void setznp32(uint32_t val) cpu_state.flags_op1 = orig; \ cpu_state.flags_op2 = shift; +#define set_flags_rotate(op, res) \ + cpu_state.flags_op = op; \ + cpu_state.flags_res = res; + static inline void setadd8(uint8_t a, uint8_t b) { cpu_state.flags_op1 = a; diff --git a/src/x86_ops_shift.h b/src/x86_ops_shift.h index c248593..0d6d193 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -8,18 +8,14 @@ case 0x00: /*ROL b, c*/ \ temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \ seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 7)) & 1) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROL8, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR b,CL*/ \ temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x80) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ + seteab(temp); if (cpu_state.abrt) return 1; \ + set_flags_rotate(FLAGS_ROR8, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -89,18 +85,14 @@ case 0x00: /*ROL w, c*/ \ temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \ seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 15)) & 1) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROL16, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR w,CL*/ \ temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \ seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x8000) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROR16, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ @@ -170,18 +162,14 @@ case 0x00: /*ROL l, c*/ \ temp = (temp << c) | (temp >> (32-c)); \ seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 31)) & 1) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROL32, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR l,CL*/ \ temp = (temp >> c) | (temp << (32-c)); \ seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x80000000) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ + set_flags_rotate(FLAGS_ROR32, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ From e8f39da4591d78b6682edb41555cae8e000b1d1e Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 30 Mar 2019 16:10:00 +0000 Subject: [PATCH 159/181] Add recompiled versions of ROL and ROR. --- src/codegen_backend_x86-64_ops.c | 90 ++++++++++++ src/codegen_backend_x86-64_ops.h | 16 +++ src/codegen_backend_x86-64_uops.c | 123 ++++++++++++++++ src/codegen_backend_x86_ops.c | 66 +++++++++ src/codegen_backend_x86_ops.h | 16 +++ src/codegen_backend_x86_uops.c | 123 ++++++++++++++++ src/codegen_ir_defs.h | 12 ++ src/codegen_ops_shift.c | 228 ++++++++++++++++++++++++++++-- 8 files changed, 665 insertions(+), 9 deletions(-) diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index cd634bd..48acb73 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -15,6 +15,8 @@ #define RM_OP_XOR 0x30 #define RM_OP_CMP 0x38 +#define RM_OP_ROL 0x00 +#define RM_OP_ROR 0x08 #define RM_OP_SHL 0x20 #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 @@ -1263,6 +1265,94 @@ void host_x86_RET(codeblock_t *block) codegen_addbyte(block, 0xc3); /*RET*/ } +void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL8 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL16 CL & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL32 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} + +void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL8 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL16 imm & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR8 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR16 CL & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR32 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} + +void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR8 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR16 imm & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR32 im & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) { if (dst_reg & 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 8d0c07a..3cd86fb 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -130,6 +130,22 @@ void host_x86_PUSH(codeblock_t *block, int src_reg); void host_x86_RET(codeblock_t *block); +void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_ROL8_CL(codeblock_t *block, int dst_reg); +void host_x86_ROL16_CL(codeblock_t *block, int dst_reg); +void host_x86_ROL32_CL(codeblock_t *block, int dst_reg); + +void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_ROR8_CL(codeblock_t *block, int dst_reg); +void host_x86_ROR16_CL(codeblock_t *block, int dst_reg); +void host_x86_ROR32_CL(codeblock_t *block, int dst_reg); + void host_x86_SAR8_CL(codeblock_t *block, int dst_reg); void host_x86_SAR16_CL(codeblock_t *block, int dst_reg); void host_x86_SAR32_CL(codeblock_t *block, int dst_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index d0768a2..8c35559 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -2333,6 +2333,125 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_CL(block, dest_reg); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} +static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} +static int codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_CL(block, dest_reg); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} +static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2758,6 +2877,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_ROL & UOP_MASK] = codegen_ROL, + [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, + [UOP_ROR & UOP_MASK] = codegen_ROR, + [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index f6a9bda..41ab522 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -15,6 +15,8 @@ #define RM_OP_XOR 0x30 #define RM_OP_CMP 0x38 +#define RM_OP_ROL 0x00 +#define RM_OP_ROR 0x08 #define RM_OP_SHL 0x20 #define RM_OP_SHR 0x28 #define RM_OP_SAR 0x38 @@ -953,6 +955,70 @@ void host_x86_RET(codeblock_t *block) codegen_addbyte(block, 0xc3); /*RET*/ } +void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} + +void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} + +void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + #define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index 1ef8df8..94f526c 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -129,6 +129,22 @@ void host_x86_PUSH(codeblock_t *block, int src_reg); void host_x86_RET(codeblock_t *block); +void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_ROL8_CL(codeblock_t *block, int dst_reg); +void host_x86_ROL16_CL(codeblock_t *block, int dst_reg); +void host_x86_ROL32_CL(codeblock_t *block, int dst_reg); + +void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift); + +void host_x86_ROR8_CL(codeblock_t *block, int dst_reg); +void host_x86_ROR16_CL(codeblock_t *block, int dst_reg); +void host_x86_ROR32_CL(codeblock_t *block, int dst_reg); + void host_x86_SAR8_CL(codeblock_t *block, int dst_reg); void host_x86_SAR16_CL(codeblock_t *block, int dst_reg); void host_x86_SAR32_CL(codeblock_t *block, int dst_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 096497c..91e80d9 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -2329,6 +2329,125 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_CL(block, dest_reg); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} +static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} +static int codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_CL(block, dest_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_CL(block, dest_reg); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_CL(block, dest_reg); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} +static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); + } +#ifdef RECOMPILER_DEBUG + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2757,6 +2876,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_ROL & UOP_MASK] = codegen_ROL, + [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, + [UOP_ROR & UOP_MASK] = codegen_ROR, + [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 82d0af9..1cecf9e 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -148,6 +148,14 @@ #define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54) /*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/ #define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) +/*UOP_ROL - dest_reg = src_reg_a rotate<< src_reg_b*/ +#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56) +/*UOP_ROL_IMM - dest_reg = src_reg_a rotate<< immediate*/ +#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57) +/*UOP_ROR - dest_reg = src_reg_a rotate>> src_reg_b*/ +#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58) +/*UOP_ROR_IMM - dest_reg = src_reg_a rotate>> immediate*/ +#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59) /*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/ #define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) @@ -616,6 +624,10 @@ static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, in #define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm) #define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) #define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) +#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg) +#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm) +#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg) +#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm) #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) diff --git a/src/codegen_ops_shift.c b/src/codegen_ops_shift.c index 7410d4d..4e8a97b 100644 --- a/src/codegen_ops_shift.c +++ b/src/codegen_ops_shift.c @@ -18,6 +18,20 @@ static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); @@ -50,6 +64,22 @@ static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, { switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); @@ -94,6 +124,20 @@ static uint32_t shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); @@ -126,6 +170,22 @@ static uint32_t shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc { switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); @@ -169,6 +229,20 @@ static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); @@ -201,6 +275,22 @@ static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc { switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); @@ -245,6 +335,20 @@ static uint32_t shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint3 switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); @@ -277,6 +381,22 @@ static uint32_t shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint3 { switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); @@ -318,7 +438,7 @@ uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch x86seg *target_seg = NULL; uint8_t imm; - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; codegen_mark_code_present(block, cs+op_pc, 1); @@ -341,7 +461,7 @@ uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet x86seg *target_seg = NULL; uint8_t imm; - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; codegen_mark_code_present(block, cs+op_pc, 1); @@ -363,7 +483,7 @@ uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet { x86seg *target_seg = NULL; - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; codegen_mark_code_present(block, cs+op_pc, 1); @@ -398,7 +518,7 @@ uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch { x86seg *target_seg = NULL; - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; codegen_mark_code_present(block, cs+op_pc, 1); @@ -416,7 +536,7 @@ uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet { x86seg *target_seg = NULL; - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; codegen_mark_code_present(block, cs+op_pc, 1); @@ -434,7 +554,7 @@ uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet { x86seg *target_seg = NULL; - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; codegen_mark_code_present(block, cs+op_pc, 1); @@ -451,7 +571,7 @@ uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; if (!(CL & 0x1f) || !block->ins) @@ -467,6 +587,20 @@ uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); @@ -506,6 +640,22 @@ uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); @@ -543,7 +693,7 @@ uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetch } uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; if (!(CL & 0x1f) || !block->ins) @@ -559,6 +709,20 @@ uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); @@ -598,6 +762,22 @@ uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); @@ -635,7 +815,7 @@ uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (!(fetchdat & 0x20)) /*ROL/ROR/RCL/RCR*/ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ return 0; if (!(CL & 0x1f) || !block->ins) @@ -651,6 +831,20 @@ uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + case 0x20: case 0x30: /*SHL*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); @@ -690,6 +884,22 @@ uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + case 0x20: case 0x30: /*SHL*/ uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); From 12d73e8a95eb8f611e3ddaa66e4922295b65bee4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 30 Mar 2019 19:45:29 +0000 Subject: [PATCH 160/181] Fix zero sized recompiled shifts. Fixes hang in Gunmetal. --- src/codegen_backend_x86-64_uops.c | 9 ++++++++- src/codegen_backend_x86_uops.c | 7 +++++++ src/codegen_ir_defs.h | 3 +++ src/codegen_ops_shift.c | 11 ++++++++--- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 8c35559..729e4fd 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1455,6 +1455,11 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2979,7 +2984,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 91e80d9..c09512e 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1451,6 +1451,11 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2980,6 +2985,8 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP, + #ifdef DEBUG_EXTRA [UOP_LOG_INSTR & UOP_MASK] = codegen_LOG_INSTR #endif diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 1cecf9e..76f4979 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -54,6 +54,7 @@ #define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) /*UOP_JMP_DEST - jump to ptr*/ #define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18) #ifdef DEBUG_EXTRA /*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/ @@ -699,6 +700,8 @@ static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, in #define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/) #define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) +#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir) + #define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b) diff --git a/src/codegen_ops_shift.c b/src/codegen_ops_shift.c index 4e8a97b..0d19f40 100644 --- a/src/codegen_ops_shift.c +++ b/src/codegen_ops_shift.c @@ -496,12 +496,17 @@ uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet } if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uint32_t new_pc; + int jump_uop; + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1); - uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp2, 0); - return shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; + new_pc = shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + return new_pc; } else { From 78572ba468f638fee31a48a3a6d782eaa3e51b49 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 30 Mar 2019 21:01:20 +0000 Subject: [PATCH 161/181] Added register barriers to LOOPE and LOOPNE. Fixes crash in Age of Empires II. --- src/codegen_ops_branch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen_ops_branch.c b/src/codegen_ops_branch.c index e41b9ee..ea9b986 100644 --- a/src/codegen_ops_branch.c +++ b/src/codegen_ops_branch.c @@ -965,6 +965,7 @@ uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe } uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); + uop_NOP_BARRIER(ir); uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); @@ -1001,6 +1002,7 @@ uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f } uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); + uop_NOP_BARRIER(ir); uop_set_jump_dest(ir, jump_uop); uop_set_jump_dest(ir, jump_uop2); From e3d5309e237f587c85604c9548a77a2979fa4025 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 31 Mar 2019 11:29:07 +0100 Subject: [PATCH 162/181] Added SST 39SF010 flash for VA-503+. --- src/Makefile.am | 2 +- src/Makefile.mingw-wx-sdl2 | 2 +- src/model.c | 2 + src/sst39sf010.c | 218 +++++++++++++++++++++++++++++++++++++ src/sst39sf010.h | 1 + 5 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 src/sst39sf010.c create mode 100644 src/sst39sf010.h diff --git a/src/Makefile.am b/src/Makefile.am index 9b2795b..7d2b106 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,7 +33,7 @@ laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xe opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \ serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c sound_emu8k.c sound_gus.c \ sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ -sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c \ +sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c sst39sf010.c tandy_eeprom.c tandy_rom.c \ t1000.c t3100e.c \ timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \ vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 435aaf5..8414549 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -29,7 +29,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer38 sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ - sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ + sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \ vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \ vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ diff --git a/src/model.c b/src/model.c index d060d67..bed454f 100644 --- a/src/model.c +++ b/src/model.c @@ -56,6 +56,7 @@ #include "sound_ps1.h" #include "sound_pssj.h" #include "sound_sn76489.h" +#include "sst39sf010.h" #include "tandy_eeprom.h" #include "tandy_rom.h" #include "um8669f.h" @@ -675,6 +676,7 @@ void at_mvp3_init() mvp3_init(); vt82c586b_init(7, 8, 9, 10, 0); w83877tf_init(); + device_add(&sst_39sf010_device); } void model_init() diff --git a/src/sst39sf010.c b/src/sst39sf010.c new file mode 100644 index 0000000..57969b4 --- /dev/null +++ b/src/sst39sf010.c @@ -0,0 +1,218 @@ +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "sst39sf010.h" + +typedef struct sst_t +{ + int command_state; + int id_mode; + int erase; + int dirty; + + char flash_path[1024]; +} sst_t; + +#define SST_CHIP_ERASE 0x10 +#define SST_SECTOR_ERASE 0x30 +#define SST_ERASE 0x80 +#define SST_SET_ID_MODE 0x90 +#define SST_BYTE_PROGRAM 0xa0 +#define SST_CLEAR_ID_MODE 0xf0 + +static void set_id_mode(sst_t *sst); +static void clear_id_mode(sst_t *sst); + +static void sst_new_command(sst_t *sst, uint8_t val) +{ + switch (val) + { + case SST_CHIP_ERASE: + if (sst->erase) + memset(rom, 0xff, 0x20000); + sst->command_state = 0; + sst->erase = 0; + break; + + case SST_ERASE: + sst->command_state = 0; + sst->erase = 1; + break; + + case SST_SET_ID_MODE: + if (!sst->id_mode) + set_id_mode(sst); + sst->command_state = 0; + sst->erase = 0; + break; + + case SST_BYTE_PROGRAM: + sst->command_state = 3; + sst->erase = 0; + break; + + case SST_CLEAR_ID_MODE: + if (sst->id_mode) + clear_id_mode(sst); + sst->command_state = 0; + sst->erase = 0; + break; + + default: + sst->command_state = 0; + sst->erase = 0; + } +} + +static void sst_sector_erase(sst_t *sst, uint32_t addr) +{ +// pclog("SST sector erase %08x\n", addr); + memset(&rom[addr & 0x1f000], 0xff, 4096); + sst->dirty = 1; +} + +static uint8_t sst_read_id(uint32_t addr, void *p) +{ + if ((addr & 0xffff) == 0) + return 0xbf; /*SST*/ + else if ((addr & 0xffff) == 1) + return 0xb5; /*39SF010*/ + else + return 0xff; +// fatal("sst_read_id: addr=%08x\n", addr); +} + +static void sst_write(uint32_t addr, uint8_t val, void *p) +{ + sst_t *sst = (sst_t *)p; + +// pclog("sst_write: addr=%08x val=%02x state=%i\n", addr, val, sst->command_state); + switch (sst->command_state) + { + case 0: + if (val == 0xf0) + { + if (sst->id_mode) + clear_id_mode(sst); + } + else if ((addr & 0xffff) == 0x5555 && val == 0xaa) + sst->command_state = 1; + else + sst->command_state = 0; + break; + case 1: + if ((addr & 0xffff) == 0x2aaa && val == 0x55) + sst->command_state = 2; + else + sst->command_state = 0; + break; + case 2: + if ((addr & 0xffff) == 0x5555) + sst_new_command(sst, val); + else if (val == SST_SECTOR_ERASE && sst->erase) + { + sst_sector_erase(sst, addr); + sst->command_state = 0; + } + else + sst->command_state = 0; + break; + case 3: +// pclog("Byte program %08x %02x\n", addr, val); + rom[addr & 0x1ffff] = val; + sst->command_state = 0; + sst->dirty = 1; + break; + } +} + +static void set_id_mode(sst_t *sst) +{ + int c; + + for (c = 0; c < 8; c++) + { + mem_mapping_set_handler(&bios_mapping[c], + sst_read_id, NULL, NULL, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_mapping[c], sst); + mem_mapping_set_handler(&bios_high_mapping[c], + sst_read_id, NULL, NULL, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_high_mapping[c], sst); + } + sst->id_mode = 1; +} + +static void clear_id_mode(sst_t *sst) +{ + int c; + + for (c = 0; c < 8; c++) + { + mem_mapping_set_handler(&bios_mapping[c], + mem_read_bios, mem_read_biosw, mem_read_biosl, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_mapping[c], sst); + mem_mapping_set_handler(&bios_high_mapping[c], + mem_read_bios, mem_read_biosw, mem_read_biosl, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_high_mapping[c], sst); + } + sst->id_mode = 0; +} + +static void *sst_39sf010_init() +{ + FILE *f; + sst_t *sst = malloc(sizeof(sst_t)); + memset(sst, 0, sizeof(sst_t)); + + switch(romset) + { + case ROM_FIC_VA503P: + strcpy(sst->flash_path, "fic_va503p/"); + break; + default: + fatal("sst_39sf010_init on unsupported ROM set %i\n", romset); + } + strcat(sst->flash_path, "flash.bin"); + f = romfopen(sst->flash_path, "rb"); + if (f) + { + fread(rom, 0x20000, 1, f); + fclose(f); + } + + clear_id_mode(sst); + + return sst; +} + +static void sst_39sf010_close(void *p) +{ + sst_t *sst = (sst_t *)p; + + if (sst->dirty) + { + FILE *f = romfopen(sst->flash_path, "wb"); + fwrite(rom, 0x20000, 1, f); + fclose(f); + } + + free(sst); +} + +device_t sst_39sf010_device = +{ + "SST 39SF010 Flash BIOS", + 0, + sst_39sf010_init, + sst_39sf010_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/sst39sf010.h b/src/sst39sf010.h new file mode 100644 index 0000000..97d4a63 --- /dev/null +++ b/src/sst39sf010.h @@ -0,0 +1 @@ +extern device_t sst_39sf010_device; From 584e67845beb50ea932f9f8163cf82e74976139b Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 31 Mar 2019 18:21:56 +0100 Subject: [PATCH 163/181] Added ROL, ROR and NOP uops to ARM and ARM64 backends. --- src/codegen_backend_arm64_ops.c | 11 ++ src/codegen_backend_arm64_ops.h | 3 + src/codegen_backend_arm64_uops.c | 232 ++++++++++++++++++++++++++++++- src/codegen_backend_arm_ops.c | 29 ++++ src/codegen_backend_arm_ops.h | 4 + src/codegen_backend_arm_uops.c | 227 +++++++++++++++++++++++++++++- 6 files changed, 504 insertions(+), 2 deletions(-) diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index eaf5089..1bc49c0 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -91,6 +91,7 @@ #define OPCODE_ORR_ASR (0x154 << 21) #define OPCODE_ORR_LSL (0x150 << 21) #define OPCODE_ORR_LSR (0x152 << 21) +#define OPCODE_ORR_ROR (0x156 << 21) #define OPCODE_ORRX_LSL (0x550 << 21) #define OPCODE_SUB_LSL (0x258 << 21) #define OPCODE_SUB_LSR (0x25a << 21) @@ -164,6 +165,7 @@ #define OPCODE_NOP (0xd503201f) #define OPCODE_ORR_V (0x0ea01c00) #define OPCODE_RET (0xd65f0000) +#define OPCODE_ROR (0x1ac02c00) #define OPCODE_SADDLP_V2S_4H (0x0e602800) #define OPCODE_SCVTF_D_Q (0x9e620000) #define OPCODE_SCVTF_D_W (0x1e620000) @@ -994,6 +996,10 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int { codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } +void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +{ + codegen_addlong(block, OPCODE_ORR_ROR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); +} void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) { @@ -1092,6 +1098,11 @@ void host_arm64_RET(codeblock_t *block, int reg) codegen_addlong(block, OPCODE_RET | Rn(reg)); } +void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +{ + codegen_addlong(block, OPCODE_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); +} + void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) { codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 42760dd..904aa6d 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -143,6 +143,7 @@ void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); +void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift); void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data); void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift); @@ -162,6 +163,8 @@ void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_RET(codeblock_t *block, int reg); +void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg); + void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg); void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 0f56360..d7fe7f6 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1474,6 +1474,11 @@ static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2354,6 +2359,225 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 32); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ROR(block, dest_reg, src_reg, REG_TEMP2); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 16); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_ROR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + cs = cs; + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } + else + { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm64_ROR(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } + else + { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2847,6 +3071,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_ROL & UOP_MASK] = codegen_ROL, + [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, + [UOP_ROR & UOP_MASK] = codegen_ROR, + [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, @@ -2945,7 +3173,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index b6a6142..9be45f2 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -49,6 +49,7 @@ #define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) #define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) #define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +#define OPCODE_RSB_IMM (0x26 << OPCODE_SHIFT) #define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) #define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) #define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) @@ -177,10 +178,12 @@ #define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +#define SHIFT_ROR_IMM(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) #define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) #define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) #define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) +#define SHIFT_ROR_REG(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_REG | Rs(x)) #define BFI_lsb(lsb) ((lsb) << 7) #define BFI_msb(msb) ((msb) << 16) @@ -695,6 +698,14 @@ void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int { codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); } +void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_IMM(shift)); +} +void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_REG(shift_reg)); +} void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { @@ -730,6 +741,24 @@ void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, i codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } +void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +{ + uint32_t arm_imm; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_RSB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } + else + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_RSB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } +} +void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +{ + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); +} void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 3e930df..7627f51 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -89,6 +89,8 @@ void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); +void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg); void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm); void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm); @@ -106,6 +108,8 @@ void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, i #define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) #define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) +void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); +void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 402a7d7..12c2eb9 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1595,6 +1595,11 @@ static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + static int codegen_OR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); @@ -2503,6 +2508,220 @@ static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 32); + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, REG_TEMP2); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 16); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_ROR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } + else + { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } + else + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, shift_reg); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) + { + if (!(uop->imm_data & 31)) + { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } + else + { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); + } + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + if ((uop->imm_data & 15) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } + else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } + else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) + { + if ((uop->imm_data & 7) == 0) + { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } + else + { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_SAR(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); @@ -2997,6 +3216,10 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, [UOP_SHR & UOP_MASK] = codegen_SHR, [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, + [UOP_ROL & UOP_MASK] = codegen_ROL, + [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, + [UOP_ROR & UOP_MASK] = codegen_ROR, + [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, @@ -3095,7 +3318,9 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ + [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP }; void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) From 3890ffdff05596f29837098ec1f8044c59275a2a Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 31 Mar 2019 18:23:21 +0100 Subject: [PATCH 164/181] Fixed multiple definition of REG_SP in ARM64 backend. Fixes build warnings, also fixes Windows 3.x. --- src/codegen_backend_arm64.c | 46 ++++++++++++++++---------------- src/codegen_backend_arm64_defs.h | 2 +- src/codegen_backend_arm64_uops.c | 28 +++++++++---------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index 7497a0b..b85d3f9 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -114,7 +114,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); if (size != 1) host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); if (size == 1) host_arm64_call(block, (uintptr_t)readmembl); else if (size == 2) @@ -130,7 +130,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); else if (size == 8) host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); host_arm64_RET(block, REG_X30); } @@ -183,7 +183,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); if (size != 1) host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); if (size == 4 && is_float) host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); else if (size == 8) @@ -199,7 +199,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) else fatal("build_store_routine - unknown size %i\n", size); codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); host_arm64_RET(block, REG_X30); } @@ -318,12 +318,12 @@ void codegen_backend_init() host_arm64_call(block, x86gpf); codegen_exit_rout = &block_write_data[block_pos]; - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); host_arm64_RET(block, REG_X30); block_write_data = NULL; @@ -349,12 +349,12 @@ void codegen_backend_prologue(codeblock_t *block) /*Entry code*/ - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16); - host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -64); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64); host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state); @@ -362,18 +362,18 @@ void codegen_backend_prologue(codeblock_t *block) { host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); } } void codegen_backend_epilogue(codeblock_t *block) { - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); host_arm64_RET(block, REG_X30); codegen_allocator_clean_blocks(block->head_mem_block); diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h index a265016..2df1e9f 100644 --- a/src/codegen_backend_arm64_defs.h +++ b/src/codegen_backend_arm64_defs.h @@ -97,7 +97,7 @@ #define REG_V30 30 #define REG_V31 31 -#define REG_SP 31 +#define REG_XSP 31 #define REG_ARG0 REG_X0 #define REG_ARG1 REG_X1 diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index d7fe7f6..458025b 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -3222,7 +3222,7 @@ void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) } void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); @@ -3230,7 +3230,7 @@ void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int } void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); @@ -3238,7 +3238,7 @@ void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int } void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); @@ -3282,7 +3282,7 @@ void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) } void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); @@ -3290,7 +3290,7 @@ void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int } void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); @@ -3298,7 +3298,7 @@ void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int } void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); @@ -3316,47 +3316,47 @@ void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { if (in_range12_h(stack_offset)) - host_arm64_LDRH_IMM(block, host_reg, REG_SP, stack_offset); + host_arm64_LDRH_IMM(block, host_reg, REG_XSP, stack_offset); else fatal("codegen_direct_read_32_stack - not in range\n"); } void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { if (in_range12_w(stack_offset)) - host_arm64_LDR_IMM_W(block, host_reg, REG_SP, stack_offset); + host_arm64_LDR_IMM_W(block, host_reg, REG_XSP, stack_offset); else fatal("codegen_direct_read_32_stack - not in range\n"); } void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { if (in_range12_q(stack_offset)) - host_arm64_LDR_IMM_X(block, host_reg, REG_SP, stack_offset); + host_arm64_LDR_IMM_X(block, host_reg, REG_XSP, stack_offset); else fatal("codegen_direct_read_pointer_stack - not in range\n"); } void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm64_LDR_IMM_F64(block, host_reg, REG_SP, stack_offset); + host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm64_LDR_IMM_F64(block, host_reg, REG_SP, stack_offset); + host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { if (in_range12_w(stack_offset)) - host_arm64_STR_IMM_W(block, host_reg, REG_SP, stack_offset); + host_arm64_STR_IMM_W(block, host_reg, REG_XSP, stack_offset); else fatal("codegen_direct_write_32_stack - not in range\n"); } void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm64_STR_IMM_F64(block, host_reg, REG_SP, stack_offset); + host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm64_STR_IMM_F64(block, host_reg, REG_SP, stack_offset); + host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } void codegen_set_jump_dest(codeblock_t *block, void *p) From 7a68bca85f4f5400f19a6a4fbef8aeb28e02f6bf Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 31 Mar 2019 18:23:34 +0100 Subject: [PATCH 165/181] Fixed some ARM64 build warnings. --- src/codegen_backend_arm64.c | 26 +++++++++++++------------- src/codegen_backend_arm64_ops.h | 4 ++++ src/codegen_backend_arm64_uops.c | 2 +- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c index b85d3f9..eb50aa6 100644 --- a/src/codegen_backend_arm64.c +++ b/src/codegen_backend_arm64.c @@ -68,7 +68,7 @@ int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = static void build_load_routine(codeblock_t *block, int size, int is_float) { uint32_t *branch_offset; - uint8_t *misaligned_offset; + uint32_t *misaligned_offset; int offset; /*In - W0 = address @@ -116,13 +116,13 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); if (size == 1) - host_arm64_call(block, (uintptr_t)readmembl); + host_arm64_call(block, (void *)readmembl); else if (size == 2) - host_arm64_call(block, (uintptr_t)readmemwl); + host_arm64_call(block, (void *)readmemwl); else if (size == 4) - host_arm64_call(block, (uintptr_t)readmemll); + host_arm64_call(block, (void *)readmemll); else if (size == 8) - host_arm64_call(block, (uintptr_t)readmemql); + host_arm64_call(block, (void *)readmemql); else fatal("build_load_routine - unknown size %i\n", size); codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); @@ -136,8 +136,8 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) static void build_store_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; int offset; /*In - R0 = address, R1 = data @@ -189,13 +189,13 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) else if (size == 8) host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); if (size == 1) - host_arm64_call(block, (uintptr_t)writemembl); + host_arm64_call(block, (void *)writemembl); else if (size == 2) - host_arm64_call(block, (uintptr_t)writememwl); + host_arm64_call(block, (void *)writememwl); else if (size == 4) - host_arm64_call(block, (uintptr_t)writememll); + host_arm64_call(block, (void *)writememll); else if (size == 8) - host_arm64_call(block, (uintptr_t)writememql); + host_arm64_call(block, (void *)writememql); else fatal("build_store_routine - unknown size %i\n", size); codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); @@ -242,7 +242,7 @@ static void build_fp_round_routine(codeblock_t *block, int is_quad) host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); host_arm64_BR(block, REG_TEMP2); - jump_table = &block_write_data[block_pos]; + jump_table = (uint64_t *)&block_write_data[block_pos]; block_pos += 4*8; jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even @@ -315,7 +315,7 @@ void codegen_backend_init() codegen_gpf_rout = &block_write_data[block_pos]; host_arm64_mov_imm(block, REG_ARG0, 0); host_arm64_mov_imm(block, REG_ARG1, 0); - host_arm64_call(block, x86gpf); + host_arm64_call(block, (void *)x86gpf); codegen_exit_rout = &block_write_data[block_pos]; host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 904aa6d..2a514ed 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -82,6 +82,8 @@ void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg); void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); @@ -112,6 +114,8 @@ void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg); +void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg); + void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 458025b..5a92749 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1396,7 +1396,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { - uint8_t *branch_offset; + uint32_t *branch_offset; /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ host_arm64_FMOV_D_D(block, dest_reg, src_64_reg); From a0ab14f56f3ce36bc2b498a9f603f70ee57f66b1 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 1 Apr 2019 21:23:09 +0100 Subject: [PATCH 166/181] When unrolling a loop, set op_32, ea_seg and ssegs to the correct values at the start of the loop. Fixes mode setting on Bahamas 64 and most likely some other bugs. --- src/codegen.c | 46 +++++++++++++++++++++++++++++++++++++++ src/codegen.h | 2 ++ src/codegen_ir.c | 9 ++++++-- src/codegen_ir.h | 2 +- src/codegen_ops_helpers.c | 20 ++++++----------- 5 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 5ffa2cc..503a6c4 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -13,6 +13,41 @@ #include "codegen_ops.h" #include "codegen_ops_helpers.h" +#define MAX_INSTRUCTION_COUNT 100 + +static struct +{ + uint32_t pc; + int op_ssegs; + x86seg *op_ea_seg; + uint32_t op_32; + int first_uop; +} codegen_instructions[MAX_INSTRUCTION_COUNT]; + +int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction) +{ + int c; + + for (c = 0; c < block->ins; c++) + { + if (codegen_instructions[c].pc == pc) + { + *first_instruction = c; + return codegen_instructions[c].first_uop; + } + } + + *first_instruction = block->ins; + return -1; +} + +void codegen_set_loop_start(ir_data_t *ir, int first_instruction) +{ + uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32); + uop_MOV_PTR(ir, IREG_ea_seg, (void *)codegen_instructions[first_instruction].op_ea_seg); + uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs); +} + int has_ea; codeblock_t *codeblock; @@ -551,6 +586,12 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t } generate_call: + codegen_instructions[block->ins].pc = cpu_state.oldpc; + codegen_instructions[block->ins].op_ssegs = last_op_ssegs; + codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg; + codegen_instructions[block->ins].op_32 = last_op_32; + codegen_instructions[block->ins].first_uop = ir->wr_pos; + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); codegen_accumulate(ACCREG_ins, 1); @@ -646,6 +687,11 @@ generate_call: codegen_endpc = (cs + cpu_state.pc) + 8; + block->ins++; + + if (block->ins >= 50) + CPU_BLOCK_END(); + return; } } diff --git a/src/codegen.h b/src/codegen.h index 9365e44..0f246b3 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -404,6 +404,8 @@ extern int codegen_in_recompile; void codegen_generate_reset(); +int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction); +void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction); #ifdef DEBUG_EXTRA extern uint32_t instr_counts[256*256]; diff --git a/src/codegen_ir.c b/src/codegen_ir.c index e3a9377..d7e6157 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -9,6 +9,7 @@ extern int has_ea; static ir_data_t ir_block; static int codegen_unroll_start, codegen_unroll_count; +static int codegen_unroll_first_instruction; ir_data_t *codegen_ir_init() { @@ -20,10 +21,11 @@ ir_data_t *codegen_ir_init() return &ir_block; } -void codegen_ir_set_unroll(int count, int start) +void codegen_ir_set_unroll(int count, int start, int first_instruction) { codegen_unroll_count = count; codegen_unroll_start = start; + codegen_unroll_first_instruction = first_instruction; } static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) @@ -59,7 +61,10 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) if (codegen_unroll_count) { int unroll_count; - int unroll_end = ir->wr_pos; + int unroll_end; + + codegen_set_loop_start(ir, codegen_unroll_first_instruction); + unroll_end = ir->wr_pos; for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) { diff --git a/src/codegen_ir.h b/src/codegen_ir.h index b560256..6274816 100644 --- a/src/codegen_ir.h +++ b/src/codegen_ir.h @@ -2,5 +2,5 @@ ir_data_t *codegen_ir_init(); -void codegen_ir_set_unroll(int count, int start); +void codegen_ir_set_unroll(int count, int start, int first_instruction); void codegen_ir_compile(ir_data_t *ir, codeblock_t *block); diff --git a/src/codegen_ops_helpers.c b/src/codegen_ops_helpers.c index fdde53b..903a0e5 100644 --- a/src/codegen_ops_helpers.c +++ b/src/codegen_ops_helpers.c @@ -33,21 +33,13 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, { int start; int max_unroll; + int first_instruction; /*Check that dest instruction was actually compiled into block*/ - for (start = 0; start < ir->wr_pos; start++) - { -// pclog(" uOP %i %08x %08x\n", c, ir->uops[c].pc, dest_addr); - if (ir->uops[start].pc == dest_addr) - break; - if (ir->uops[start].pc > dest_addr) - { -// pclog("Went past dest_addr. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start); - return 0; - } - } + start = codegen_get_instruction_uop(block, dest_addr, &first_instruction); + /*Couldn't find any uOPs corresponding to the destination instruction*/ - if (start == ir->wr_pos) + if (start == -1) { /*Is instruction jumping to itself?*/ if (dest_addr != cpu_state.oldpc) @@ -55,6 +47,8 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, // pclog("Couldn't find start. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start); return 0; } + else + start = ir->wr_pos; } max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6); @@ -65,7 +59,7 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, if (max_unroll <= 1) return 0; - codegen_ir_set_unroll(max_unroll, start); + codegen_ir_set_unroll(max_unroll, start, first_instruction); return 1; } From 7f99cb7fb17bf52eb12f6e54d0e6464926c51eff Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 1 Apr 2019 21:24:32 +0100 Subject: [PATCH 167/181] Use correct value for MAX_INSTRUCTION_COUNT. --- src/codegen.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 503a6c4..ba33e47 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -13,7 +13,7 @@ #include "codegen_ops.h" #include "codegen_ops_helpers.h" -#define MAX_INSTRUCTION_COUNT 100 +#define MAX_INSTRUCTION_COUNT 50 static struct { @@ -689,7 +689,7 @@ generate_call: block->ins++; - if (block->ins >= 50) + if (block->ins >= MAX_INSTRUCTION_COUNT) CPU_BLOCK_END(); return; @@ -761,7 +761,7 @@ generate_call: block->ins++; - if (block->ins >= 50) + if (block->ins >= MAX_INSTRUCTION_COUNT) CPU_BLOCK_END(); codegen_endpc = (cs + cpu_state.pc) + 8; From 8a91051e25b958c5d2111aa231d17411a6c9694f Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 1 Apr 2019 21:38:21 +0100 Subject: [PATCH 168/181] SST flash now keeps local copy of flash data to write back on device close. Prevents flash corruption when switching models and PCem loads the new BIOS before writing out the old flash. --- src/sst39sf010.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sst39sf010.c b/src/sst39sf010.c index 57969b4..8acb664 100644 --- a/src/sst39sf010.c +++ b/src/sst39sf010.c @@ -12,6 +12,7 @@ typedef struct sst_t int dirty; char flash_path[1024]; + uint8_t data[0x20000]; } sst_t; #define SST_CHIP_ERASE 0x10 @@ -30,7 +31,10 @@ static void sst_new_command(sst_t *sst, uint8_t val) { case SST_CHIP_ERASE: if (sst->erase) + { memset(rom, 0xff, 0x20000); + memset(sst->data, 0xff, 0x20000); + } sst->command_state = 0; sst->erase = 0; break; @@ -69,6 +73,7 @@ static void sst_sector_erase(sst_t *sst, uint32_t addr) { // pclog("SST sector erase %08x\n", addr); memset(&rom[addr & 0x1f000], 0xff, 4096); + memset(&sst->data[addr & 0x1f000], 0xff, 4096); sst->dirty = 1; } @@ -121,6 +126,7 @@ static void sst_write(uint32_t addr, uint8_t val, void *p) case 3: // pclog("Byte program %08x %02x\n", addr, val); rom[addr & 0x1ffff] = val; + sst->data[addr & 0x1ffff] = val; sst->command_state = 0; sst->dirty = 1; break; @@ -184,6 +190,7 @@ static void *sst_39sf010_init() fread(rom, 0x20000, 1, f); fclose(f); } + memcpy(sst->data, rom, 0x20000); clear_id_mode(sst); @@ -197,7 +204,7 @@ static void sst_39sf010_close(void *p) if (sst->dirty) { FILE *f = romfopen(sst->flash_path, "wb"); - fwrite(rom, 0x20000, 1, f); + fwrite(sst->data, 0x20000, 1, f); fclose(f); } From fc369826a42b92e6a7abc5aae2d7aaaf57d6c1b4 Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 2 Apr 2019 20:40:40 +0100 Subject: [PATCH 169/181] Fix start address when calculating block size. Fixes rendering issues in Wolfenstein 3D. --- src/386_dynarec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index d904612..eaa2041 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -401,7 +401,7 @@ void exec386_dynarec(int cycs) } else if (valid_block && !cpu_state.abrt) { - uint32_t start_pc = cpu_state.pc; + uint32_t start_pc = cs+cpu_state.pc; const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; cpu_block_end = 0; @@ -447,7 +447,7 @@ void exec386_dynarec(int cycs) will prevent any block from spanning more than 2 pages. In practice this limit will never be hit, as host block size is only 2kB*/ - if ((cpu_state.pc - start_pc) >= max_block_size) + if (((cs+cpu_state.pc) - start_pc) >= max_block_size) CPU_BLOCK_END(); if (trap) @@ -477,7 +477,7 @@ void exec386_dynarec(int cycs) else if (!cpu_state.abrt) { /*Mark block but do not recompile*/ - uint32_t start_pc = cpu_state.pc; + uint32_t start_pc = cs+cpu_state.pc; const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; cpu_block_end = 0; @@ -519,7 +519,7 @@ void exec386_dynarec(int cycs) will prevent any block from spanning more than 2 pages. In practice this limit will never be hit, as host block size is only 2kB*/ - if ((cpu_state.pc - start_pc) >= max_block_size) + if (((cs+cpu_state.pc) - start_pc) >= max_block_size) CPU_BLOCK_END(); if (trap) From b2e236e7204abee57ebc15b61c55a426df20035a Mon Sep 17 00:00:00 2001 From: SarahW Date: Tue, 9 Apr 2019 22:19:39 +0100 Subject: [PATCH 170/181] Mark FINIT as ending a code block. Fixes crash in Armoured Fist II. --- src/x87_ops_misc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 4354cb2..f22d618 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -38,6 +38,7 @@ static int opFINIT(uint32_t fetchdat) cpu_state.TOP = 0; cpu_state.ismmx = 0; CLOCK_CYCLES(17); + CPU_BLOCK_END(); return 0; } From 73c20a723f448182122e0eb5fb05c4a87b3b9729 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 10 Apr 2019 20:28:45 +0100 Subject: [PATCH 171/181] Clear integer registers on CPU reset. Fixes hang on reboot on VA-503+. --- src/808x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/808x.c b/src/808x.c index cba4273..1336727 100644 --- a/src/808x.c +++ b/src/808x.c @@ -630,14 +630,13 @@ void resetx86() idt.base = 0; idt.limit = is386 ? 0x03FF : 0xFFFF; cpu_state.flags=2; + EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; makeznptable(); resetreadlookup(); makemod1table(); FETCHCLEAR(); x87_reset(); cpu_set_edx(); - EAX = 0; - ESP=0; mmu_perm=4; x86seg_reset(); codegen_reset(); @@ -679,6 +678,7 @@ void softresetx86() cpu_state.flags=2; idt.base = 0; idt.limit = is386 ? 0x03FF : 0xFFFF; + EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; x86seg_reset(); x86_was_reset = 1; } From c79074c980b4a69c6facb180b3d0c2e1f5b6b4ef Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 10 Apr 2019 20:31:31 +0100 Subject: [PATCH 172/181] Fix timer bug in AudioPCI. --- src/sound_audiopci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound_audiopci.c b/src/sound_audiopci.c index e9d4ef7..b56b510 100644 --- a/src/sound_audiopci.c +++ b/src/sound_audiopci.c @@ -1224,7 +1224,7 @@ static void es1371_speed_changed(void *p) { es1371_t *es1371 = (es1371_t *)p; - es1371->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); + es1371->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); } void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_nr) From c0a7fcb3432abf49aae18699253d2fe3f66b680c Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 10 Apr 2019 22:05:26 +0100 Subject: [PATCH 173/181] Correct code present mask when using 16-bit addressing. Fixes graphics issues on Windows 9x with VGA 16-colour driver. --- src/codegen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index ba33e47..06f6213 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -121,7 +121,7 @@ void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { - uint32_t old_pc = *op_pc; + uint32_t old_pc = (*op_pc) + 1; // pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat); if (!cpu_mod && cpu_rm == 6) { @@ -182,7 +182,7 @@ static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uin } } - codegen_mark_code_present(ir->block, cs+old_pc, (*op_pc)-old_pc); + codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-old_pc); return op_ea_seg; } From e2cddb8759577daf842ebf6047ff806ca9ce2691 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 10 Apr 2019 22:13:25 +0100 Subject: [PATCH 174/181] Fix Mach64 pixel clock. --- src/vid_ati_mach64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vid_ati_mach64.c b/src/vid_ati_mach64.c index f997892..e38fca3 100644 --- a/src/vid_ati_mach64.c +++ b/src/vid_ati_mach64.c @@ -422,7 +422,7 @@ void mach64_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; svga->rowoffset = (mach64->crtc_off_pitch >> 22); - svga->clock = cpuclock / mach64->ics2595.output_clock; + svga->clock = (cpuclock * (float)(1ull << 32)) / mach64->ics2595.output_clock; svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; svga->linedbl = svga->rowcount = 0; svga->split = 0xffffff; From de177759f77d003f95a52f550305a306c7242400 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 11 Apr 2019 20:58:07 +0100 Subject: [PATCH 175/181] Fix EA calculations on 3DNow PREFETCH instruction --- src/x86_ops_3dnow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86_ops_3dnow.h b/src/x86_ops_3dnow.h index 304943f..9f852d5 100644 --- a/src/x86_ops_3dnow.h +++ b/src/x86_ops_3dnow.h @@ -10,7 +10,7 @@ static int opPREFETCH_a16(uint32_t fetchdat) } static int opPREFETCH_a32(uint32_t fetchdat) { - fetch_ea_16(fetchdat); + fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); CLOCK_CYCLES(1); From 9a49a75eaf599e667d5fd38c4a0cf28c96c12889 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 14 Apr 2019 13:47:20 +0100 Subject: [PATCH 176/181] IDE soft reset should also reset ATAPI devices. Should fix at least some 'Device failed to request command' errors. --- src/ide.c | 2 ++ src/ide_atapi.c | 10 ++++++++++ src/ide_atapi.h | 1 + src/scsi.c | 18 ++++++++++++++++++ src/scsi.h | 2 ++ src/scsi_cd.c | 9 +++++++++ src/scsi_hd.c | 1 + src/scsi_zip.c | 9 +++++++++ 8 files changed, 52 insertions(+) diff --git a/src/ide.c b/src/ide.c index 0cbad14..4e8d5ef 100644 --- a/src/ide.c +++ b/src/ide.c @@ -819,6 +819,7 @@ void callbackide(int ide_board) { ide->cylinder=0xEB14; atapi->stop(); + atapi_reset(&ide->atapi); } if (ide->type == IDE_NONE) { @@ -829,6 +830,7 @@ void callbackide(int ide_board) { ide_other->cylinder=0xEB14; atapi->stop(); + atapi_reset(&ide_other->atapi); } if (ide_other->type == IDE_NONE) { diff --git a/src/ide_atapi.c b/src/ide_atapi.c index 78a648b..0324e9c 100644 --- a/src/ide_atapi.c +++ b/src/ide_atapi.c @@ -563,3 +563,13 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } + +void atapi_reset(atapi_device_t *atapi_dev) +{ + pclog("atapi_reset\n"); + atapi_dev->state = ATAPI_STATE_IDLE; + atapi_dev->command_pos = 0; + atapi_dev->data_read_pos = 0; + atapi_dev->data_write_pos = 0; + scsi_bus_reset(&atapi_dev->bus); +} diff --git a/src/ide_atapi.h b/src/ide_atapi.h index f737090..ab2174c 100644 --- a/src/ide_atapi.h +++ b/src/ide_atapi.h @@ -64,5 +64,6 @@ uint8_t atapi_read_iir(atapi_device_t *atapi_dev); uint8_t atapi_read_drq(atapi_device_t *atapi_dev); void atapi_process_packet(atapi_device_t *atapi_dev); void atapi_set_transfer_granularity(atapi_device_t *atapi_dev, int size); +void atapi_reset(atapi_device_t *atapi_dev); #endif diff --git a/src/scsi.c b/src/scsi.c index df4b8a8..199ac6e 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -374,3 +374,21 @@ void scsi_bus_close(scsi_bus_t *bus) bus->devices[c]->close(bus->device_data[c]); } } + +void scsi_bus_reset(scsi_bus_t *bus) +{ + int c; + + bus->state = STATE_IDLE; + bus->clear_req = 0; + bus->change_state_delay = 0; + bus->new_req_delay = 0; + bus->bus_in = bus->bus_out = 0; + bus->command_pos = 0; + + for (c = 0; c < 8; c++) + { + if (bus->device_data[c] && bus->devices[c]->reset) + bus->devices[c]->reset(bus->device_data[c]); + } +} diff --git a/src/scsi.h b/src/scsi.h index 8791011..cba4a98 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -9,6 +9,7 @@ typedef struct scsi_device_t void *(*init)(struct scsi_bus_t *bus, int id); void *(*atapi_init)(struct scsi_bus_t *bus, int id, struct atapi_device_t *atapi_dev); void (*close)(void *p); + void (*reset)(void *p); void (*start_command)(void *p); int (*command)(uint8_t *cdb, void *p); @@ -106,6 +107,7 @@ int scsi_bus_match(scsi_bus_t *bus, int bus_assert); void scsi_bus_kick(scsi_bus_t *bus); void scsi_bus_init(scsi_bus_t *bus); void scsi_bus_close(scsi_bus_t *bus); +void scsi_bus_reset(scsi_bus_t *bus); void scsi_bus_atapi_init(scsi_bus_t *bus, scsi_device_t *device, int id, struct atapi_device_t *atapi_dev); diff --git a/src/scsi_cd.c b/src/scsi_cd.c index 5abe1f3..48dbdb6 100644 --- a/src/scsi_cd.c +++ b/src/scsi_cd.c @@ -420,6 +420,14 @@ static void scsi_cd_close(void *p) free(data); } +static void scsi_cd_reset(void *p) +{ + scsi_cd_data_t *data = p; + + timer_disable(&data->callback_timer); + data->cmd_pos = CMD_POS_IDLE; +} + static void scsi_cd_illegal(scsi_cd_data_t *data) { atapi_cmd_error(data, KEY_ILLEGAL_REQ, ASC_INVALID_LUN, 0); @@ -1546,6 +1554,7 @@ scsi_device_t scsi_cd = scsi_cd_init, scsi_cd_atapi_init, scsi_cd_close, + scsi_cd_reset, scsi_cd_start_command, scsi_cd_command, diff --git a/src/scsi_hd.c b/src/scsi_hd.c index bf6412e..914f984 100644 --- a/src/scsi_hd.c +++ b/src/scsi_hd.c @@ -816,6 +816,7 @@ scsi_device_t scsi_hd = scsi_hd_init, NULL, scsi_hd_close, + NULL, scsi_hd_start_command, scsi_hd_command, diff --git a/src/scsi_zip.c b/src/scsi_zip.c index 8f81700..51dacb2 100644 --- a/src/scsi_zip.c +++ b/src/scsi_zip.c @@ -218,6 +218,14 @@ static void scsi_zip_close(void *p) zip_data = NULL; } +static void scsi_zip_reset(void *p) +{ + scsi_zip_data *data = p; + + timer_disable(&data->callback_timer); + data->cmd_pos = CMD_POS_IDLE; +} + static int scsi_add_data(uint8_t val, void *p) { scsi_zip_data *data = p; @@ -1195,6 +1203,7 @@ scsi_device_t scsi_zip = scsi_zip_init, scsi_zip_atapi_init, scsi_zip_close, + scsi_zip_reset, scsi_zip_start_command, scsi_zip_command, From f4074eaacd4be4644bbdd7e5c28b305913e54306 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 14 Apr 2019 15:38:13 +0100 Subject: [PATCH 177/181] Add better immediate handling to ARM64 backend. --- src/codegen_backend_arm64.h | 2 + src/codegen_backend_arm64_imm.c | 1330 +++++++++++++++++++++++++++++++ src/codegen_backend_arm64_ops.c | 70 +- 3 files changed, 1350 insertions(+), 52 deletions(-) create mode 100644 src/codegen_backend_arm64_imm.c diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h index 1fb0cfb..3263aa1 100644 --- a/src/codegen_backend_arm64.h +++ b/src/codegen_backend_arm64.h @@ -27,3 +27,5 @@ void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int o void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); + +uint32_t host_arm64_find_imm(uint32_t data); \ No newline at end of file diff --git a/src/codegen_backend_arm64_imm.c b/src/codegen_backend_arm64_imm.c new file mode 100644 index 0000000..0362b71 --- /dev/null +++ b/src/codegen_backend_arm64_imm.c @@ -0,0 +1,1330 @@ +#include +#include + +/*ARM64 logical instructions have an 'interesting' immediate encoding. + All valid values are in the table below, which we perform a binary + search over*/ +#define IMM_NR 1302 +static uint32_t imm_table[][2] = +{ + {0x800, 0x00000001}, + {0xfc0, 0x00000002}, + {0x801, 0x00000003}, + {0xf80, 0x00000004}, + {0xfc1, 0x00000006}, + {0x802, 0x00000007}, + {0xf40, 0x00000008}, + {0xf81, 0x0000000c}, + {0xfc2, 0x0000000e}, + {0x803, 0x0000000f}, + {0xf00, 0x00000010}, + {0xf41, 0x00000018}, + {0xf82, 0x0000001c}, + {0xfc3, 0x0000001e}, + {0x804, 0x0000001f}, + {0xec0, 0x00000020}, + {0xf01, 0x00000030}, + {0xf42, 0x00000038}, + {0xf83, 0x0000003c}, + {0xfc4, 0x0000003e}, + {0x805, 0x0000003f}, + {0xe80, 0x00000040}, + {0xec1, 0x00000060}, + {0xf02, 0x00000070}, + {0xf43, 0x00000078}, + {0xf84, 0x0000007c}, + {0xfc5, 0x0000007e}, + {0x806, 0x0000007f}, + {0xe40, 0x00000080}, + {0xe81, 0x000000c0}, + {0xec2, 0x000000e0}, + {0xf03, 0x000000f0}, + {0xf44, 0x000000f8}, + {0xf85, 0x000000fc}, + {0xfc6, 0x000000fe}, + {0x807, 0x000000ff}, + {0xe00, 0x00000100}, + {0xe41, 0x00000180}, + {0xe82, 0x000001c0}, + {0xec3, 0x000001e0}, + {0xf04, 0x000001f0}, + {0xf45, 0x000001f8}, + {0xf86, 0x000001fc}, + {0xfc7, 0x000001fe}, + {0x808, 0x000001ff}, + {0xdc0, 0x00000200}, + {0xe01, 0x00000300}, + {0xe42, 0x00000380}, + {0xe83, 0x000003c0}, + {0xec4, 0x000003e0}, + {0xf05, 0x000003f0}, + {0xf46, 0x000003f8}, + {0xf87, 0x000003fc}, + {0xfc8, 0x000003fe}, + {0x809, 0x000003ff}, + {0xd80, 0x00000400}, + {0xdc1, 0x00000600}, + {0xe02, 0x00000700}, + {0xe43, 0x00000780}, + {0xe84, 0x000007c0}, + {0xec5, 0x000007e0}, + {0xf06, 0x000007f0}, + {0xf47, 0x000007f8}, + {0xf88, 0x000007fc}, + {0xfc9, 0x000007fe}, + {0x80a, 0x000007ff}, + {0xd40, 0x00000800}, + {0xd81, 0x00000c00}, + {0xdc2, 0x00000e00}, + {0xe03, 0x00000f00}, + {0xe44, 0x00000f80}, + {0xe85, 0x00000fc0}, + {0xec6, 0x00000fe0}, + {0xf07, 0x00000ff0}, + {0xf48, 0x00000ff8}, + {0xf89, 0x00000ffc}, + {0xfca, 0x00000ffe}, + {0x80b, 0x00000fff}, + {0xd00, 0x00001000}, + {0xd41, 0x00001800}, + {0xd82, 0x00001c00}, + {0xdc3, 0x00001e00}, + {0xe04, 0x00001f00}, + {0xe45, 0x00001f80}, + {0xe86, 0x00001fc0}, + {0xec7, 0x00001fe0}, + {0xf08, 0x00001ff0}, + {0xf49, 0x00001ff8}, + {0xf8a, 0x00001ffc}, + {0xfcb, 0x00001ffe}, + {0x80c, 0x00001fff}, + {0xcc0, 0x00002000}, + {0xd01, 0x00003000}, + {0xd42, 0x00003800}, + {0xd83, 0x00003c00}, + {0xdc4, 0x00003e00}, + {0xe05, 0x00003f00}, + {0xe46, 0x00003f80}, + {0xe87, 0x00003fc0}, + {0xec8, 0x00003fe0}, + {0xf09, 0x00003ff0}, + {0xf4a, 0x00003ff8}, + {0xf8b, 0x00003ffc}, + {0xfcc, 0x00003ffe}, + {0x80d, 0x00003fff}, + {0xc80, 0x00004000}, + {0xcc1, 0x00006000}, + {0xd02, 0x00007000}, + {0xd43, 0x00007800}, + {0xd84, 0x00007c00}, + {0xdc5, 0x00007e00}, + {0xe06, 0x00007f00}, + {0xe47, 0x00007f80}, + {0xe88, 0x00007fc0}, + {0xec9, 0x00007fe0}, + {0xf0a, 0x00007ff0}, + {0xf4b, 0x00007ff8}, + {0xf8c, 0x00007ffc}, + {0xfcd, 0x00007ffe}, + {0x80e, 0x00007fff}, + {0xc40, 0x00008000}, + {0xc81, 0x0000c000}, + {0xcc2, 0x0000e000}, + {0xd03, 0x0000f000}, + {0xd44, 0x0000f800}, + {0xd85, 0x0000fc00}, + {0xdc6, 0x0000fe00}, + {0xe07, 0x0000ff00}, + {0xe48, 0x0000ff80}, + {0xe89, 0x0000ffc0}, + {0xeca, 0x0000ffe0}, + {0xf0b, 0x0000fff0}, + {0xf4c, 0x0000fff8}, + {0xf8d, 0x0000fffc}, + {0xfce, 0x0000fffe}, + {0x80f, 0x0000ffff}, + {0xc00, 0x00010000}, + {0xc20, 0x00010001}, + {0xc41, 0x00018000}, + {0xc82, 0x0001c000}, + {0xcc3, 0x0001e000}, + {0xd04, 0x0001f000}, + {0xd45, 0x0001f800}, + {0xd86, 0x0001fc00}, + {0xdc7, 0x0001fe00}, + {0xe08, 0x0001ff00}, + {0xe49, 0x0001ff80}, + {0xe8a, 0x0001ffc0}, + {0xecb, 0x0001ffe0}, + {0xf0c, 0x0001fff0}, + {0xf4d, 0x0001fff8}, + {0xf8e, 0x0001fffc}, + {0xfcf, 0x0001fffe}, + {0x810, 0x0001ffff}, + {0xbc0, 0x00020000}, + {0xfe0, 0x00020002}, + {0xc01, 0x00030000}, + {0xc21, 0x00030003}, + {0xc42, 0x00038000}, + {0xc83, 0x0003c000}, + {0xcc4, 0x0003e000}, + {0xd05, 0x0003f000}, + {0xd46, 0x0003f800}, + {0xd87, 0x0003fc00}, + {0xdc8, 0x0003fe00}, + {0xe09, 0x0003ff00}, + {0xe4a, 0x0003ff80}, + {0xe8b, 0x0003ffc0}, + {0xecc, 0x0003ffe0}, + {0xf0d, 0x0003fff0}, + {0xf4e, 0x0003fff8}, + {0xf8f, 0x0003fffc}, + {0xfd0, 0x0003fffe}, + {0x811, 0x0003ffff}, + {0xb80, 0x00040000}, + {0xfa0, 0x00040004}, + {0xbc1, 0x00060000}, + {0xfe1, 0x00060006}, + {0xc02, 0x00070000}, + {0xc22, 0x00070007}, + {0xc43, 0x00078000}, + {0xc84, 0x0007c000}, + {0xcc5, 0x0007e000}, + {0xd06, 0x0007f000}, + {0xd47, 0x0007f800}, + {0xd88, 0x0007fc00}, + {0xdc9, 0x0007fe00}, + {0xe0a, 0x0007ff00}, + {0xe4b, 0x0007ff80}, + {0xe8c, 0x0007ffc0}, + {0xecd, 0x0007ffe0}, + {0xf0e, 0x0007fff0}, + {0xf4f, 0x0007fff8}, + {0xf90, 0x0007fffc}, + {0xfd1, 0x0007fffe}, + {0x812, 0x0007ffff}, + {0xb40, 0x00080000}, + {0xf60, 0x00080008}, + {0xb81, 0x000c0000}, + {0xfa1, 0x000c000c}, + {0xbc2, 0x000e0000}, + {0xfe2, 0x000e000e}, + {0xc03, 0x000f0000}, + {0xc23, 0x000f000f}, + {0xc44, 0x000f8000}, + {0xc85, 0x000fc000}, + {0xcc6, 0x000fe000}, + {0xd07, 0x000ff000}, + {0xd48, 0x000ff800}, + {0xd89, 0x000ffc00}, + {0xdca, 0x000ffe00}, + {0xe0b, 0x000fff00}, + {0xe4c, 0x000fff80}, + {0xe8d, 0x000fffc0}, + {0xece, 0x000fffe0}, + {0xf0f, 0x000ffff0}, + {0xf50, 0x000ffff8}, + {0xf91, 0x000ffffc}, + {0xfd2, 0x000ffffe}, + {0x813, 0x000fffff}, + {0xb00, 0x00100000}, + {0xf20, 0x00100010}, + {0xb41, 0x00180000}, + {0xf61, 0x00180018}, + {0xb82, 0x001c0000}, + {0xfa2, 0x001c001c}, + {0xbc3, 0x001e0000}, + {0xfe3, 0x001e001e}, + {0xc04, 0x001f0000}, + {0xc24, 0x001f001f}, + {0xc45, 0x001f8000}, + {0xc86, 0x001fc000}, + {0xcc7, 0x001fe000}, + {0xd08, 0x001ff000}, + {0xd49, 0x001ff800}, + {0xd8a, 0x001ffc00}, + {0xdcb, 0x001ffe00}, + {0xe0c, 0x001fff00}, + {0xe4d, 0x001fff80}, + {0xe8e, 0x001fffc0}, + {0xecf, 0x001fffe0}, + {0xf10, 0x001ffff0}, + {0xf51, 0x001ffff8}, + {0xf92, 0x001ffffc}, + {0xfd3, 0x001ffffe}, + {0x814, 0x001fffff}, + {0xac0, 0x00200000}, + {0xee0, 0x00200020}, + {0xb01, 0x00300000}, + {0xf21, 0x00300030}, + {0xb42, 0x00380000}, + {0xf62, 0x00380038}, + {0xb83, 0x003c0000}, + {0xfa3, 0x003c003c}, + {0xbc4, 0x003e0000}, + {0xfe4, 0x003e003e}, + {0xc05, 0x003f0000}, + {0xc25, 0x003f003f}, + {0xc46, 0x003f8000}, + {0xc87, 0x003fc000}, + {0xcc8, 0x003fe000}, + {0xd09, 0x003ff000}, + {0xd4a, 0x003ff800}, + {0xd8b, 0x003ffc00}, + {0xdcc, 0x003ffe00}, + {0xe0d, 0x003fff00}, + {0xe4e, 0x003fff80}, + {0xe8f, 0x003fffc0}, + {0xed0, 0x003fffe0}, + {0xf11, 0x003ffff0}, + {0xf52, 0x003ffff8}, + {0xf93, 0x003ffffc}, + {0xfd4, 0x003ffffe}, + {0x815, 0x003fffff}, + {0xa80, 0x00400000}, + {0xea0, 0x00400040}, + {0xac1, 0x00600000}, + {0xee1, 0x00600060}, + {0xb02, 0x00700000}, + {0xf22, 0x00700070}, + {0xb43, 0x00780000}, + {0xf63, 0x00780078}, + {0xb84, 0x007c0000}, + {0xfa4, 0x007c007c}, + {0xbc5, 0x007e0000}, + {0xfe5, 0x007e007e}, + {0xc06, 0x007f0000}, + {0xc26, 0x007f007f}, + {0xc47, 0x007f8000}, + {0xc88, 0x007fc000}, + {0xcc9, 0x007fe000}, + {0xd0a, 0x007ff000}, + {0xd4b, 0x007ff800}, + {0xd8c, 0x007ffc00}, + {0xdcd, 0x007ffe00}, + {0xe0e, 0x007fff00}, + {0xe4f, 0x007fff80}, + {0xe90, 0x007fffc0}, + {0xed1, 0x007fffe0}, + {0xf12, 0x007ffff0}, + {0xf53, 0x007ffff8}, + {0xf94, 0x007ffffc}, + {0xfd5, 0x007ffffe}, + {0x816, 0x007fffff}, + {0xa40, 0x00800000}, + {0xe60, 0x00800080}, + {0xa81, 0x00c00000}, + {0xea1, 0x00c000c0}, + {0xac2, 0x00e00000}, + {0xee2, 0x00e000e0}, + {0xb03, 0x00f00000}, + {0xf23, 0x00f000f0}, + {0xb44, 0x00f80000}, + {0xf64, 0x00f800f8}, + {0xb85, 0x00fc0000}, + {0xfa5, 0x00fc00fc}, + {0xbc6, 0x00fe0000}, + {0xfe6, 0x00fe00fe}, + {0xc07, 0x00ff0000}, + {0xc27, 0x00ff00ff}, + {0xc48, 0x00ff8000}, + {0xc89, 0x00ffc000}, + {0xcca, 0x00ffe000}, + {0xd0b, 0x00fff000}, + {0xd4c, 0x00fff800}, + {0xd8d, 0x00fffc00}, + {0xdce, 0x00fffe00}, + {0xe0f, 0x00ffff00}, + {0xe50, 0x00ffff80}, + {0xe91, 0x00ffffc0}, + {0xed2, 0x00ffffe0}, + {0xf13, 0x00fffff0}, + {0xf54, 0x00fffff8}, + {0xf95, 0x00fffffc}, + {0xfd6, 0x00fffffe}, + {0x817, 0x00ffffff}, + {0xa00, 0x01000000}, + {0xe20, 0x01000100}, + {0xe30, 0x01010101}, + {0xa41, 0x01800000}, + {0xe61, 0x01800180}, + {0xa82, 0x01c00000}, + {0xea2, 0x01c001c0}, + {0xac3, 0x01e00000}, + {0xee3, 0x01e001e0}, + {0xb04, 0x01f00000}, + {0xf24, 0x01f001f0}, + {0xb45, 0x01f80000}, + {0xf65, 0x01f801f8}, + {0xb86, 0x01fc0000}, + {0xfa6, 0x01fc01fc}, + {0xbc7, 0x01fe0000}, + {0xfe7, 0x01fe01fe}, + {0xc08, 0x01ff0000}, + {0xc28, 0x01ff01ff}, + {0xc49, 0x01ff8000}, + {0xc8a, 0x01ffc000}, + {0xccb, 0x01ffe000}, + {0xd0c, 0x01fff000}, + {0xd4d, 0x01fff800}, + {0xd8e, 0x01fffc00}, + {0xdcf, 0x01fffe00}, + {0xe10, 0x01ffff00}, + {0xe51, 0x01ffff80}, + {0xe92, 0x01ffffc0}, + {0xed3, 0x01ffffe0}, + {0xf14, 0x01fffff0}, + {0xf55, 0x01fffff8}, + {0xf96, 0x01fffffc}, + {0xfd7, 0x01fffffe}, + {0x818, 0x01ffffff}, + {0x9c0, 0x02000000}, + {0xde0, 0x02000200}, + {0xff0, 0x02020202}, + {0xa01, 0x03000000}, + {0xe21, 0x03000300}, + {0xe31, 0x03030303}, + {0xa42, 0x03800000}, + {0xe62, 0x03800380}, + {0xa83, 0x03c00000}, + {0xea3, 0x03c003c0}, + {0xac4, 0x03e00000}, + {0xee4, 0x03e003e0}, + {0xb05, 0x03f00000}, + {0xf25, 0x03f003f0}, + {0xb46, 0x03f80000}, + {0xf66, 0x03f803f8}, + {0xb87, 0x03fc0000}, + {0xfa7, 0x03fc03fc}, + {0xbc8, 0x03fe0000}, + {0xfe8, 0x03fe03fe}, + {0xc09, 0x03ff0000}, + {0xc29, 0x03ff03ff}, + {0xc4a, 0x03ff8000}, + {0xc8b, 0x03ffc000}, + {0xccc, 0x03ffe000}, + {0xd0d, 0x03fff000}, + {0xd4e, 0x03fff800}, + {0xd8f, 0x03fffc00}, + {0xdd0, 0x03fffe00}, + {0xe11, 0x03ffff00}, + {0xe52, 0x03ffff80}, + {0xe93, 0x03ffffc0}, + {0xed4, 0x03ffffe0}, + {0xf15, 0x03fffff0}, + {0xf56, 0x03fffff8}, + {0xf97, 0x03fffffc}, + {0xfd8, 0x03fffffe}, + {0x819, 0x03ffffff}, + {0x980, 0x04000000}, + {0xda0, 0x04000400}, + {0xfb0, 0x04040404}, + {0x9c1, 0x06000000}, + {0xde1, 0x06000600}, + {0xff1, 0x06060606}, + {0xa02, 0x07000000}, + {0xe22, 0x07000700}, + {0xe32, 0x07070707}, + {0xa43, 0x07800000}, + {0xe63, 0x07800780}, + {0xa84, 0x07c00000}, + {0xea4, 0x07c007c0}, + {0xac5, 0x07e00000}, + {0xee5, 0x07e007e0}, + {0xb06, 0x07f00000}, + {0xf26, 0x07f007f0}, + {0xb47, 0x07f80000}, + {0xf67, 0x07f807f8}, + {0xb88, 0x07fc0000}, + {0xfa8, 0x07fc07fc}, + {0xbc9, 0x07fe0000}, + {0xfe9, 0x07fe07fe}, + {0xc0a, 0x07ff0000}, + {0xc2a, 0x07ff07ff}, + {0xc4b, 0x07ff8000}, + {0xc8c, 0x07ffc000}, + {0xccd, 0x07ffe000}, + {0xd0e, 0x07fff000}, + {0xd4f, 0x07fff800}, + {0xd90, 0x07fffc00}, + {0xdd1, 0x07fffe00}, + {0xe12, 0x07ffff00}, + {0xe53, 0x07ffff80}, + {0xe94, 0x07ffffc0}, + {0xed5, 0x07ffffe0}, + {0xf16, 0x07fffff0}, + {0xf57, 0x07fffff8}, + {0xf98, 0x07fffffc}, + {0xfd9, 0x07fffffe}, + {0x81a, 0x07ffffff}, + {0x940, 0x08000000}, + {0xd60, 0x08000800}, + {0xf70, 0x08080808}, + {0x981, 0x0c000000}, + {0xda1, 0x0c000c00}, + {0xfb1, 0x0c0c0c0c}, + {0x9c2, 0x0e000000}, + {0xde2, 0x0e000e00}, + {0xff2, 0x0e0e0e0e}, + {0xa03, 0x0f000000}, + {0xe23, 0x0f000f00}, + {0xe33, 0x0f0f0f0f}, + {0xa44, 0x0f800000}, + {0xe64, 0x0f800f80}, + {0xa85, 0x0fc00000}, + {0xea5, 0x0fc00fc0}, + {0xac6, 0x0fe00000}, + {0xee6, 0x0fe00fe0}, + {0xb07, 0x0ff00000}, + {0xf27, 0x0ff00ff0}, + {0xb48, 0x0ff80000}, + {0xf68, 0x0ff80ff8}, + {0xb89, 0x0ffc0000}, + {0xfa9, 0x0ffc0ffc}, + {0xbca, 0x0ffe0000}, + {0xfea, 0x0ffe0ffe}, + {0xc0b, 0x0fff0000}, + {0xc2b, 0x0fff0fff}, + {0xc4c, 0x0fff8000}, + {0xc8d, 0x0fffc000}, + {0xcce, 0x0fffe000}, + {0xd0f, 0x0ffff000}, + {0xd50, 0x0ffff800}, + {0xd91, 0x0ffffc00}, + {0xdd2, 0x0ffffe00}, + {0xe13, 0x0fffff00}, + {0xe54, 0x0fffff80}, + {0xe95, 0x0fffffc0}, + {0xed6, 0x0fffffe0}, + {0xf17, 0x0ffffff0}, + {0xf58, 0x0ffffff8}, + {0xf99, 0x0ffffffc}, + {0xfda, 0x0ffffffe}, + {0x81b, 0x0fffffff}, + {0x900, 0x10000000}, + {0xd20, 0x10001000}, + {0xf30, 0x10101010}, + {0xf38, 0x11111111}, + {0x941, 0x18000000}, + {0xd61, 0x18001800}, + {0xf71, 0x18181818}, + {0x982, 0x1c000000}, + {0xda2, 0x1c001c00}, + {0xfb2, 0x1c1c1c1c}, + {0x9c3, 0x1e000000}, + {0xde3, 0x1e001e00}, + {0xff3, 0x1e1e1e1e}, + {0xa04, 0x1f000000}, + {0xe24, 0x1f001f00}, + {0xe34, 0x1f1f1f1f}, + {0xa45, 0x1f800000}, + {0xe65, 0x1f801f80}, + {0xa86, 0x1fc00000}, + {0xea6, 0x1fc01fc0}, + {0xac7, 0x1fe00000}, + {0xee7, 0x1fe01fe0}, + {0xb08, 0x1ff00000}, + {0xf28, 0x1ff01ff0}, + {0xb49, 0x1ff80000}, + {0xf69, 0x1ff81ff8}, + {0xb8a, 0x1ffc0000}, + {0xfaa, 0x1ffc1ffc}, + {0xbcb, 0x1ffe0000}, + {0xfeb, 0x1ffe1ffe}, + {0xc0c, 0x1fff0000}, + {0xc2c, 0x1fff1fff}, + {0xc4d, 0x1fff8000}, + {0xc8e, 0x1fffc000}, + {0xccf, 0x1fffe000}, + {0xd10, 0x1ffff000}, + {0xd51, 0x1ffff800}, + {0xd92, 0x1ffffc00}, + {0xdd3, 0x1ffffe00}, + {0xe14, 0x1fffff00}, + {0xe55, 0x1fffff80}, + {0xe96, 0x1fffffc0}, + {0xed7, 0x1fffffe0}, + {0xf18, 0x1ffffff0}, + {0xf59, 0x1ffffff8}, + {0xf9a, 0x1ffffffc}, + {0xfdb, 0x1ffffffe}, + {0x81c, 0x1fffffff}, + {0x8c0, 0x20000000}, + {0xce0, 0x20002000}, + {0xef0, 0x20202020}, + {0xff8, 0x22222222}, + {0x901, 0x30000000}, + {0xd21, 0x30003000}, + {0xf31, 0x30303030}, + {0xf39, 0x33333333}, + {0x942, 0x38000000}, + {0xd62, 0x38003800}, + {0xf72, 0x38383838}, + {0x983, 0x3c000000}, + {0xda3, 0x3c003c00}, + {0xfb3, 0x3c3c3c3c}, + {0x9c4, 0x3e000000}, + {0xde4, 0x3e003e00}, + {0xff4, 0x3e3e3e3e}, + {0xa05, 0x3f000000}, + {0xe25, 0x3f003f00}, + {0xe35, 0x3f3f3f3f}, + {0xa46, 0x3f800000}, + {0xe66, 0x3f803f80}, + {0xa87, 0x3fc00000}, + {0xea7, 0x3fc03fc0}, + {0xac8, 0x3fe00000}, + {0xee8, 0x3fe03fe0}, + {0xb09, 0x3ff00000}, + {0xf29, 0x3ff03ff0}, + {0xb4a, 0x3ff80000}, + {0xf6a, 0x3ff83ff8}, + {0xb8b, 0x3ffc0000}, + {0xfab, 0x3ffc3ffc}, + {0xbcc, 0x3ffe0000}, + {0xfec, 0x3ffe3ffe}, + {0xc0d, 0x3fff0000}, + {0xc2d, 0x3fff3fff}, + {0xc4e, 0x3fff8000}, + {0xc8f, 0x3fffc000}, + {0xcd0, 0x3fffe000}, + {0xd11, 0x3ffff000}, + {0xd52, 0x3ffff800}, + {0xd93, 0x3ffffc00}, + {0xdd4, 0x3ffffe00}, + {0xe15, 0x3fffff00}, + {0xe56, 0x3fffff80}, + {0xe97, 0x3fffffc0}, + {0xed8, 0x3fffffe0}, + {0xf19, 0x3ffffff0}, + {0xf5a, 0x3ffffff8}, + {0xf9b, 0x3ffffffc}, + {0xfdc, 0x3ffffffe}, + {0x81d, 0x3fffffff}, + {0x880, 0x40000000}, + {0xca0, 0x40004000}, + {0xeb0, 0x40404040}, + {0xfb8, 0x44444444}, + {0xfbc, 0x55555555}, + {0x8c1, 0x60000000}, + {0xce1, 0x60006000}, + {0xef1, 0x60606060}, + {0xff9, 0x66666666}, + {0x902, 0x70000000}, + {0xd22, 0x70007000}, + {0xf32, 0x70707070}, + {0xf3a, 0x77777777}, + {0x943, 0x78000000}, + {0xd63, 0x78007800}, + {0xf73, 0x78787878}, + {0x984, 0x7c000000}, + {0xda4, 0x7c007c00}, + {0xfb4, 0x7c7c7c7c}, + {0x9c5, 0x7e000000}, + {0xde5, 0x7e007e00}, + {0xff5, 0x7e7e7e7e}, + {0xa06, 0x7f000000}, + {0xe26, 0x7f007f00}, + {0xe36, 0x7f7f7f7f}, + {0xa47, 0x7f800000}, + {0xe67, 0x7f807f80}, + {0xa88, 0x7fc00000}, + {0xea8, 0x7fc07fc0}, + {0xac9, 0x7fe00000}, + {0xee9, 0x7fe07fe0}, + {0xb0a, 0x7ff00000}, + {0xf2a, 0x7ff07ff0}, + {0xb4b, 0x7ff80000}, + {0xf6b, 0x7ff87ff8}, + {0xb8c, 0x7ffc0000}, + {0xfac, 0x7ffc7ffc}, + {0xbcd, 0x7ffe0000}, + {0xfed, 0x7ffe7ffe}, + {0xc0e, 0x7fff0000}, + {0xc2e, 0x7fff7fff}, + {0xc4f, 0x7fff8000}, + {0xc90, 0x7fffc000}, + {0xcd1, 0x7fffe000}, + {0xd12, 0x7ffff000}, + {0xd53, 0x7ffff800}, + {0xd94, 0x7ffffc00}, + {0xdd5, 0x7ffffe00}, + {0xe16, 0x7fffff00}, + {0xe57, 0x7fffff80}, + {0xe98, 0x7fffffc0}, + {0xed9, 0x7fffffe0}, + {0xf1a, 0x7ffffff0}, + {0xf5b, 0x7ffffff8}, + {0xf9c, 0x7ffffffc}, + {0xfdd, 0x7ffffffe}, + {0x81e, 0x7fffffff}, + {0x840, 0x80000000}, + {0x841, 0x80000001}, + {0x842, 0x80000003}, + {0x843, 0x80000007}, + {0x844, 0x8000000f}, + {0x845, 0x8000001f}, + {0x846, 0x8000003f}, + {0x847, 0x8000007f}, + {0x848, 0x800000ff}, + {0x849, 0x800001ff}, + {0x84a, 0x800003ff}, + {0x84b, 0x800007ff}, + {0x84c, 0x80000fff}, + {0x84d, 0x80001fff}, + {0x84e, 0x80003fff}, + {0x84f, 0x80007fff}, + {0xc60, 0x80008000}, + {0x850, 0x8000ffff}, + {0xc61, 0x80018001}, + {0x851, 0x8001ffff}, + {0xc62, 0x80038003}, + {0x852, 0x8003ffff}, + {0xc63, 0x80078007}, + {0x853, 0x8007ffff}, + {0xc64, 0x800f800f}, + {0x854, 0x800fffff}, + {0xc65, 0x801f801f}, + {0x855, 0x801fffff}, + {0xc66, 0x803f803f}, + {0x856, 0x803fffff}, + {0xc67, 0x807f807f}, + {0x857, 0x807fffff}, + {0xe70, 0x80808080}, + {0xc68, 0x80ff80ff}, + {0x858, 0x80ffffff}, + {0xe71, 0x81818181}, + {0xc69, 0x81ff81ff}, + {0x859, 0x81ffffff}, + {0xe72, 0x83838383}, + {0xc6a, 0x83ff83ff}, + {0x85a, 0x83ffffff}, + {0xe73, 0x87878787}, + {0xc6b, 0x87ff87ff}, + {0x85b, 0x87ffffff}, + {0xf78, 0x88888888}, + {0xe74, 0x8f8f8f8f}, + {0xc6c, 0x8fff8fff}, + {0x85c, 0x8fffffff}, + {0xf79, 0x99999999}, + {0xe75, 0x9f9f9f9f}, + {0xc6d, 0x9fff9fff}, + {0x85d, 0x9fffffff}, + {0xffc, 0xaaaaaaaa}, + {0xf7a, 0xbbbbbbbb}, + {0xe76, 0xbfbfbfbf}, + {0xc6e, 0xbfffbfff}, + {0x85e, 0xbfffffff}, + {0x881, 0xc0000000}, + {0x882, 0xc0000001}, + {0x883, 0xc0000003}, + {0x884, 0xc0000007}, + {0x885, 0xc000000f}, + {0x886, 0xc000001f}, + {0x887, 0xc000003f}, + {0x888, 0xc000007f}, + {0x889, 0xc00000ff}, + {0x88a, 0xc00001ff}, + {0x88b, 0xc00003ff}, + {0x88c, 0xc00007ff}, + {0x88d, 0xc0000fff}, + {0x88e, 0xc0001fff}, + {0x88f, 0xc0003fff}, + {0x890, 0xc0007fff}, + {0xca1, 0xc000c000}, + {0x891, 0xc000ffff}, + {0xca2, 0xc001c001}, + {0x892, 0xc001ffff}, + {0xca3, 0xc003c003}, + {0x893, 0xc003ffff}, + {0xca4, 0xc007c007}, + {0x894, 0xc007ffff}, + {0xca5, 0xc00fc00f}, + {0x895, 0xc00fffff}, + {0xca6, 0xc01fc01f}, + {0x896, 0xc01fffff}, + {0xca7, 0xc03fc03f}, + {0x897, 0xc03fffff}, + {0xca8, 0xc07fc07f}, + {0x898, 0xc07fffff}, + {0xeb1, 0xc0c0c0c0}, + {0xca9, 0xc0ffc0ff}, + {0x899, 0xc0ffffff}, + {0xeb2, 0xc1c1c1c1}, + {0xcaa, 0xc1ffc1ff}, + {0x89a, 0xc1ffffff}, + {0xeb3, 0xc3c3c3c3}, + {0xcab, 0xc3ffc3ff}, + {0x89b, 0xc3ffffff}, + {0xeb4, 0xc7c7c7c7}, + {0xcac, 0xc7ffc7ff}, + {0x89c, 0xc7ffffff}, + {0xfb9, 0xcccccccc}, + {0xeb5, 0xcfcfcfcf}, + {0xcad, 0xcfffcfff}, + {0x89d, 0xcfffffff}, + {0xfba, 0xdddddddd}, + {0xeb6, 0xdfdfdfdf}, + {0xcae, 0xdfffdfff}, + {0x89e, 0xdfffffff}, + {0x8c2, 0xe0000000}, + {0x8c3, 0xe0000001}, + {0x8c4, 0xe0000003}, + {0x8c5, 0xe0000007}, + {0x8c6, 0xe000000f}, + {0x8c7, 0xe000001f}, + {0x8c8, 0xe000003f}, + {0x8c9, 0xe000007f}, + {0x8ca, 0xe00000ff}, + {0x8cb, 0xe00001ff}, + {0x8cc, 0xe00003ff}, + {0x8cd, 0xe00007ff}, + {0x8ce, 0xe0000fff}, + {0x8cf, 0xe0001fff}, + {0x8d0, 0xe0003fff}, + {0x8d1, 0xe0007fff}, + {0xce2, 0xe000e000}, + {0x8d2, 0xe000ffff}, + {0xce3, 0xe001e001}, + {0x8d3, 0xe001ffff}, + {0xce4, 0xe003e003}, + {0x8d4, 0xe003ffff}, + {0xce5, 0xe007e007}, + {0x8d5, 0xe007ffff}, + {0xce6, 0xe00fe00f}, + {0x8d6, 0xe00fffff}, + {0xce7, 0xe01fe01f}, + {0x8d7, 0xe01fffff}, + {0xce8, 0xe03fe03f}, + {0x8d8, 0xe03fffff}, + {0xce9, 0xe07fe07f}, + {0x8d9, 0xe07fffff}, + {0xef2, 0xe0e0e0e0}, + {0xcea, 0xe0ffe0ff}, + {0x8da, 0xe0ffffff}, + {0xef3, 0xe1e1e1e1}, + {0xceb, 0xe1ffe1ff}, + {0x8db, 0xe1ffffff}, + {0xef4, 0xe3e3e3e3}, + {0xcec, 0xe3ffe3ff}, + {0x8dc, 0xe3ffffff}, + {0xef5, 0xe7e7e7e7}, + {0xced, 0xe7ffe7ff}, + {0x8dd, 0xe7ffffff}, + {0xffa, 0xeeeeeeee}, + {0xef6, 0xefefefef}, + {0xcee, 0xefffefff}, + {0x8de, 0xefffffff}, + {0x903, 0xf0000000}, + {0x904, 0xf0000001}, + {0x905, 0xf0000003}, + {0x906, 0xf0000007}, + {0x907, 0xf000000f}, + {0x908, 0xf000001f}, + {0x909, 0xf000003f}, + {0x90a, 0xf000007f}, + {0x90b, 0xf00000ff}, + {0x90c, 0xf00001ff}, + {0x90d, 0xf00003ff}, + {0x90e, 0xf00007ff}, + {0x90f, 0xf0000fff}, + {0x910, 0xf0001fff}, + {0x911, 0xf0003fff}, + {0x912, 0xf0007fff}, + {0xd23, 0xf000f000}, + {0x913, 0xf000ffff}, + {0xd24, 0xf001f001}, + {0x914, 0xf001ffff}, + {0xd25, 0xf003f003}, + {0x915, 0xf003ffff}, + {0xd26, 0xf007f007}, + {0x916, 0xf007ffff}, + {0xd27, 0xf00ff00f}, + {0x917, 0xf00fffff}, + {0xd28, 0xf01ff01f}, + {0x918, 0xf01fffff}, + {0xd29, 0xf03ff03f}, + {0x919, 0xf03fffff}, + {0xd2a, 0xf07ff07f}, + {0x91a, 0xf07fffff}, + {0xf33, 0xf0f0f0f0}, + {0xd2b, 0xf0fff0ff}, + {0x91b, 0xf0ffffff}, + {0xf34, 0xf1f1f1f1}, + {0xd2c, 0xf1fff1ff}, + {0x91c, 0xf1ffffff}, + {0xf35, 0xf3f3f3f3}, + {0xd2d, 0xf3fff3ff}, + {0x91d, 0xf3ffffff}, + {0xf36, 0xf7f7f7f7}, + {0xd2e, 0xf7fff7ff}, + {0x91e, 0xf7ffffff}, + {0x944, 0xf8000000}, + {0x945, 0xf8000001}, + {0x946, 0xf8000003}, + {0x947, 0xf8000007}, + {0x948, 0xf800000f}, + {0x949, 0xf800001f}, + {0x94a, 0xf800003f}, + {0x94b, 0xf800007f}, + {0x94c, 0xf80000ff}, + {0x94d, 0xf80001ff}, + {0x94e, 0xf80003ff}, + {0x94f, 0xf80007ff}, + {0x950, 0xf8000fff}, + {0x951, 0xf8001fff}, + {0x952, 0xf8003fff}, + {0x953, 0xf8007fff}, + {0xd64, 0xf800f800}, + {0x954, 0xf800ffff}, + {0xd65, 0xf801f801}, + {0x955, 0xf801ffff}, + {0xd66, 0xf803f803}, + {0x956, 0xf803ffff}, + {0xd67, 0xf807f807}, + {0x957, 0xf807ffff}, + {0xd68, 0xf80ff80f}, + {0x958, 0xf80fffff}, + {0xd69, 0xf81ff81f}, + {0x959, 0xf81fffff}, + {0xd6a, 0xf83ff83f}, + {0x95a, 0xf83fffff}, + {0xd6b, 0xf87ff87f}, + {0x95b, 0xf87fffff}, + {0xf74, 0xf8f8f8f8}, + {0xd6c, 0xf8fff8ff}, + {0x95c, 0xf8ffffff}, + {0xf75, 0xf9f9f9f9}, + {0xd6d, 0xf9fff9ff}, + {0x95d, 0xf9ffffff}, + {0xf76, 0xfbfbfbfb}, + {0xd6e, 0xfbfffbff}, + {0x95e, 0xfbffffff}, + {0x985, 0xfc000000}, + {0x986, 0xfc000001}, + {0x987, 0xfc000003}, + {0x988, 0xfc000007}, + {0x989, 0xfc00000f}, + {0x98a, 0xfc00001f}, + {0x98b, 0xfc00003f}, + {0x98c, 0xfc00007f}, + {0x98d, 0xfc0000ff}, + {0x98e, 0xfc0001ff}, + {0x98f, 0xfc0003ff}, + {0x990, 0xfc0007ff}, + {0x991, 0xfc000fff}, + {0x992, 0xfc001fff}, + {0x993, 0xfc003fff}, + {0x994, 0xfc007fff}, + {0xda5, 0xfc00fc00}, + {0x995, 0xfc00ffff}, + {0xda6, 0xfc01fc01}, + {0x996, 0xfc01ffff}, + {0xda7, 0xfc03fc03}, + {0x997, 0xfc03ffff}, + {0xda8, 0xfc07fc07}, + {0x998, 0xfc07ffff}, + {0xda9, 0xfc0ffc0f}, + {0x999, 0xfc0fffff}, + {0xdaa, 0xfc1ffc1f}, + {0x99a, 0xfc1fffff}, + {0xdab, 0xfc3ffc3f}, + {0x99b, 0xfc3fffff}, + {0xdac, 0xfc7ffc7f}, + {0x99c, 0xfc7fffff}, + {0xfb5, 0xfcfcfcfc}, + {0xdad, 0xfcfffcff}, + {0x99d, 0xfcffffff}, + {0xfb6, 0xfdfdfdfd}, + {0xdae, 0xfdfffdff}, + {0x99e, 0xfdffffff}, + {0x9c6, 0xfe000000}, + {0x9c7, 0xfe000001}, + {0x9c8, 0xfe000003}, + {0x9c9, 0xfe000007}, + {0x9ca, 0xfe00000f}, + {0x9cb, 0xfe00001f}, + {0x9cc, 0xfe00003f}, + {0x9cd, 0xfe00007f}, + {0x9ce, 0xfe0000ff}, + {0x9cf, 0xfe0001ff}, + {0x9d0, 0xfe0003ff}, + {0x9d1, 0xfe0007ff}, + {0x9d2, 0xfe000fff}, + {0x9d3, 0xfe001fff}, + {0x9d4, 0xfe003fff}, + {0x9d5, 0xfe007fff}, + {0xde6, 0xfe00fe00}, + {0x9d6, 0xfe00ffff}, + {0xde7, 0xfe01fe01}, + {0x9d7, 0xfe01ffff}, + {0xde8, 0xfe03fe03}, + {0x9d8, 0xfe03ffff}, + {0xde9, 0xfe07fe07}, + {0x9d9, 0xfe07ffff}, + {0xdea, 0xfe0ffe0f}, + {0x9da, 0xfe0fffff}, + {0xdeb, 0xfe1ffe1f}, + {0x9db, 0xfe1fffff}, + {0xdec, 0xfe3ffe3f}, + {0x9dc, 0xfe3fffff}, + {0xded, 0xfe7ffe7f}, + {0x9dd, 0xfe7fffff}, + {0xff6, 0xfefefefe}, + {0xdee, 0xfefffeff}, + {0x9de, 0xfeffffff}, + {0xa07, 0xff000000}, + {0xa08, 0xff000001}, + {0xa09, 0xff000003}, + {0xa0a, 0xff000007}, + {0xa0b, 0xff00000f}, + {0xa0c, 0xff00001f}, + {0xa0d, 0xff00003f}, + {0xa0e, 0xff00007f}, + {0xa0f, 0xff0000ff}, + {0xa10, 0xff0001ff}, + {0xa11, 0xff0003ff}, + {0xa12, 0xff0007ff}, + {0xa13, 0xff000fff}, + {0xa14, 0xff001fff}, + {0xa15, 0xff003fff}, + {0xa16, 0xff007fff}, + {0xe27, 0xff00ff00}, + {0xa17, 0xff00ffff}, + {0xe28, 0xff01ff01}, + {0xa18, 0xff01ffff}, + {0xe29, 0xff03ff03}, + {0xa19, 0xff03ffff}, + {0xe2a, 0xff07ff07}, + {0xa1a, 0xff07ffff}, + {0xe2b, 0xff0fff0f}, + {0xa1b, 0xff0fffff}, + {0xe2c, 0xff1fff1f}, + {0xa1c, 0xff1fffff}, + {0xe2d, 0xff3fff3f}, + {0xa1d, 0xff3fffff}, + {0xe2e, 0xff7fff7f}, + {0xa1e, 0xff7fffff}, + {0xa48, 0xff800000}, + {0xa49, 0xff800001}, + {0xa4a, 0xff800003}, + {0xa4b, 0xff800007}, + {0xa4c, 0xff80000f}, + {0xa4d, 0xff80001f}, + {0xa4e, 0xff80003f}, + {0xa4f, 0xff80007f}, + {0xa50, 0xff8000ff}, + {0xa51, 0xff8001ff}, + {0xa52, 0xff8003ff}, + {0xa53, 0xff8007ff}, + {0xa54, 0xff800fff}, + {0xa55, 0xff801fff}, + {0xa56, 0xff803fff}, + {0xa57, 0xff807fff}, + {0xe68, 0xff80ff80}, + {0xa58, 0xff80ffff}, + {0xe69, 0xff81ff81}, + {0xa59, 0xff81ffff}, + {0xe6a, 0xff83ff83}, + {0xa5a, 0xff83ffff}, + {0xe6b, 0xff87ff87}, + {0xa5b, 0xff87ffff}, + {0xe6c, 0xff8fff8f}, + {0xa5c, 0xff8fffff}, + {0xe6d, 0xff9fff9f}, + {0xa5d, 0xff9fffff}, + {0xe6e, 0xffbfffbf}, + {0xa5e, 0xffbfffff}, + {0xa89, 0xffc00000}, + {0xa8a, 0xffc00001}, + {0xa8b, 0xffc00003}, + {0xa8c, 0xffc00007}, + {0xa8d, 0xffc0000f}, + {0xa8e, 0xffc0001f}, + {0xa8f, 0xffc0003f}, + {0xa90, 0xffc0007f}, + {0xa91, 0xffc000ff}, + {0xa92, 0xffc001ff}, + {0xa93, 0xffc003ff}, + {0xa94, 0xffc007ff}, + {0xa95, 0xffc00fff}, + {0xa96, 0xffc01fff}, + {0xa97, 0xffc03fff}, + {0xa98, 0xffc07fff}, + {0xea9, 0xffc0ffc0}, + {0xa99, 0xffc0ffff}, + {0xeaa, 0xffc1ffc1}, + {0xa9a, 0xffc1ffff}, + {0xeab, 0xffc3ffc3}, + {0xa9b, 0xffc3ffff}, + {0xeac, 0xffc7ffc7}, + {0xa9c, 0xffc7ffff}, + {0xead, 0xffcfffcf}, + {0xa9d, 0xffcfffff}, + {0xeae, 0xffdfffdf}, + {0xa9e, 0xffdfffff}, + {0xaca, 0xffe00000}, + {0xacb, 0xffe00001}, + {0xacc, 0xffe00003}, + {0xacd, 0xffe00007}, + {0xace, 0xffe0000f}, + {0xacf, 0xffe0001f}, + {0xad0, 0xffe0003f}, + {0xad1, 0xffe0007f}, + {0xad2, 0xffe000ff}, + {0xad3, 0xffe001ff}, + {0xad4, 0xffe003ff}, + {0xad5, 0xffe007ff}, + {0xad6, 0xffe00fff}, + {0xad7, 0xffe01fff}, + {0xad8, 0xffe03fff}, + {0xad9, 0xffe07fff}, + {0xeea, 0xffe0ffe0}, + {0xada, 0xffe0ffff}, + {0xeeb, 0xffe1ffe1}, + {0xadb, 0xffe1ffff}, + {0xeec, 0xffe3ffe3}, + {0xadc, 0xffe3ffff}, + {0xeed, 0xffe7ffe7}, + {0xadd, 0xffe7ffff}, + {0xeee, 0xffefffef}, + {0xade, 0xffefffff}, + {0xb0b, 0xfff00000}, + {0xb0c, 0xfff00001}, + {0xb0d, 0xfff00003}, + {0xb0e, 0xfff00007}, + {0xb0f, 0xfff0000f}, + {0xb10, 0xfff0001f}, + {0xb11, 0xfff0003f}, + {0xb12, 0xfff0007f}, + {0xb13, 0xfff000ff}, + {0xb14, 0xfff001ff}, + {0xb15, 0xfff003ff}, + {0xb16, 0xfff007ff}, + {0xb17, 0xfff00fff}, + {0xb18, 0xfff01fff}, + {0xb19, 0xfff03fff}, + {0xb1a, 0xfff07fff}, + {0xf2b, 0xfff0fff0}, + {0xb1b, 0xfff0ffff}, + {0xf2c, 0xfff1fff1}, + {0xb1c, 0xfff1ffff}, + {0xf2d, 0xfff3fff3}, + {0xb1d, 0xfff3ffff}, + {0xf2e, 0xfff7fff7}, + {0xb1e, 0xfff7ffff}, + {0xb4c, 0xfff80000}, + {0xb4d, 0xfff80001}, + {0xb4e, 0xfff80003}, + {0xb4f, 0xfff80007}, + {0xb50, 0xfff8000f}, + {0xb51, 0xfff8001f}, + {0xb52, 0xfff8003f}, + {0xb53, 0xfff8007f}, + {0xb54, 0xfff800ff}, + {0xb55, 0xfff801ff}, + {0xb56, 0xfff803ff}, + {0xb57, 0xfff807ff}, + {0xb58, 0xfff80fff}, + {0xb59, 0xfff81fff}, + {0xb5a, 0xfff83fff}, + {0xb5b, 0xfff87fff}, + {0xf6c, 0xfff8fff8}, + {0xb5c, 0xfff8ffff}, + {0xf6d, 0xfff9fff9}, + {0xb5d, 0xfff9ffff}, + {0xf6e, 0xfffbfffb}, + {0xb5e, 0xfffbffff}, + {0xb8d, 0xfffc0000}, + {0xb8e, 0xfffc0001}, + {0xb8f, 0xfffc0003}, + {0xb90, 0xfffc0007}, + {0xb91, 0xfffc000f}, + {0xb92, 0xfffc001f}, + {0xb93, 0xfffc003f}, + {0xb94, 0xfffc007f}, + {0xb95, 0xfffc00ff}, + {0xb96, 0xfffc01ff}, + {0xb97, 0xfffc03ff}, + {0xb98, 0xfffc07ff}, + {0xb99, 0xfffc0fff}, + {0xb9a, 0xfffc1fff}, + {0xb9b, 0xfffc3fff}, + {0xb9c, 0xfffc7fff}, + {0xfad, 0xfffcfffc}, + {0xb9d, 0xfffcffff}, + {0xfae, 0xfffdfffd}, + {0xb9e, 0xfffdffff}, + {0xbce, 0xfffe0000}, + {0xbcf, 0xfffe0001}, + {0xbd0, 0xfffe0003}, + {0xbd1, 0xfffe0007}, + {0xbd2, 0xfffe000f}, + {0xbd3, 0xfffe001f}, + {0xbd4, 0xfffe003f}, + {0xbd5, 0xfffe007f}, + {0xbd6, 0xfffe00ff}, + {0xbd7, 0xfffe01ff}, + {0xbd8, 0xfffe03ff}, + {0xbd9, 0xfffe07ff}, + {0xbda, 0xfffe0fff}, + {0xbdb, 0xfffe1fff}, + {0xbdc, 0xfffe3fff}, + {0xbdd, 0xfffe7fff}, + {0xfee, 0xfffefffe}, + {0xbde, 0xfffeffff}, + {0xc0f, 0xffff0000}, + {0xc10, 0xffff0001}, + {0xc11, 0xffff0003}, + {0xc12, 0xffff0007}, + {0xc13, 0xffff000f}, + {0xc14, 0xffff001f}, + {0xc15, 0xffff003f}, + {0xc16, 0xffff007f}, + {0xc17, 0xffff00ff}, + {0xc18, 0xffff01ff}, + {0xc19, 0xffff03ff}, + {0xc1a, 0xffff07ff}, + {0xc1b, 0xffff0fff}, + {0xc1c, 0xffff1fff}, + {0xc1d, 0xffff3fff}, + {0xc1e, 0xffff7fff}, + {0xc50, 0xffff8000}, + {0xc51, 0xffff8001}, + {0xc52, 0xffff8003}, + {0xc53, 0xffff8007}, + {0xc54, 0xffff800f}, + {0xc55, 0xffff801f}, + {0xc56, 0xffff803f}, + {0xc57, 0xffff807f}, + {0xc58, 0xffff80ff}, + {0xc59, 0xffff81ff}, + {0xc5a, 0xffff83ff}, + {0xc5b, 0xffff87ff}, + {0xc5c, 0xffff8fff}, + {0xc5d, 0xffff9fff}, + {0xc5e, 0xffffbfff}, + {0xc91, 0xffffc000}, + {0xc92, 0xffffc001}, + {0xc93, 0xffffc003}, + {0xc94, 0xffffc007}, + {0xc95, 0xffffc00f}, + {0xc96, 0xffffc01f}, + {0xc97, 0xffffc03f}, + {0xc98, 0xffffc07f}, + {0xc99, 0xffffc0ff}, + {0xc9a, 0xffffc1ff}, + {0xc9b, 0xffffc3ff}, + {0xc9c, 0xffffc7ff}, + {0xc9d, 0xffffcfff}, + {0xc9e, 0xffffdfff}, + {0xcd2, 0xffffe000}, + {0xcd3, 0xffffe001}, + {0xcd4, 0xffffe003}, + {0xcd5, 0xffffe007}, + {0xcd6, 0xffffe00f}, + {0xcd7, 0xffffe01f}, + {0xcd8, 0xffffe03f}, + {0xcd9, 0xffffe07f}, + {0xcda, 0xffffe0ff}, + {0xcdb, 0xffffe1ff}, + {0xcdc, 0xffffe3ff}, + {0xcdd, 0xffffe7ff}, + {0xcde, 0xffffefff}, + {0xd13, 0xfffff000}, + {0xd14, 0xfffff001}, + {0xd15, 0xfffff003}, + {0xd16, 0xfffff007}, + {0xd17, 0xfffff00f}, + {0xd18, 0xfffff01f}, + {0xd19, 0xfffff03f}, + {0xd1a, 0xfffff07f}, + {0xd1b, 0xfffff0ff}, + {0xd1c, 0xfffff1ff}, + {0xd1d, 0xfffff3ff}, + {0xd1e, 0xfffff7ff}, + {0xd54, 0xfffff800}, + {0xd55, 0xfffff801}, + {0xd56, 0xfffff803}, + {0xd57, 0xfffff807}, + {0xd58, 0xfffff80f}, + {0xd59, 0xfffff81f}, + {0xd5a, 0xfffff83f}, + {0xd5b, 0xfffff87f}, + {0xd5c, 0xfffff8ff}, + {0xd5d, 0xfffff9ff}, + {0xd5e, 0xfffffbff}, + {0xd95, 0xfffffc00}, + {0xd96, 0xfffffc01}, + {0xd97, 0xfffffc03}, + {0xd98, 0xfffffc07}, + {0xd99, 0xfffffc0f}, + {0xd9a, 0xfffffc1f}, + {0xd9b, 0xfffffc3f}, + {0xd9c, 0xfffffc7f}, + {0xd9d, 0xfffffcff}, + {0xd9e, 0xfffffdff}, + {0xdd6, 0xfffffe00}, + {0xdd7, 0xfffffe01}, + {0xdd8, 0xfffffe03}, + {0xdd9, 0xfffffe07}, + {0xdda, 0xfffffe0f}, + {0xddb, 0xfffffe1f}, + {0xddc, 0xfffffe3f}, + {0xddd, 0xfffffe7f}, + {0xdde, 0xfffffeff}, + {0xe17, 0xffffff00}, + {0xe18, 0xffffff01}, + {0xe19, 0xffffff03}, + {0xe1a, 0xffffff07}, + {0xe1b, 0xffffff0f}, + {0xe1c, 0xffffff1f}, + {0xe1d, 0xffffff3f}, + {0xe1e, 0xffffff7f}, + {0xe58, 0xffffff80}, + {0xe59, 0xffffff81}, + {0xe5a, 0xffffff83}, + {0xe5b, 0xffffff87}, + {0xe5c, 0xffffff8f}, + {0xe5d, 0xffffff9f}, + {0xe5e, 0xffffffbf}, + {0xe99, 0xffffffc0}, + {0xe9a, 0xffffffc1}, + {0xe9b, 0xffffffc3}, + {0xe9c, 0xffffffc7}, + {0xe9d, 0xffffffcf}, + {0xe9e, 0xffffffdf}, + {0xeda, 0xffffffe0}, + {0xedb, 0xffffffe1}, + {0xedc, 0xffffffe3}, + {0xedd, 0xffffffe7}, + {0xede, 0xffffffef}, + {0xf1b, 0xfffffff0}, + {0xf1c, 0xfffffff1}, + {0xf1d, 0xfffffff3}, + {0xf1e, 0xfffffff7}, + {0xf5c, 0xfffffff8}, + {0xf5d, 0xfffffff9}, + {0xf5e, 0xfffffffb}, + {0xf9d, 0xfffffffc}, + {0xf9e, 0xfffffffd}, + {0xfde, 0xfffffffe}, +}; + +uint32_t host_arm64_find_imm(uint32_t data) +{ + int l = 0, r = IMM_NR - 1; + + while (l <= r) + { + int m = (l + r) >> 1; + + if (imm_table[m][1] < data) + l = m+1; + else if (imm_table[m][1] > data) + r = m-1; + else + return imm_table[m][0]; + } + return 0; +} diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 1bc49c0..552665a 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -218,6 +218,8 @@ #define IMMR(immr) ((immr) << 16) #define IMMS(imms) ((imms) << 10) +#define IMM_LOGICAL(imm) ((imm) << 10) + #define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) #define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) @@ -379,25 +381,11 @@ void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ + uint32_t imm_encoding = host_arm64_find_imm(imm_data); + + if (imm_encoding) { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); - } - else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else if (imm_data == 0xffffff00) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); - } - else if (imm_data == 0xffff00ff) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); - } - else if (imm_data == 0x0000ff00) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); } else { @@ -424,25 +412,11 @@ void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */ + uint32_t imm_encoding = host_arm64_find_imm(imm_data); + + if (imm_encoding) { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07)); - } - else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ - { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else if (imm_data == 0xffffff00) - { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); - } - else if (imm_data == 0xffff00ff) - { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); - } - else if (imm_data == 0x0000ff00) - { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07)); + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); } else { @@ -722,9 +696,11 @@ void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int elem void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + uint32_t imm_encoding = host_arm64_find_imm(imm_data); + + if (imm_encoding) { - codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); + codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); } else { @@ -1062,21 +1038,11 @@ void host_arm64_NOP(codeblock_t *block) void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */ + uint32_t imm_encoding = host_arm64_find_imm(imm_data); + + if (imm_encoding) { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f)); - } - else if (imm_data == 0xffff0000) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f)); - } - else if (imm_data == 0xffffff00) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17)); - } - else if (imm_data == 0xffff00ff) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17)); + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); } else { From f7c7f46712cee0998d609c7a66ea6128e5e76647 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 14 Apr 2019 15:38:45 +0100 Subject: [PATCH 178/181] Add missing ARM64 file to Makefile.am --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7d2b106..7528428 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,7 +85,7 @@ pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_ops.c codegen_backend_ endif if CPU_ARM64 -pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c +pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_imm.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c endif if USE_NETWORKING From d527736d21944b201b75b2d8550ce99f468cd774 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 14 Apr 2019 17:03:07 +0100 Subject: [PATCH 179/181] ARM64 fixes - mask off immediate data in UOP_MOV_IMM to the destination size, and add UOP_MOVZX_REG_PTR_16 to uop list. --- src/codegen_backend_arm64_uops.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index 5a92749..0cad9bb 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1246,16 +1246,16 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) } else if (REG_IS_W(dest_size)) { - host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data); + host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data & 0xffff); } else if (REG_IS_B(dest_size)) { - host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data); + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); } else if (REG_IS_BH(dest_size)) { - host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data); + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); } else @@ -3051,6 +3051,7 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, [UOP_ADD & UOP_MASK] = codegen_ADD, [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, From 18a293d5ccb964b08723b487db89e774713c6cce Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 14 Apr 2019 21:40:32 +0100 Subject: [PATCH 180/181] Flush MMU cache on CPU soft reset. Fixes hang on reset under some configurations. --- src/808x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/808x.c b/src/808x.c index 1336727..3ac3dae 100644 --- a/src/808x.c +++ b/src/808x.c @@ -680,6 +680,7 @@ void softresetx86() idt.limit = is386 ? 0x03FF : 0xFFFF; EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; x86seg_reset(); + flushmmucache(); x86_was_reset = 1; } From 0a5198828a0bf17e814be61054b4b6c47cee3abc Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 17 Apr 2019 18:04:05 +0100 Subject: [PATCH 181/181] Latch Voodoo vertices at the start of triangle_setup() before sorting to prevent any races. --- src/vid_voodoo.c | 125 +++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index a5d03e7..480374e 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -202,6 +202,15 @@ typedef struct texture_t uint32_t *data; } texture_t; +typedef struct vert_t +{ + float sVx, sVy; + float sRed, sGreen, sBlue, sAlpha; + float sVz, sWb; + float sW0, sS0, sT0; + float sW1, sS1, sT1; +} vert_t; + typedef struct voodoo_t { mem_mapping_t mapping; @@ -318,14 +327,7 @@ typedef struct voodoo_t uint32_t cmdfifo_amin, cmdfifo_amax; uint32_t sSetupMode; - struct - { - float sVx, sVy; - float sRed, sGreen, sBlue, sAlpha; - float sVz, sWb; - float sW0, sS0, sT0; - float sW1, sS1, sT1; - } verts[4]; + vert_t verts[4]; int vertex_num; int num_verticies; @@ -3705,10 +3707,15 @@ static void triangle_setup(voodoo_t *voodoo) float area; int va = 0, vb = 1, vc = 2; int reverse_cull = 0; + vert_t verts[3]; - if (voodoo->verts[0].sVy < voodoo->verts[1].sVy) + verts[0] = voodoo->verts[0]; + verts[1] = voodoo->verts[1]; + verts[2] = voodoo->verts[2]; + + if (verts[0].sVy < verts[1].sVy) { - if (voodoo->verts[1].sVy < voodoo->verts[2].sVy) + if (verts[1].sVy < verts[2].sVy) { /* V1>V0, V2>V1, V2>V1>V0*/ va = 0; /*OK*/ @@ -3718,7 +3725,7 @@ static void triangle_setup(voodoo_t *voodoo) else { /* V1>V0, V1>V2*/ - if (voodoo->verts[0].sVy < voodoo->verts[2].sVy) + if (verts[0].sVy < verts[2].sVy) { /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/ va = 0; @@ -3737,10 +3744,10 @@ static void triangle_setup(voodoo_t *voodoo) } else { - if (voodoo->verts[1].sVy < voodoo->verts[2].sVy) + if (verts[1].sVy < verts[2].sVy) { /* V0>V1, V2>V1*/ - if (voodoo->verts[0].sVy < voodoo->verts[2].sVy) + if (verts[0].sVy < verts[2].sVy) { /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/ va = 1; @@ -3766,10 +3773,10 @@ static void triangle_setup(voodoo_t *voodoo) } } - dxAB = voodoo->verts[va].sVx - voodoo->verts[vb].sVx; - dxBC = voodoo->verts[vb].sVx - voodoo->verts[vc].sVx; - dyAB = voodoo->verts[va].sVy - voodoo->verts[vb].sVy; - dyBC = voodoo->verts[vb].sVy - voodoo->verts[vc].sVy; + dxAB = verts[va].sVx - verts[vb].sVx; + dxBC = verts[vb].sVx - verts[vc].sVx; + dyAB = verts[va].sVy - verts[vb].sVy; + dyBC = verts[vb].sVy - verts[vc].sVy; area = dxAB * dyBC - dxBC * dyAB; @@ -3804,66 +3811,66 @@ static void triangle_setup(voodoo_t *voodoo) return; } - voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(voodoo->verts[va].sVx * 16.0f) & 0xffff); - voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(voodoo->verts[va].sVy * 16.0f) & 0xffff); - voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(voodoo->verts[vb].sVx * 16.0f) & 0xffff); - voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(voodoo->verts[vb].sVy * 16.0f) & 0xffff); - voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(voodoo->verts[vc].sVx * 16.0f) & 0xffff); - voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(voodoo->verts[vc].sVy * 16.0f) & 0xffff); + voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff); + voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff); + voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff); + voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff); + voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff); + voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff); if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) fatal("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy); if (voodoo->sSetupMode & SETUPMODE_RGB) { - voodoo->params.startR = (int32_t)(voodoo->verts[va].sRed * 4096.0f); - voodoo->params.dRdX = (int32_t)(((voodoo->verts[va].sRed - voodoo->verts[vb].sRed) * dyBC - (voodoo->verts[vb].sRed - voodoo->verts[vc].sRed) * dyAB) * 4096.0f); - voodoo->params.dRdY = (int32_t)(((voodoo->verts[vb].sRed - voodoo->verts[vc].sRed) * dxAB - (voodoo->verts[va].sRed - voodoo->verts[vb].sRed) * dxBC) * 4096.0f); - voodoo->params.startG = (int32_t)(voodoo->verts[va].sGreen * 4096.0f); - voodoo->params.dGdX = (int32_t)(((voodoo->verts[va].sGreen - voodoo->verts[vb].sGreen) * dyBC - (voodoo->verts[vb].sGreen - voodoo->verts[vc].sGreen) * dyAB) * 4096.0f); - voodoo->params.dGdY = (int32_t)(((voodoo->verts[vb].sGreen - voodoo->verts[vc].sGreen) * dxAB - (voodoo->verts[va].sGreen - voodoo->verts[vb].sGreen) * dxBC) * 4096.0f); - voodoo->params.startB = (int32_t)(voodoo->verts[va].sBlue * 4096.0f); - voodoo->params.dBdX = (int32_t)(((voodoo->verts[va].sBlue - voodoo->verts[vb].sBlue) * dyBC - (voodoo->verts[vb].sBlue - voodoo->verts[vc].sBlue) * dyAB) * 4096.0f); - voodoo->params.dBdY = (int32_t)(((voodoo->verts[vb].sBlue - voodoo->verts[vc].sBlue) * dxAB - (voodoo->verts[va].sBlue - voodoo->verts[vb].sBlue) * dxBC) * 4096.0f); + voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f); + voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f); + voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f); + voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f); + voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f); + voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f); + voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f); + voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f); + voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f); } if (voodoo->sSetupMode & SETUPMODE_ALPHA) { - voodoo->params.startA = (int32_t)(voodoo->verts[va].sAlpha * 4096.0f); - voodoo->params.dAdX = (int32_t)(((voodoo->verts[va].sAlpha - voodoo->verts[vb].sAlpha) * dyBC - (voodoo->verts[vb].sAlpha - voodoo->verts[vc].sAlpha) * dyAB) * 4096.0f); - voodoo->params.dAdY = (int32_t)(((voodoo->verts[vb].sAlpha - voodoo->verts[vc].sAlpha) * dxAB - (voodoo->verts[va].sAlpha - voodoo->verts[vb].sAlpha) * dxBC) * 4096.0f); + voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f); + voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f); + voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f); } if (voodoo->sSetupMode & SETUPMODE_Z) { - voodoo->params.startZ = (int32_t)(voodoo->verts[va].sVz * 4096.0f); - voodoo->params.dZdX = (int32_t)(((voodoo->verts[va].sVz - voodoo->verts[vb].sVz) * dyBC - (voodoo->verts[vb].sVz - voodoo->verts[vc].sVz) * dyAB) * 4096.0f); - voodoo->params.dZdY = (int32_t)(((voodoo->verts[vb].sVz - voodoo->verts[vc].sVz) * dxAB - (voodoo->verts[va].sVz - voodoo->verts[vb].sVz) * dxBC) * 4096.0f); + voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f); + voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f); + voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f); } if (voodoo->sSetupMode & SETUPMODE_Wb) { - voodoo->params.startW = (int64_t)(voodoo->verts[va].sWb * 4294967296.0f); - voodoo->params.dWdX = (int64_t)(((voodoo->verts[va].sWb - voodoo->verts[vb].sWb) * dyBC - (voodoo->verts[vb].sWb - voodoo->verts[vc].sWb) * dyAB) * 4294967296.0f); - voodoo->params.dWdY = (int64_t)(((voodoo->verts[vb].sWb - voodoo->verts[vc].sWb) * dxAB - (voodoo->verts[va].sWb - voodoo->verts[vb].sWb) * dxBC) * 4294967296.0f); + voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f); + voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f); + voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f); voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW; voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; } if (voodoo->sSetupMode & SETUPMODE_W0) { - voodoo->params.tmu[0].startW = (int64_t)(voodoo->verts[va].sW0 * 4294967296.0f); - voodoo->params.tmu[0].dWdX = (int64_t)(((voodoo->verts[va].sW0 - voodoo->verts[vb].sW0) * dyBC - (voodoo->verts[vb].sW0 - voodoo->verts[vc].sW0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dWdY = (int64_t)(((voodoo->verts[vb].sW0 - voodoo->verts[vc].sW0) * dxAB - (voodoo->verts[va].sW0 - voodoo->verts[vb].sW0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f); + voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f); voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW; voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX; voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY; } if (voodoo->sSetupMode & SETUPMODE_S0_T0) { - voodoo->params.tmu[0].startS = (int64_t)(voodoo->verts[va].sS0 * 4294967296.0f); - voodoo->params.tmu[0].dSdX = (int64_t)(((voodoo->verts[va].sS0 - voodoo->verts[vb].sS0) * dyBC - (voodoo->verts[vb].sS0 - voodoo->verts[vc].sS0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dSdY = (int64_t)(((voodoo->verts[vb].sS0 - voodoo->verts[vc].sS0) * dxAB - (voodoo->verts[va].sS0 - voodoo->verts[vb].sS0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[0].startT = (int64_t)(voodoo->verts[va].sT0 * 4294967296.0f); - voodoo->params.tmu[0].dTdX = (int64_t)(((voodoo->verts[va].sT0 - voodoo->verts[vb].sT0) * dyBC - (voodoo->verts[vb].sT0 - voodoo->verts[vc].sT0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dTdY = (int64_t)(((voodoo->verts[vb].sT0 - voodoo->verts[vc].sT0) * dxAB - (voodoo->verts[va].sT0 - voodoo->verts[vb].sT0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f); + voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f); + voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f); voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS; voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX; voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY; @@ -3873,18 +3880,18 @@ static void triangle_setup(voodoo_t *voodoo) } if (voodoo->sSetupMode & SETUPMODE_W1) { - voodoo->params.tmu[1].startW = (int64_t)(voodoo->verts[va].sW1 * 4294967296.0f); - voodoo->params.tmu[1].dWdX = (int64_t)(((voodoo->verts[va].sW1 - voodoo->verts[vb].sW1) * dyBC - (voodoo->verts[vb].sW1 - voodoo->verts[vc].sW1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dWdY = (int64_t)(((voodoo->verts[vb].sW1 - voodoo->verts[vc].sW1) * dxAB - (voodoo->verts[va].sW1 - voodoo->verts[vb].sW1) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f); + voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f); } if (voodoo->sSetupMode & SETUPMODE_S1_T1) { - voodoo->params.tmu[1].startS = (int64_t)(voodoo->verts[va].sS1 * 4294967296.0f); - voodoo->params.tmu[1].dSdX = (int64_t)(((voodoo->verts[va].sS1 - voodoo->verts[vb].sS1) * dyBC - (voodoo->verts[vb].sS1 - voodoo->verts[vc].sS1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dSdY = (int64_t)(((voodoo->verts[vb].sS1 - voodoo->verts[vc].sS1) * dxAB - (voodoo->verts[va].sS1 - voodoo->verts[vb].sS1) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startT = (int64_t)(voodoo->verts[va].sT1 * 4294967296.0f); - voodoo->params.tmu[1].dTdX = (int64_t)(((voodoo->verts[va].sT1 - voodoo->verts[vb].sT1) * dyBC - (voodoo->verts[vb].sT1 - voodoo->verts[vc].sT1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dTdY = (int64_t)(((voodoo->verts[vb].sT1 - voodoo->verts[vc].sT1) * dxAB - (voodoo->verts[va].sT1 - voodoo->verts[vb].sT1) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f); + voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f); + voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f); } voodoo->params.sign = (area < 0.0);